I'm new the the Clojure world and to functional programming in general. I'm trying to write a function that computes the probability of a particular list of words occurring given a vocabulary (just a list of words) and a set of probabilities (the probabilities of each of those words occurring). I'm using a simplified bag-of-words model and each outcome is assumed to be independent.
For example, given:
- Vocabulary (associated probability): sleep (0.3), dog (0.09), a (0.2), the (0.05), cow (0.17), boat (0.04), everything (0.15)
- Sentence:
(list 'the 'dog 'boat)
I want it to calculate (0.05) * (0.09) * (0.04) = 0.00018
I already have a function that fetches the probability of each individual word and it works as expected. I'll paste it here for reference:
(defn lookup-probability [w outcomes probs]
(if (not= w (first outcomes)) ;;if the current element is not equal to the word we're looking for...
(lookup-probability w (rest outcomes) (rest probs)) ;;...keep cycling through the vocabulary
(first probs) ;;once we find the right word, fetch the corresponding entry in the probability list
)
)
Here's the part that I'm confused about:
(def sentenceprobs '()) ;;STEP 1
(defn compute-BOW-prob [sentence vocabulary probabilities]
(if (not(empty? sentence))
(def sentenceprobs (conj sentenceprobs (lookup-probability (first sentence) vocabulary probabilities)) ;;STEP 2
(compute-BOW-prob (rest sentence) vocabulary probabilities) ;;STEP 3
)
(product sentenceprobs) ;;STEP 4 (the product function just multiplies all the elements of a list together)
)
)
Here's my general strategy:
- Start out by defining an empty list "sentenceprobs" where I will store the probabilities of each word in the sentence
- If the sentence is nonempty, then add the probability of the first word to the list "sentenceprobs"
- Recursively call the function on the rest of the sentence (minus the word we just found the probability for, ofc)
- Once the sentence is empty, i.e. we have fetched the probability for every word, return the product of all the elements in "sentenceprobs"
This works fine if I only want to use the function once. However, if I want to call it multiple times, sentenceprobs still contains all the probabilities from the previous call. The function will still run, but it just gives me the wrong probability (something much much tinier). So I tried to reset the value of the sentenceprobs at the very end of my function to make it "reusable":
(def sentenceprobs '())
(defn compute-BOW-prob [sentence vocabulary probabilities]
(if (not(empty? sentence))
(def sentenceprobs (conj sentenceprobs (lookup-probability (first sentence) vocabulary probabilities))
(compute-BOW-prob (rest sentence) vocabulary probabilities)
)
(product sentenceprobs)
)
(def sentenceprobs '()) ;; <---THIS IS WHAT I ADDED
)
When I do this, the function doesn't return anything at all. In a sense, that is expected since the function has to return an operation on this list, so making it empty would probably mess that up. But I thought since I'm recursing and returning a value before we ever get out of the if-statement, this wouldn't be a problem. I guess I was mistaken haha.
I've done some poking around on the internet, and it seems like this isn't how def works in Clojure, but I have no idea how to fix it. Does anyone know how I could make this work? Thanks so much.