1
votes

I have the following issue: When i type in functions in REPL everyting works fine and I don't get any exceptions, but when I take the input value for my clojure function from an input field in html I get clojure.lang.LazySeq cannot be cast to clojure.lang.IFn exception for this part of my code:

(apply map + 
       (for [i (range (count frequencies-of-words-reviews))]
         (for [j (range (count tokens))]
           (if (= ((nth frequencies-of-words-reviews i)
                     (nth tokens j))
                  nil)
             0
             1)))

The input value has been taken from input field correctly, so that's not the problem... Does anyone have an idea of what could the problem be? Thank you in advice, I'm quite new to clojure and web programming in clojure.

2
Could you please provide example values for frequencies-of-words-reviews and tokens? (Also, this would be a lot easier to read if you wrote your code on multiple lines with proper indentation.)bsvingen
(def frequencies-of-words-reviews ({"charging" 1, "excellent" 2, "bit" 1, "great" 1} , {"bought" 1, "daughter" 1}) (def tokens ("charging" "excellent" "bit" "great" "bought" "daughter") )Savas
I'm sorry for the bad indentation. :/Savas
You are missing a parenthesis here. If I add it at the end, frequencies-of-words-reviews evaluates to nil - I'm assuming that's not the value you want?bsvingen
You have several lists here. The way a list is evaluated is that the first value of the list is taken as a function, and the rest are parameters to that function. That does not seem to be what you want here? For instance, "charging" is not a function?bsvingen

2 Answers

0
votes

Indenting the code helps to reveal part of what's wrong. Unfortunately, you haven't stated what you're trying to accomplish, so it's hard to provide a full answer. I'm going to make some guesses, and I think that even if I guess incorrectly, what I say will help you sort out the problems.

@bsvingen is right that there's a missing parenthesis. However, my guess is that the problem is that there's an extra parenthesis before the first nth. Don't you want = to apply to the two expressions containing nth? it doesn't. Instead, the first one is evaluated, and Clojure expects it to produce a function, because it appears at the beginning of a list. If we fix that, what results is:

(apply map + 
       (for [i (range (count frequencies-of-words-reviews))]
         (for [j (range (count tokens))]
           (if (= (nth frequencies-of-words-reviews i)
                  (nth tokens j))
             nil)
             0
             1)))

However, that can't be what you intend, because in this case, the if expression returns nil if the condition is true, and if the condition is false, if does its default for the "else", which is to return nil. So the if expression returns nil no matter what. However, this value is ignored anyway, as is the 0. The code as I've rewritten is returns 1 for each element. So that's not what you intend, either.

Next, you don't need two for's. You can use

(for [i ...
      j ...]
  ...)

My guess is that what you're trying to test with = is whether the keys of frequencies-of-words-reviews are equal to the strings in tokens, and that you're trying to count the cases in which you get equality. In that case, the code could look like this, with the addition of keys in the 4th line.

(apply map + 
       (for [i (range (count frequencies-of-words-reviews))
             j (range (count tokens))]
         (if (= (nth (keys frequencies-of-words-reviews) i)
                (nth tokens j))
           0
           1)))

(Note that the only way I was able to keep track of all of the parentheses and make sure that they were correct was by letting my editor format the code. When the resulting indentation isn't right, I know that I've done something wrong.)

However, there's still a problem. You define frequencies-of-words-reviews to be a list whose first element is a hash map. This would usually produce an error, because Clojure assumes the first element of a list is a function. However, it turns out that hash maps are also treated as functions, so there's no error, but the result is that frequencies-of-words-reviews has the value nil. The solution is to quote the list:

(def frequencies-of-words-reviews
  '({"charging" 1, "excellent" 2, "bit" 1, "great" 1}, {"bought" 1, "daughter" 1}))

or use a vector:

(def frequencies-of-words-reviews 
  [{"charging" 1, "excellent" 2, "bit" 1, "great" 1}, {"bought" 1, "daughter" 1}])

You need to do the same thing with tokens:

(def tokens ["charging" "excellent" "bit" "great" "bought" "daughter"])

However, given my guesses, I think you need to merge the two hash maps. This will require some care if they have some of the same keys. merge-with might be useful for this. I'm simply going to merge the two maps:

(def frequencies-of-words-reviews
  (merge {"charging" 1, "excellent" 2, "bit" 1, "great" 1}, {"bought" 1, "daughter" 1}))

Finally, if you're trying to sum the values that result, you don't need apply map +, you need apply + or reduce +. The result is:

(apply + 
       (for [i (range (count frequencies-of-words-reviews))
             j (range (count tokens))]
         (if (= (nth (keys frequencies-of-words-reviews) i)
                (nth tokens j))
           0
           1))

This sums a bunch of 0's and 1's, and produces the result 30.

Other tips:

It would be more idiomatic to avoid indexing into sequences at all. Look at filter, some, set, etc.

0
votes

The most immediate problem is this part:

((nth frequencies-of-words-reviews i)...

Calling the function "nth" will return a value I'll call X. Then you have something like:

(X (nth tokens j))

where clojure is trying to interpret X as a function (implemented in the JVM as the interface clojure.lang.IFn).

The first time through the loop, the index i will be the map {"charging" 1, "excellent" 2, "bit" 1, "great" 1}. While this may or may not be what you intended, it doesn't seem to match the exception.

If you could paste together a working 5-line example and paste it here we could probably solve the problem quickly. Right now, I suspect that what you have in your editor and what you have pasted into your REPL or here are slightly different.