有正常的吗;“设置”;Scheme语言中的函数(非特殊形式)?

有正常的吗;“设置”;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)应

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)
应该返回什么?如果它应该返回
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在