定义带括号和不带括号的名称之间的语义差异是什么?

时间:2014-10-18 19:37:41

标签: scheme

(虽然这确实是一个简单的问题,但我发现有时候我作为初学者编写Scheme程序时会犯一些常见的错误。)

我对define特殊表格感到困惑。情况如下:

(define num1
  2)

(define (num2)
  2)

我发现在没有括号的情况下我调用num2并且程序失败时经常发生这种情况。我通常最终花费数小时才找到原因。

通过阅读r5rs,我意识到这个定义没有括号,例如num1是一个变量;虽然用括号定义,例如num2,是一个没有形式参数的函数。

然而,我仍然对a"变量"之间的差异感到模糊。和"功能"。

从emacs lisp背景中,我只能将上述差异与emacs lisp中的类似想法联系起来:

  

在Emacs Lisp中,符号可以尽可能附加一个值   附加了一个函数定义。 [here]

问题:这是理解方案中封闭和非封闭定义之间差异的正确方法吗?

3 个答案:

答案 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,它指的是通过计算表达式返回的值。在后一种情况下,每次评估时。

相关问题