在MIT Scheme/Racket中,值可以既是运算符又是操作数吗?i、 e.(兰姆达(y)(y))

在MIT Scheme/Racket中,值可以既是运算符又是操作数吗?i、 e.(兰姆达(y)(y)),scheme,racket,currying,sicp,Scheme,Racket,Currying,Sicp,对于函数foo6,给出计算结果为3的过程的当前应用程序 (define foo6 (lambda (x) (x (lambda (y) (y y))))) 我定义了一个foo7来查看最后一行是如何工作的 (define foo7 (lambda (y) (y y))) 是否存在既可以是运算符又可以是操作数的“y” 编辑:问题应改为: 是否有一些“y”既可以是运算符也可以是操作数,不会导致错误或无限循环 问题取自计算机程序(SICP)样本编程作业的结构和解释: 来自“介绍性作业”

对于函数foo6,给出计算结果为3的过程的当前应用程序

(define foo6
  (lambda (x)
    (x (lambda (y) (y y)))))
我定义了一个foo7来查看最后一行是如何工作的

(define foo7 (lambda (y) (y y)))
是否存在既可以是运算符又可以是操作数的“y”

编辑:问题应改为:

是否有一些“y”既可以是运算符也可以是操作数,不会导致错误或无限循环

问题取自计算机程序(SICP)样本编程作业的结构和解释:

来自“介绍性作业”,练习11:

  • PDF版本:
  • PS(原版):

  • 是的。Scheme和Racket都是Lisp1,这意味着它们只有一个名称空间,因此。变量
    v
    可以是包括过程在内的任何值

    第二次看到类似于
    (lambda(y)(y))
    的内容,从应用的方式来看,很明显
    y
    是一个什么类型的过程。对于过程以外的任何其他值,它将以应用程序错误结束:

    ((lambda (y) (y y)) 5)
    ; ERROR: application: 5 is not a procedure
    
    这个过程本身可能会期望它本身是一个参数,所以我们可以假设某种ω或z组合式

    我们有更高阶的过程,您可以将函数作为值传递到操作数位置,然后将它们放在运算符位置使用:

    (define (times n p)
      (lambda (arg)
        (let loop ((n n) (acc arg))
          (if (<= n 0)
              acc
              (loop (sub1 n) (p acc))))))
    
    (define double (lambda (v) (+ v v)))
    (define test (times 3 double))
    (test 5) ; ==> 40
    
    Z组合子是语言的Y组合子。它可以在不改变环境的情况下进行自我参考。

    是的

    (define (foobar n)
      ((foo6
        (lambda (u) (u (lambda (y)
                         (lambda (n)
                           (if (zero? n)
                               1
                               (* n ((y y) (- n 1)))))))))
       n))
    
    是吗?我是说,为什么?因为

    因此,
    foo6
    的参数应该是一个函数
    x
    期望
    u
    ,这样
    uy=yy
    。所以我们给它这样的函数

      (foobar n)
    =
       ((foo6 x) n)
    =
        ((x u) n)               
    =
         ((u y) n)                 so, x = (lambda (u) (u (lambda (y) (lambda (n) ...))))
    =
          ((y y) n)              so, y = (lambda (y) (lambda (n) ...))
    =
           ((lambda (n)
              (if (zero? n)
                1
                (* n ((y y) (- n 1)))))
            n)
    
    随后,当需要计算/if
    ((y)(-n1))
    时,作为
    (y)
    应用程序的结果,再次到达相同的
    (lambda(n)…
    函数,并且在需要计算/if
    ((y)(-n1)1))
    时再次使用该函数

    试试看!
    (foobar 5)
    评估的目的是什么?(乌鲁巴诺)

    所以,一切都合适。你看见我了吗



    (lambda(y)(y))
    实际上有一个名称:它是“Ucombinator”。

    foo7是否可以应用一些不会导致错误的y值?i、 e.“(foo7)”请注意,问题要求的是(当前)应用foo6,而不是定义。谢谢回复@Sylvester@注意模糊是的。您可以执行
    (foo7 foo7)
    。它将产生一个无限循环,但没有错误。这是我尝试的第一件事,但对foo6的应用没有帮助。我将编辑问题以反映这一点。再次感谢@Sylvester@注意模糊你确实看到了我的编辑,你的代码是Z组合器的一部分,可以完美地计算斐波那契?@sylvester现在读一下编辑,它很吸引人!我从未遇到过Z组合器。尽管如此,还不清楚如何使用Z组合符来导出一个当前应用的foo6,以计算为3。也许我最初的问题(在标题中)在弄清楚如何最终使foo6评估为3时可能没有用处?
      (foo6 x)
    =
      (x (lambda (y) (y y))
    =
      (x u)             where u = (lambda (y) (y y))
                        i.e. (u y) = (y y)
    
      (foobar n)
    =
       ((foo6 x) n)
    =
        ((x u) n)               
    =
         ((u y) n)                 so, x = (lambda (u) (u (lambda (y) (lambda (n) ...))))
    =
          ((y y) n)              so, y = (lambda (y) (lambda (n) ...))
    =
           ((lambda (n)
              (if (zero? n)
                1
                (* n ((y y) (- n 1)))))
            n)