【问题标题】:Why all the lambdas in The Little Schemer?为什么 The Little Schemer 中的所有 lambda 表达式?
【发布时间】:2011-06-14 06:05:19
【问题描述】:

在从 SICP 学习了一些 Scheme 之后,我开始阅读 The Little Schemer(我觉得很有趣),大约完成了四分之一。我注意到我可以在不使用 lambda 的情况下编写许多(大多数?全部?)解决方案,而 The Little Schemer always 使用它们。例如,第一个定义是

(define atom?
  (lambda (x)
    (and (not (pair? x)) (not (null? x)))))

除非我弄错了,否则可以更简单地写成

(define (atom? x) 
   (and (not (pair? x)) (not (null? x))))

如果我编写无 lambda 解决方案,我是否缺少一些基本的东西?

【问题讨论】:

  • lambda 是 alpha 和 omega

标签: lambda scheme the-little-schemer


【解决方案1】:

最初,define 有一个语法,用于将变量设置为一个值。这就是这些古老(和永恒)书籍中使用的风格。后来,define 得到了一种不同的语法作为快捷方式,这就是您正在使用的。

只是为了好玩,搜索一下你的 Scheme 库,你可能会发现一个将非 lambda 形式扩展为旧的 lambda-heavy 形式的宏。

【讨论】:

  • 并非如此——“新”define 形式自 1978 年第一次修订报告以来一直在该语言中。在书中使用显式 lambda 的选择是一种风格/教学方法。
  • 不知道...但是查看第一版(最初称为“小 LISPer”)于 1974 年发布
【解决方案2】:

我依稀记得一位教授讨论过这样的事情。

我认为使用 lambda 解决方案有两个原因:

第一个纯粹是历史的东西。在某个时间点,这是唯一可行的方法。所以有些人仍然使用这种方法。

第二个是有些人只是喜欢更明确地说明正在创建函数的事实,所以他们喜欢看到 lambda 这个词。

所以我相信选择取决于你个人最喜欢的东西。

【讨论】:

    【解决方案3】:

    Little Schemer 使用伪代码 Scheme(出于教育目的进行简化并独立于实现)。今天的标准 Scheme 有一个 define 的定义,你在其中隐式调用 lambda(参见 http://www.cs.cmu.edu/Groups/AI/html/r4rs/r4rs_7.html)。 Little Schemer 方案非常简单,不包括这种替代形式。

    【讨论】:

      【解决方案4】:

      我非常喜欢 lambda-heavy 的教学风格,因为它使函数创建更加明确,正如 Jay 所说。

      在学习的时候,像atom? 这样的简单函数在顶层是defined。这意味着可以使用您提到的defun-style define 创建函数,甚至更紧凑。

      但是,当您开始将函数用作一等值时,例如,作为map 的参数,您将第一次看到lambda,它可能看起来比实际更奇怪和更神奇是。

      相反,如果您一直在使用 lambda 定义函数,那么看到函数与任何其他值一样,这并不是一个飞跃。它们恰好经常出现在define 的右侧,但与数字或带引号的常量没有什么不同:

      (define x 1)
      (define l '(2 3 4 5))
      (define s (cons x ls))
      (define f (lambda (n) (+ n 2)))
      

      当然,语言支持这两种形式,所以最终归结为样式。对我来说,当你的所有函数都是用lambda 生成时,define 的使用具有吸引人的一致性:第一个参数始终是一个符号,第二个参数只是任何旧表达式。 lambda 就像任何旧表达式一样这一事实是任何函数式程序员学习的最重要的事情之一。

      【讨论】:

      • +1 以与声明变量相同的方式声明函数令人耳目一新:左边是名称,右边是值。
      • 感谢您强调这种方法的一致性方面;它补充了其他解释。
      • “事实上,lambda 就像任何旧表达式一样,这是任何函数式程序员要学习的最重要的事情之一”——直到我阅读了你的解释,我才明白这一点。跨度>
      • @Andrè - 我不认为这是对其他答案的补充。在我看来,这是一个完全不同的答案。好的,如果你问我:-)
      【解决方案5】:

      您可以使用expand(如果支持)查看您的方案将这些快捷方式(宏)扩展为什么:

      mzscheme 4.2.4(带有 DrScheme):

      > (expand '(define (add1 x) (+ 1 x)))
      #<syntax (define-values (add1) (lambda...>
      (define-values
        (add1)
        (lambda (x) (apply + '1 x)))
      

      Chez 方案 8.0:

      > (expand '(define (add1 x) (+ 1 x)))
      (begin
        (set! add1
          (lambda (x)
            (+ 1 x)))
        (void))
      

      lambda 看起来很简单。

      【讨论】:

      • 只是说明宏在Scheme中的重要性,甚至define也是一个宏!
      【解决方案6】:

      当我使用 TLS 时,我正在阅读一些关于 lambda 演算的内容(阅读 Simon Peyton Jones 的“函数式编程语言的实现”;在线免费 pdf)。所以这只是一个猜测,但我相信 TLS 的作者希望你在思考中真正重视 lambda。他们没有说出来,但有一些提示(查看 TLS 的第 107 页)这只是应用 lambda calc 的一个练习。所以也许他们会说,“你在做 lambda 抽象,我的朋友!”

      【讨论】:

        猜你喜欢
        • 2014-08-28
        • 1970-01-01
        • 1970-01-01
        • 2015-10-22
        • 2012-05-16
        • 2011-11-10
        • 2022-01-15
        • 2012-09-06
        • 2014-06-28
        相关资源
        最近更新 更多