(虽然这确实是一个简单的问题,但我发现有时候我作为初学者编写Scheme程序时会犯一些常见的错误。)
我对define
特殊表格感到困惑。情况如下:
(define num1
2)
(define (num2)
2)
我发现在没有括号的情况下我调用num2
并且程序失败时经常发生这种情况。我通常最终花费数小时才找到原因。
通过阅读r5rs,我意识到这个定义没有括号,例如num1是一个变量;虽然用括号定义,例如num2,是一个没有形式参数的函数。
然而,我仍然对a"变量"之间的差异感到模糊。和"功能"。
从emacs lisp背景中,我只能将上述差异与emacs lisp中的类似想法联系起来:
在Emacs Lisp中,符号可以尽可能附加一个值 附加了一个函数定义。 [here]
问题:这是理解方案中封闭和非封闭定义之间差异的正确方法吗?
答案 0 :(得分:4)
Scheme中的值和函数没有区别。函数只是一个可以以特定方式使用的值 - 它可以被调用(与其他类型的值相反,例如数字,不能被调用,但可以例如添加,函数不能)。 / p>
括号只是一个句法快捷方式 - 它们是一种更快,更易读(以专家方式)的方式将名称的定义写为包含的变量一个函数:
(define (num)
2)
;is exactly the same as
(define num
(lambda () 2) )
其中第二个应该使得在num
分配的值不是数字更明显地显而易见。
如果你想让函数接受参数,它们要么在括号内(num
之后,例如{1}},要么在(num x y)
之内。括号(例如,lambda
在第二个。
对于初学者来说,大多数教程实际上都没有介绍几个练习的第一个表格,以便将它不分开并且没有'真的提供任何真正的功能。它只是减少程序文本中重复次数的简写。
在Scheme中,所有函数都是值;变量包含任何一个值。
答案 1 :(得分:3)
在Scheme中,与Common Lisp和Emacs Lisp不同,函数和其他值没有不同的命名空间。因此,您引用的声明不适用于Scheme。在Scheme中,符号最多与一个值相关联,该值可能是也可能不是函数。
关于非函数值和返回该值的nullary函数之间的区别:在您的示例中,唯一的区别是,如您所知,必须应用num2
来获取数值和{{ 1}}并非必须且实际上无法应用。
一般来说,num1
和(define foo bar)
之间的区别在于前者现在评估(define (foo) bar)
而bar
则指的是foo
的值bar
评估为,而在后一种情况下,每次使用bar
时评估(foo)
。因此,如果表达式foo
计算成本很高,那么在您调用函数时(而不是每次)都会支付该成本,而不是在定义时。并且,或许更重要的是,如果表达式具有副作用(例如,打印某些内容),则每次调用该函数时都会发生这些效果。副作用是您定义不带参数的函数的主要原因。
答案 2 :(得分:1)
尽管@ sepp2k已回答了这个问题,但我会通过示例更加清晰:
1 ]=> (define foo1 (display 23))
23
;Value: foo1
1 ]=> foo1
;Unspecified return value
注意在第一个中,foo1
在现场进行评估(因此打印),并将评估值分配给名称foo1。它不会一次又一次地评估
1 ]=> (define (foo2) (display 23))
;Value: foo2
1 ]=> foo2
;Value 11: #[compound-procedure 11 foo2]
1 ]=> (foo2)
23
;Unspecified return value
只需foo2
即可返回另一个程序((display 23)
)。执行(foo2)
实际上会对其进行评估。每次被召唤时,它都会重新评估
1 ]=> (foo1)
;The object #!unspecific is not applicable.
foo1是引用值的名称。因此,应用foo1没有意义,因为在这种情况下,值不是一个过程。
所以我希望事情更清楚。简而言之,在前一种情况下,它是一个name
,它指的是通过计算表达式返回的值。在后一种情况下,每次评估时。