Recursion let函数中的递归
我对def和let如何以不同方式绑定变量感到困惑。有人能给我解释一下为什么会这样:Recursion let函数中的递归,recursion,clojure,let,Recursion,Clojure,Let,我对def和let如何以不同方式绑定变量感到困惑。有人能给我解释一下为什么会这样: (def leven (回忆) (fn[x y] (条件(空?x)(计数y) (空?y)(计数x) :else(最小(+(剩余x)y)1) (+(leven x(rest y))1) (+(leven(rest x)(rest y))(如果(=(first x)(first y))0 1()()()())((first x)40 但当我试图将函数声明为let时,它无法编译: (def leven (让[l(me
(def leven
(回忆)
(fn[x y]
(条件(空?x)(计数y)
(空?y)(计数x)
:else(最小(+(剩余x)y)1)
(+(leven x(rest y))1)
(+(leven(rest x)(rest y))(如果(=(first x)(first y))0 1()()()())((first x)40
但当我试图将函数声明为let时,它无法编译:
(def leven
(让[l(memoize)(fn[x y]
(条件(空?x)(计数y)
(空?y)(计数x)
:else(最小(+(l(剩余x)y)1)
(+(长x(其余y))1)
(+(l(剩余x)(剩余y))(如果(=(第一个x)(第一个y))0 1()()()()))]
(l x y)))
编辑:使用Ankur展示的技术,这项工作很有效
(defn leven[x y]
(让[l(memoize)(fn[f x y]
(条件(空?x)(计数y)
(空?y)(计数x)
:else(最小(+(剩余x)y)1)
(+(fx(剩余y))1)
(+(f(剩余x)(剩余y))(如果(=(第一个x)(第一个y))0 1‘‘‘‘‘‘)
魔术(部分l)]
(魔法x y)))
下面就是这样一个例子,可以满足您的要求。为了简单起见,我使用了factorial,并在factorial中添加了println,以确保备忘录工作正常
(let [fact (memoize (fn [f x]
(println (str "Called for " x))
(if (<= x 1) 1 (* x (f f (- x 1))))))
magic (partial fact fact)]
(magic 10)
(magic 11))
let
表单按顺序绑定名称,因此在第二个函数定义中,当您尝试引用它时,名称l
不存在。您可以使用letfn
(与一些次要mod一起使用),或者为定义的函数指定一个名称,并改为引用该名称,如下所示:
(def leven
(let [l (memoize (fn SOME-NAME [x y]
(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))
您可能会注意到,我将
let
的返回值更改为l
本身,因为这是您想要绑定到leven
的内容。(l x y)
是有问题的,因为它只引用了函数的本地绑定,而不能访问let
函数SOME-NAME在这样使用时是否会失去memoize的好处?您不需要调用函数memoize returns吗,或者在let语句中不可能有递归的memoized函数吗?@onit可以修改定义leven
,通过移动SOME-NAME
作为第一个参数来获得memoized的好处:(fn[SOME-NAME x y]
,然后将对SOME-NAME
的调用替换为(SOME-NAME SOME-NAME…
,最后将返回值l
替换为(部分l)
。非常有趣。因此,您基本上只是将函数作为参数传入,这样编译器就不会因为没有定义它而感到困惑。我现在无法尝试这种方法,但稍后我将尝试这种方法。
(def leven
(let [l (memoize (fn SOME-NAME [x y]
(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))