lambda Scheme 中的 if 语句

if statement in lambda Scheme

我是一个新的阴谋家。我只想问我是否可以在 lambda 中包含 if 语句?例如,(lambda (x) (if e1 e2 e3))。我不明白为什么不,但如果我这样写,我的程序就会一直失败。

非常感谢!

这是我的代码 here.I我正在尝试使用高阶函数实现过滤器作为练习。由于@sepp2k 回答说在 lambda 中包含 ifs 完全没问题,我猜这是我使用 foldr 的问题?

如果有人能对此提供一些见解以帮助我理解它的工作方式,我将不胜感激!

(define filter (f xs)
  (if (null? xs) '()
     (foldr (lambda (elem ys) ((if (f elem) (cons elem ys)
                                   (cons '() ys)))) '() xs)))

是的,在 lambda 中使用 ifs 是完全有效的。如果您的程序失败,那一定是因为其他原因。

当然我们可以在lambda里面使用if,事实上,任何有效的表达式都可以放在lambda里面。您的代码中有更严重的错误:

  1. 最里面的 if 表达式周围有额外的(不必要的)括号。 Scheme 会将它们解释为一个函数应用程序,而这不是你想要在这里做的
  2. if表达式的else是错误的,你只需要不加修改地传递累加器
  3. 函数定义不正确

也可以简化整个函数,不需要最外层的if并且可以改进缩进。试试这个:

(define (filter f xs)
  (foldr (lambda (elem ys)
           (if (f elem)       ; if the predicate is true
               (cons elem ys) ; then `cons` element to accumulator
               ys))           ; otherwise leave accumulator alone
         '()
         xs))

它按预期工作:

(filter even? '(1 2 3 4 5 6))
=> '(2 4 6)

if 调用的额外括号。方案重载分组 (list of expressions) 和函数调用 (+ 2 2)。 FWIW,您也可以使用 foldl,因为 foldr 占用 O(|elements of the input|) 内存。

再深入一点,lambda 就是所谓的 "special form" 方案。这意味着他们遵守不同的评估规则。我之所以提出这个,是因为它让我们对 scheme 的一个关键特征有了一些了解:一切都只是一种形式。 define?特殊形式。 lambda?特殊形式。如果你真的喜欢,没有什么是你不能自己写的。这意味着有很多特殊形式,即使它们看起来 automagic/baked-in,它们也没有任何深奥的警告。

此外,仅供将来参考,这里有一些供您策划的精华:MIT Scheme Reference (lambdas), Racket Guide (Pairs and Lists)