有正常的吗;“设置”;Scheme语言中的函数(非特殊形式)?
Scheme语言中是否有正常的“set”函数(非特殊形式)或某种实现方法 我想编写如下代码:有正常的吗;“设置”;Scheme语言中的函数(非特殊形式)?,scheme,Scheme,Scheme语言中是否有正常的“set”函数(非特殊形式)或某种实现方法 我想编写如下代码: (映射(lambda(var) (设置变量0) "(a b c) 它可以为列表中的变量赋值(这里是‘0’)(这里是‘a’、‘b’和‘c’)。不,看看为什么没有考虑这样的事情: (define (mutant var val) (let ((x 1)) (set var val) x)) (mutant-horror (λ () (set 'x 3))) 现在,(突变体'x3)应
(映射(lambda(var)
(设置变量0)
"(a b c)
它可以为列表中的变量赋值(这里是‘0’)(这里是‘a’、‘b’和‘c’)。
不,看看为什么没有考虑这样的事情:(define (mutant var val)
(let ((x 1))
(set var val)
x))
(mutant-horror (λ () (set 'x 3)))
现在,(突变体'x3)
应该返回什么?如果它应该返回3
,则:
不能是函数,因为它需要访问set
突变体的词法环境李>
- 此函数的任何合理编译都是不可能的
将设置为一个函数,则灾难随之而来。考虑这个定义:
(define (mutant-horror f)
(let ([x 3])
(f)
x))
现在,您会认为这可以优化为:
(define (mutant-horror f)
(f)
3)
但它不能。因为你可以这样称呼它:
(define (mutant var val)
(let ((x 1))
(set var val)
x))
(mutant-horror (λ () (set 'x 3)))
或者,更一般地说,您可以使用一个函数调用它,该函数最终在从它间接调用的某个函数中的某个地方可能会说(set'x 3)
这意味着任何绑定都无法优化,这是一场灾难。它也至少非常接近于词法范围不可能的含义:如果除了set
,还存在一个名为get
的函数,它检索符号的绑定,那么从本质上讲,您就拥有了动态范围。这反过来又使得尾部调用消除这样的事情至少变得困难,而且可能不可能(事实上,set
可能是自己完成的)
这样的原因就是为什么即使是非常古老的LISP,比如set
确实存在并且表面上起作用,实际上也对编译代码进行了特殊豁免,而set
不起作用(例如,请参见(PDF链接)编译代码和解释代码的语义之间的这种差异是后来Lisp和Lisp相关语言(如CL和Scheme)消除的事情之一
相反,如果您想要Common Lisp的语义,那么
(defun mutant (var val)
(let ((x 1))
(set var val)
x))
将返回1
(除非x
是一个全局(见下文)特殊变量,在这种情况下,它可能会返回其他变量),并且作为一种副作用,修改var
命名的任何符号的值单元格(可能是x
)那么,好吧,Scheme根本就没有这个概念,总的来说这是件好事
请注意,函数的修改版本也适用于局部特殊变量:
(defun mutant/local-special (a b)
(let ((x 1))
(declare (special x))
(set a b)
x))
但是,在这种情况下,你总是知道有一个特殊的绑定发生,因为你总是可以看到声明。 不,看看为什么没有考虑这样的事情:
(define (mutant var val)
(let ((x 1))
(set var val)
x))
(mutant-horror (λ () (set 'x 3)))
现在,(突变体'x 3)
应该返回什么?如果它应该返回3
,那么:
set
不能是函数,因为它需要访问突变体的词法环境
- 此函数的任何合理编译都是不可能的
如果你想把代码> SET/COD>作为一个函数,那么灾难就发生了。考虑这个定义:
(define (mutant-horror f)
(let ([x 3])
(f)
x))
现在,您会认为这可以优化为:
(define (mutant-horror f)
(f)
3)
但它不能。因为你可以这样称呼它:
(define (mutant var val)
(let ((x 1))
(set var val)
x))
(mutant-horror (λ () (set 'x 3)))
或者,更一般地说,您可以使用一个函数调用它,该函数最终在从它间接调用的某个函数中的某个地方可能会说(set'x 3)
这意味着任何绑定都不能被优化,这是一场灾难。这至少非常接近于词法范围不可能实现的意思:如果除了set
,还存在一个名为get
的函数,该函数检索符号的绑定,那么从本质上讲,您就拥有了动态范围。这反过来又产生了类似tail的事情-调用消除至少是困难的,而且可能是不可能的(事实上,set
可能是自己完成的)
这样的原因就是为什么即使是非常古老的LISP,比如set
确实存在并且表面上起作用,实际上也对编译代码进行了特殊豁免,而set
不起作用(例如,请参见(PDF链接)编译代码和解释代码的语义之间的这种差异是后来Lisp和Lisp相关语言(如CL和Scheme)消除的事情之一
相反,如果您想要Common Lisp的语义,那么
(defun mutant (var val)
(let ((x 1))
(set var val)
x))
将返回1
(除非x
是一个全局(见下文)特殊变量,在这种情况下,它可能会返回其他变量),并且作为一种副作用,修改var
命名的任何符号的值单元格(可能是x
)那么,好吧,Scheme根本就没有这个概念,总的来说这是件好事
请注意,函数的修改版本也适用于局部特殊变量:
(defun mutant/local-special (a b)
(let ((x 1))
(declare (special x))
(set a b)
x))
但是在这种情况下,您总是知道会发生一个特殊的绑定,因为您总是可以看到声明。当您编写类似于
(map (lambda (var)
(set var 0))
'(a b c))
我的第一个想法是,您尝试累积形式((a0)(b0)(c0))
的无序集
您不能为该语言提供的任何内部数据结构实现自己的setter,因为这意味着要编写scheme函数来修改某些用C实现的数据结构。对于用C实现的数据结构,您需要提供用C编写的setter——假设较低的语言是C
如果您想实现自己的setter,您可以
--检查数据结构是如何实现的,如果它是在scheme中实现的,您将不理解如何修改它
--使用已有的数据结构定义您自己的数据结构,并为其定义setter
变异数据结构的setter在