Recursion inside let function

I got confused about how def and let variables bind in different ways. Can someone explain to me why this works:

(def leven (memoize (fn [xy] (cond (empty? x) (count y) (empty? y) (count x) :else (min (+ (leven (rest x) y) 1) (+ (leven x (rest y)) 1) (+ (leven (rest x) (rest y)) (if (= (first x) (first y)) 0 1)) ) ))) ) 

But when I try to declare a function, since it does not compile:

 (def leven (let [l (memoize (fn [xy] (cond (empty? x) (count y) (empty? y) (count x) :else (min (+ (l (rest x) y) 1) (+ (lx (rest y)) 1) (+ (l (rest x) (rest y)) (if (= (first x) (first y)) 0 1)) ) ) ))] (lxy) ) ) 

EDIT: This works using the technique shown by Ankur.

 (defn leven [xy] (let [l (memoize (fn [fxy] (cond (empty? x) (count y) (empty? y) (count x) :else (min (+ (ff (rest x) y) 1) (+ (ffx (rest y)) 1) (+ (ff (rest x) (rest y)) (if (= (first x) (first y)) 0 1)) ) ) )) magic (partial ll)] (magic xy) ) ) 
+7
source share
2 answers

Below is an example to do what you requested. I use factorial for simplicity only and added println in factorial to make sure memoization is working fine

 (let [fact (memoize (fn [fx] (println (str "Called for " x)) (if (<= x 1) 1 (* x (ff (- x 1)))))) magic (partial fact fact)] (magic 10) (magic 11)) 

First calculate factorial 10, and then 11, in which case he should not call factorial again within 10 to 1, as this was remembered.

 Called for 10 Called for 9 Called for 8 Called for 7 Called for 6 Called for 5 Called for 4 Called for 3 Called for 2 Called for 1 Called for 11 39916800 
+7
source

The let form binds the names in series, so in the second function definition, the name l does not exist when you try to access it. You can use letfn (with some minor modifications) or give a specific function a name and refer to it instead, for example:

 (def leven (let [l (memoize (fn SOME-NAME [xy] (cond (empty? x) (count y) (empty? y) (count x) :else (min (+ (SOME-NAME (rest x) y) 1) (+ (SOME-NAME x (rest y)) 1) (+ (SOME-NAME (rest x) (rest y)) (if (= (first x) (first y)) 0 1))))))] l)) 

As you may have noticed, I am changing the return from let to l , since that is what you want to bind leven . (lxy) was problematic because it only referenced bindings locally to a function and was not accessible to let .

+6
source

All Articles