如何创建一个lambda程序?
How to create a lambda procedures?
我需要使用 Scheme 完成大学课程的作业。我以前从未在 Scheme 中编写过代码,所以我不知道自己在做什么。我们的任务是定义一个匿名函数来计算二次函数的判别式。我将 运行 保留在错误中:“无效的 `define'。任何帮助将不胜感激。
(define roots (lambda(abc))(
(lambda(discriminant))(
list(/(+(-b) discriminant)(*2a))
(/(-(-b) discriminant)(*2a))
)
(sqrt - (*bb)(*4ac))
)
首先,您应该了解一下 Scheme 代码是什么样的;找到一些示例代码(在您的教科书或在线,或在此处关于 SO 的答案中)并注意如何使用括号和 whitespace 。然后效仿。你不能在 Scheme(或任何 Lisp)中任意放置括号或任意删除 whitespace.
例如,在发布的代码中 (-b)
有两处错误。首先,-b
被视为一个符号,而不是b
值的否定。此外,将符号放在括号中表示过程调用;给定一个 s 表达式 (f x)
,f
要么是句法关键字(在这种情况下 (f x)
被解释为宏调用),要么 (f x)
被解释为过程调用.如果它是过程调用并且 f
未绑定到过程,则会引发异常。因此 (-b)
尝试调用名为 -b
的过程,该过程不存在(除非您已定义它),引发异常。您可以使用 (- b)
,在 -
过程和符号 b
之间使用 space;这计算出 b
.
值的否定
类似地,*2a
被解释为符号,而不是表达式;将 *2a
放在括号之间被解释为过程调用。解释器(或编译器)期望 *2a
是一个不带参数的过程。您需要添加 spaces: (* 2 a)
;这被解释为使用参数 2
和 a
.
调用过程 *
(*bb)
和 (*4ac)
有完全相同的问题。第二种情况很有趣,因为当它被正确书写时,它说明了前缀表示法的优点之一。由于 *
是关联的,因此多个值相乘的顺序无关紧要。要用前缀表示法天真地表达 4 * a * c
,您可以编写 (* 4 (* a c))
,明确排序乘法。您也可以将其写为 (* (* 4 a) c)
,以不同的顺序相乘。相乘的顺序无关紧要,所以只要您的语言支持这种表示法,您也可以只写 (* 4 a c)
。事实证明,Scheme 和其他 Lisp 确实支持这种表示法。
已发布代码中 s 表达式表示法的另一个问题(在解决上述问题后):(sqrt - (* b b) (* 4 a c))
。这是试图在参数 -
、(* b b)
和 (* 4 a c)
上调用 sqrt
过程。但是 sqrt
不是高阶过程(即它不将过程作为参数),实际上它只接受一个参数。它的目的是将 -
过程应用于参数 (* b b)
和 (* 4 a c)
,在求平方根之前减去它们:(sqrt (- (* b b) (* 4 a c)))
.
第一个 lambda
表达式的形式参数列表仅包含一个参数:abc
。和以前一样,这是一个错误。目的是定义三个参数:不要吝啬 spaces:(lambda (a b c))
.
另一个重要的问题是 lambda
表达式中存在语法错误:(lambda (a b c))
没有正文,但是 lambda
表达式 must 在它的主体中至少有一个表达式。这可能是为了包装后面的 lambda
表达式。类似地,内部 lambda
表达式缺少它的主体。它可能是为了包装后面的 (list ;;...)
形式。
完成后,内部 lambda
表达式本身位于一对括号内,将表达式 (sqrt (- (* b b) (* 4 a c)))
作为其参数。这是 let
绑定的 lambda
形式。因此,内部 lambda
接受一个参数 discriminant
,并评估作为其主体的 list
形式。由于内部 lambda
表达式本身出现在 s 表达式的第一个位置,它是过程调用的一部分,然后这个内部匿名过程在其参数上被调用,将 discriminant
绑定到值通过评估该参数获得,即 (sqrt (- (* b b) (* 4 a c)))
。这一切都发生在外部 lambda
内部,它采用三个参数 a
、b
和 c
。因此,root
是一个接受三个参数并返回根列表的函数,在将判别计算的结果绑定到 discriminant
之后(作为一种既简化根表达式又确保判别式只需计算一次)。
这是修复后的代码。请注意,我只添加了一些 space 并添加或移动了一些括号;没有其他改变:
(define roots
(lambda (a b c)
((lambda (discriminant)
(list (/ (+ (- b) discriminant) (* 2 a))
(/ (- (- b) discriminant) (* 2 a))))
(sqrt (- (* b b) (* 4 a c))))))
注意这是什么样子的。在 Lisps 中,你几乎不应该让括号单独挂在行上,你应该总是在参数之间放置一个 space。请记住,一切都是过程调用。
这是一个交互示例。请注意,您 可以 将负数表示为 -1
而不是 (- 1)
(如果您愿意,您可以这样做)。您不能使用变量 -b
.
来表示负值
> (roots 1 0 -1)
(1 -1)
> (roots 1 8 15)
(-3 -5)
我需要使用 Scheme 完成大学课程的作业。我以前从未在 Scheme 中编写过代码,所以我不知道自己在做什么。我们的任务是定义一个匿名函数来计算二次函数的判别式。我将 运行 保留在错误中:“无效的 `define'。任何帮助将不胜感激。
(define roots (lambda(abc))(
(lambda(discriminant))(
list(/(+(-b) discriminant)(*2a))
(/(-(-b) discriminant)(*2a))
)
(sqrt - (*bb)(*4ac))
)
首先,您应该了解一下 Scheme 代码是什么样的;找到一些示例代码(在您的教科书或在线,或在此处关于 SO 的答案中)并注意如何使用括号和 whitespace 。然后效仿。你不能在 Scheme(或任何 Lisp)中任意放置括号或任意删除 whitespace.
例如,在发布的代码中 (-b)
有两处错误。首先,-b
被视为一个符号,而不是b
值的否定。此外,将符号放在括号中表示过程调用;给定一个 s 表达式 (f x)
,f
要么是句法关键字(在这种情况下 (f x)
被解释为宏调用),要么 (f x)
被解释为过程调用.如果它是过程调用并且 f
未绑定到过程,则会引发异常。因此 (-b)
尝试调用名为 -b
的过程,该过程不存在(除非您已定义它),引发异常。您可以使用 (- b)
,在 -
过程和符号 b
之间使用 space;这计算出 b
.
类似地,*2a
被解释为符号,而不是表达式;将 *2a
放在括号之间被解释为过程调用。解释器(或编译器)期望 *2a
是一个不带参数的过程。您需要添加 spaces: (* 2 a)
;这被解释为使用参数 2
和 a
.
*
(*bb)
和 (*4ac)
有完全相同的问题。第二种情况很有趣,因为当它被正确书写时,它说明了前缀表示法的优点之一。由于 *
是关联的,因此多个值相乘的顺序无关紧要。要用前缀表示法天真地表达 4 * a * c
,您可以编写 (* 4 (* a c))
,明确排序乘法。您也可以将其写为 (* (* 4 a) c)
,以不同的顺序相乘。相乘的顺序无关紧要,所以只要您的语言支持这种表示法,您也可以只写 (* 4 a c)
。事实证明,Scheme 和其他 Lisp 确实支持这种表示法。
已发布代码中 s 表达式表示法的另一个问题(在解决上述问题后):(sqrt - (* b b) (* 4 a c))
。这是试图在参数 -
、(* b b)
和 (* 4 a c)
上调用 sqrt
过程。但是 sqrt
不是高阶过程(即它不将过程作为参数),实际上它只接受一个参数。它的目的是将 -
过程应用于参数 (* b b)
和 (* 4 a c)
,在求平方根之前减去它们:(sqrt (- (* b b) (* 4 a c)))
.
第一个 lambda
表达式的形式参数列表仅包含一个参数:abc
。和以前一样,这是一个错误。目的是定义三个参数:不要吝啬 spaces:(lambda (a b c))
.
另一个重要的问题是 lambda
表达式中存在语法错误:(lambda (a b c))
没有正文,但是 lambda
表达式 must 在它的主体中至少有一个表达式。这可能是为了包装后面的 lambda
表达式。类似地,内部 lambda
表达式缺少它的主体。它可能是为了包装后面的 (list ;;...)
形式。
完成后,内部 lambda
表达式本身位于一对括号内,将表达式 (sqrt (- (* b b) (* 4 a c)))
作为其参数。这是 let
绑定的 lambda
形式。因此,内部 lambda
接受一个参数 discriminant
,并评估作为其主体的 list
形式。由于内部 lambda
表达式本身出现在 s 表达式的第一个位置,它是过程调用的一部分,然后这个内部匿名过程在其参数上被调用,将 discriminant
绑定到值通过评估该参数获得,即 (sqrt (- (* b b) (* 4 a c)))
。这一切都发生在外部 lambda
内部,它采用三个参数 a
、b
和 c
。因此,root
是一个接受三个参数并返回根列表的函数,在将判别计算的结果绑定到 discriminant
之后(作为一种既简化根表达式又确保判别式只需计算一次)。
这是修复后的代码。请注意,我只添加了一些 space 并添加或移动了一些括号;没有其他改变:
(define roots
(lambda (a b c)
((lambda (discriminant)
(list (/ (+ (- b) discriminant) (* 2 a))
(/ (- (- b) discriminant) (* 2 a))))
(sqrt (- (* b b) (* 4 a c))))))
注意这是什么样子的。在 Lisps 中,你几乎不应该让括号单独挂在行上,你应该总是在参数之间放置一个 space。请记住,一切都是过程调用。
这是一个交互示例。请注意,您 可以 将负数表示为 -1
而不是 (- 1)
(如果您愿意,您可以这样做)。您不能使用变量 -b
.
> (roots 1 0 -1)
(1 -1)
> (roots 1 8 15)
(-3 -5)