Search code examples
clojure

Nested Let in Anglican Clojure


I am new to Anglican, the Probabilistic programming language in Clojure. I am trying to use a nested let construct in Clojure.

The following defqueryruns without any issues.

(defquery panda3 [p1]
  (let [p2 (sample 
              (categorical
                {:speA (/ 1 2),
                 :speB (/ 1 2)}))]
    (if (= p2 :speA)
      ( let [p3 (sample 
              (categorical
                {:twins (/ 1 10),
                 :notwins (/ 9 10)}))] 

      )
      ( let [p3 (sample 
              (categorical
                {:twins (/ 2 10),
                 :notwins (/ 8 10)}))]

      ))

    p2))

However, instead of returning the value of p2 at the end, if I try to return the value of p3, it returns errors.

(defquery panda3 [p1]
  (let [p2 (sample 
              (categorical
                {:speA (/ 1 2),
                 :speB (/ 1 2)}))]
    (if (= p2 :speA)
      ( let [p3 (sample 
              (categorical
                {:twins (/ 1 10),
                 :notwins (/ 9 10)}))] 

      )
      ( let [p3 (sample 
              (categorical
                {:twins (/ 2 10),
                 :notwins (/ 8 10)}))]

      ))

    p3))

The idea is to assign p3 based on the outcome of p2. However, I am unable to do so. What am I doing wrong?

Thanks in advance,


Solution

  • As the comment said, you need to return p3 from within the scope of the let in which it is defined:

    (defquery panda3 [p1]
      (let [p2 (sample 
                  (categorical
                    {:speA (/ 1 2),
                     :speB (/ 1 2)}))]
        (if (= p2 :speA)
          (let [p3 (sample 
                     (categorical
                       {:twins (/ 1 10),
                        :notwins (/ 9 10)}))] 
            p3)
          (let [p3 (sample 
                     (categorical
                       {:twins (/ 2 10),
                        :notwins (/ 8 10)}))]
            p3 ))))
    

    Update

    As amalloy points out, the 2nd part could be:

      ; return the result of `(sample (categorical ...))` called
      ; with one of the 2 maps
      (if (= p2 :speA)
        (sample 
          (categorical
            {:twins (/ 1 10),
             :notwins (/ 9 10)} ))
        (sample 
          (categorical
            {:twins (/ 2 10),
             :notwins (/ 8 10)} )))
    

    or even

      ; return the result of `(sample (categorical ...))` called
      ; with one of the 2 maps
      (sample 
        (categorical
          (if (= p2 :speA)
            {:twins (/ 1 10),
             :notwins (/ 9 10)}
            {:twins (/ 2 10),
             :notwins (/ 8 10)} )))