Functional programming 使用scheme本身实现内置的scheme函数begin(),相同的代码在MIT-scheme和Racket中的行为不同?
我正在阅读r5rs scheme标准,发现begin()实际上是一种库语法,这意味着它可以由scheme本身定义,该标准在标准末尾给出了一个实现 我遵循R5R使用如下定义语法实现了begin():Functional programming 使用scheme本身实现内置的scheme函数begin(),相同的代码在MIT-scheme和Racket中的行为不同?,functional-programming,scheme,racket,r5rs,Functional Programming,Scheme,Racket,R5rs,我正在阅读r5rs scheme标准,发现begin()实际上是一种库语法,这意味着它可以由scheme本身定义,该标准在标准末尾给出了一个实现 我遵循R5R使用如下定义语法实现了begin(): (define-syntax mybegin (syntax-rules () ((mybegin expr) expr) ((mybegin expr1 expr2 ...) (let ((x ex
(define-syntax mybegin
(syntax-rules ()
((mybegin expr) expr)
((mybegin expr1 expr2 ...)
(let ((x expr1))
(mybegin expr2 ...)))))
然后我尝试使用函数实现它,下面是我的代码:
(define begin-func
(lambda (expr1 expr2)
((lambda (x) expr2) expr1)))
以下是我的测试用例:
(define x 3)
(define y 3)
(mybegin
(set! x 4)
(set! x 5))
(begin-func
(set! y 4)
(set! y 5))
我在MIT-SCHEME和Racket中使用#lang SCHEME运行代码,
在MIT-SCHEME和Racket中x都是5,然而,在MIT-SCHEME中y是4,但在Racket中是5
所以,我的问题是:
begin
是一种特殊形式,它按顺序计算每个元素,并计算到最后一个表达式。在纯功能方案中,您永远不需要使用begin
,但在没有将begin
作为特殊形式或嵌入lambda
表单或亲属的方案中,可以以功能方式获得与begin
类似的功能。只有一个例外,那就是define
<顶级begin中的code>define将在全局范围内定义,而模拟将使用过程按顺序进行评估,define
将仅成为局部绑定,当过程超出范围时,该绑定将失效
begin
必须定义为语法,因为如果执行以下过程:
(define (mybegin . args)
...)
调用mybegin
时,所有参数都将按照特定于实现的顺序进行计算。报告说,评估需要是后续的,这样您就不会看到一个实现一次得到4个,另一次得到5个,但是您会看到,对于同一个过程,每次都会发生其中一个。不能保证在两个不同的过程中也会以相同的顺序进行评估,但许多方案实现通常以相同的顺序进行评估
Racket总是按顺序计算参数,这是可以的,因为报告说你可以随心所欲,而麻省理工学院至少有时会按相反的顺序进行计算。@benrudgers没有纯函数式方案,但你可以用纯函数式的方式对方案进行编程。他确实在第一个问题中提到了功能方案,并避免在
let
中使用显式begin
,而是嵌套let
表单,就好像let
只处理尾部调用一样。这使得这个问题更有趣,因为它表明我们可以用宏来降低函数式语言的功能。