Lisp 这段代码的行为如何(funcall中的函数组合)

Lisp 这段代码的行为如何(funcall中的函数组合),lisp,common-lisp,Lisp,Common Lisp,我在lisp中具有以下功能: (defun F(F) #'(lambda (n) (if (zerop n) (funcall F n) (1+ (funcall (F F) (1- n)))))) 如果我调用: (funcall (F #'(lambda (x) (+ 2 x))) 2) 我不明白为什么输出是4 提前感谢因为我们知道参数,我们可以简化函数中的if语句: (funcall (F #'(lambda (x) (+ 2 x)))

我在lisp中具有以下功能:

(defun F(F)
  #'(lambda (n)
      (if (zerop n)
         (funcall F n)
         (1+ (funcall (F F) (1- n))))))
如果我调用:

(funcall (F #'(lambda (x) (+ 2 x))) 2)
我不明白为什么输出是4


提前感谢

因为我们知道参数,我们可以简化函数中的
if
语句:

(funcall (F #'(lambda (x) (+ 2 x))) 2)
(1+ (funcall (F #'(lambda (x) (+ 2 x))) 1))
(1+ (1+ (funcall #'(lambda (x) (+ 2 x)) 0)))
(1+ (1+ 2))
4

前两个转换将
(如果为false A B)
替换为
B
,而第三个转换将
(如果为true A B)
替换为
A
,因为我们知道参数,所以可以简化函数中的
if
语句:

(funcall (F #'(lambda (x) (+ 2 x))) 2)
(1+ (funcall (F #'(lambda (x) (+ 2 x))) 1))
(1+ (1+ (funcall #'(lambda (x) (+ 2 x)) 0)))
(1+ (1+ 2))
4

前两个转换将
(如果为false A B)
替换为
B
,而第三个转换将
(如果为true A B)
替换为
A

首先,解开这两个
F

(defun foo (fun)
  #'(lambda (n)
      (if (zerop n)
          (funcall fun n)
          (1+ (funcall (foo fun) (1- n))))))
现在,你呼叫:

(funcall (foo #'(lambda (x) (+ 2 x))) 2)
我们可以给内部lambda一个名称,我称之为
add-2

(funcall (foo #'add-2) 2)
(Foo#'add-2)
然后返回函数

(lambda (n)
  (if (zerop n)
      (funcall #'add-2 n) ; n is always 0 here
      (1+ (funcall (foo #'add-2) (1- n)))))
使用
2
调用它,它不是
zerop
,因此它是:

(1+ (funcall (foo #'add-2) 1))
我们已经知道
(foo#'add-2)
返回的内容,现在使用
1
调用它,它仍然不是
zerop

(1+ (1+ (funcall (foo #'add-2) 0)))
现在参数是
0
,因此我们进入基本情况:

(1+ (1+ (funcall #'add-2 0)))

现在我们可以看到
foo
创建了一个函数,该函数将
n
添加到调用
(fun 0)

的结果中。首先,解开这两个
F

(defun foo (fun)
  #'(lambda (n)
      (if (zerop n)
          (funcall fun n)
          (1+ (funcall (foo fun) (1- n))))))
现在,你呼叫:

(funcall (foo #'(lambda (x) (+ 2 x))) 2)
我们可以给内部lambda一个名称,我称之为
add-2

(funcall (foo #'add-2) 2)
(Foo#'add-2)
然后返回函数

(lambda (n)
  (if (zerop n)
      (funcall #'add-2 n) ; n is always 0 here
      (1+ (funcall (foo #'add-2) (1- n)))))
使用
2
调用它,它不是
zerop
,因此它是:

(1+ (funcall (foo #'add-2) 1))
我们已经知道
(foo#'add-2)
返回的内容,现在使用
1
调用它,它仍然不是
zerop

(1+ (1+ (funcall (foo #'add-2) 0)))
现在参数是
0
,因此我们进入基本情况:

(1+ (1+ (funcall #'add-2 0)))

现在我们可以看到,
foo
创建了一个函数,该函数将
n
添加到调用
(乐趣0)

的结果中。没有人知道这个函数中发生了什么?请耐心等待。人们通常需要几个小时才能做出响应,尤其是当标记不是[c#]或[java]。;-)有个问题,我可以把线(1+(funcall(F)(1-n))展开如下:(1+(funcall(F(+2x))(1-n)))。这是函数的组合吗?另外,我注意到参数和函数有相同的名称这有什么含义吗?你可能想继续读下去。没有人知道函数中发生了什么?请耐心等待。人们通常需要几个小时才能做出响应,尤其是当标记不是[c#]或[java]。;-)有个问题,我可以把线(1+(funcall(F)(1-n))展开如下:(1+(funcall(F(+2x))(1-n)))。这像是函数的组合吗?我注意到参数和函数有相同的名称,这有什么含义吗?你可能想继续读下去。所以,在(1+(funcall(F)(1-n‘‘‘‘‘)’))行中,在funcall(F)中,他再次调用自己,而不是参数。是吗?@LuisAlves:两者:-)它在它的参数上调用自己。你能解释一下他是如何知道第一个F对应于函数本身而不是参数的吗?我发现这是因为在LISP中,如果在复合形式中第一个元素(汽车)是一个符号,那么它必须作为函数进行评估。如果第一个元素不是符号,那么它必须是lambda表达式。谢谢我还添加了这个链接,并给出了更好的解释,因此,在(1+(funcall(F)(1-n‘‘‘‘)’))行中,在funcall(F)中,他再次调用了自己,而不是参数。是吗?@LuisAlves:两者:-)它在它的参数上调用自己。你能解释一下他是如何知道第一个F对应于函数本身而不是参数的吗?我发现这是因为在LISP中,如果在复合形式中第一个元素(汽车)是一个符号,那么它必须作为函数进行评估。如果第一个元素不是符号,那么它必须是lambda表达式。谢谢我还添加了这个链接,并提供了更好的解释