Scheme 方案:附加到本地环境

Scheme 方案:附加到本地环境,scheme,lisp,racket,Scheme,Lisp,Racket,比方说,我想通过定义对象符号,然后将方法和字段附加到该对象,在Scheme中实现“声明性”对象系统。在这样做的同时,我想利用这个对象的本地环境,在方法中正确地绑定它的字段(稍后添加),例如(一个非常“黑在一起”的示例): 不要介意愚蠢的调度机制和硬编码的“localmethod1”:(也不要介意,在定义调度程序时x可能不可用。 首先,我在define中使用define时遇到了问题(define放置错误)。 那么:如何确保lambda中的x绑定到正确的x(在myobj内部),而不是全局环境中的某个

比方说,我想通过定义对象符号,然后将方法和字段附加到该对象,在Scheme中实现“声明性”对象系统。在这样做的同时,我想利用这个对象的本地环境,在方法中正确地绑定它的字段(稍后添加),例如(一个非常“黑在一起”的示例):

不要介意愚蠢的调度机制和硬编码的“localmethod1”:(也不要介意,在定义调度程序时x可能不可用。 首先,我在define中使用define时遇到了问题(define放置错误)。
那么:如何确保lambda中的x绑定到正确的x(在myobj内部),而不是全局环境中的某个x?
最后:有没有一种方法可以改变这种本地的有害元素(闭包,对吧?)


EDIT2:我知道你可以使用本地列表,比如“字段”和“方法”,然后通过调度器对它们进行变异。我想知道是否有可能改变本地环境(由调度lambda生成)。

begin
在Scheme中不会生成本地环境。要引入局部变量,请使用
let
。或者,或者定义一个对象,或者更确切地说定义一个类来构造该对象,如
lambda
-procedure,它将充当构造函数。这将解决您的前两个问题

变异:您可以通过使用正确的分派方法进行变异。比如说,

(define (make-object init-val)
  (define x init-val)
  (define (dispatch msg)
    (cond ((eq? msg 'inc)
           (lambda (y)
             (set! x (+ x y))))
          ((eq? msg 'x)
           x)
          (else
           (error "Unknown msg"))))
  dispatch)

> (define obj (make-object 10))
> (obj 'x)
10
> ((obj 'inc) 20)
> (obj 'x)
30

提供了如何使对象具有本地状态的良好示例。

在Scheme中开始
不会生成本地环境。要引入局部变量,请使用
let
。或者,或者定义一个对象,或者更确切地说定义一个类来构造该对象,如
lambda
-procedure,它将充当构造函数。这将解决您的前两个问题

变异:您可以通过使用正确的分派方法进行变异。比如说,

(define (make-object init-val)
  (define x init-val)
  (define (dispatch msg)
    (cond ((eq? msg 'inc)
           (lambda (y)
             (set! x (+ x y))))
          ((eq? msg 'x)
           x)
          (else
           (error "Unknown msg"))))
  dispatch)

> (define obj (make-object 10))
> (obj 'x)
10
> ((obj 'inc) 20)
> (obj 'x)
30
提供了如何使用本地状态创建对象的良好示例。

您的意思是:

在定义dispatcher期间,x可能不可用

然后你会问:

然后:如何确保lambda中的x绑定到正确的x(在myobj内部),而不是全局环境中的某个x

简单的回答是:你不能

原因是(例如,请参见):

Scheme是一种具有块结构的静态范围语言。在这方面,它类似于阿尔戈尔语和帕斯卡语,不同于除普通Lisp之外的大多数其他Lisp方言

Scheme是静态范围的(而不是动态绑定的)这一事实意味着在调用过程时扩展(并变为当前)的环境是创建过程的环境(即在其中计算过程的定义lambda表达式),不是调用过程的环境。由于所有其他方案绑定表达式都可以用过程表示,因此这决定了所有绑定的行为方式

(我的重点)

你是说:

在定义dispatcher期间,x可能不可用

然后你会问:

然后:如何确保lambda中的x绑定到正确的x(在myobj内部),而不是全局环境中的某个x

简单的回答是:你不能

原因是(例如,请参见):

Scheme是一种具有块结构的静态范围语言。在这方面,它类似于阿尔戈尔语和帕斯卡语,不同于除普通Lisp之外的大多数其他Lisp方言

Scheme是静态范围的(而不是动态绑定的)这一事实意味着在调用过程时扩展(并变为当前)的环境是创建过程的环境(即在其中计算过程的定义lambda表达式),不是调用过程的环境。由于所有其他方案绑定表达式都可以用过程表示,因此这决定了所有绑定的行为方式


(我的重点)

当你知道要构造什么时,你就可以构造对象。我想尝试这样一种想法,即对象是声明的,但随后会添加字段和方法。因此,在本例中(以您的示例为例),x甚至可能还不存在,所以您不能使用set!x(…)直接。在这种情况下怎么办?(也更新了问题)。我知道您可能会列出两个字段和方法列表并使用这种方法,但我对本地环境突变更感兴趣。好的,我知道您想要什么。原则上,这是可能的(查看Scheme解释器实现),但我还没有看到任何Scheme实现会提供“本地”过程环境作为第一类对象。MIT Scheme提供了一流的顶级环境,但这对于您的目的来说似乎太重了。@如果您在更新中写入您知道如何使用列表等内容,那么,您只需替换direct
set,带有间接的
(set字段!…)
,它将使用结构变异原语,如
set car
设置cdr并通过名称(字符串)标识字段。当您知道要构造什么时,您可以构造对象。我想尝试这样一种想法,即对象是声明的,但随后会添加字段和方法。因此,在本例中(以您的示例为例),x甚至可能还不存在,所以您不能使用set!x(…)直接。在这种情况下怎么办?(也更新了问题)。我知道您可能会列出两个字段和方法列表并使用这种方法,但我对本地环境突变更感兴趣。好的,我知道您想要什么。原则上,这是可能的(查看Scheme解释器实现),但我还没有看到任何Scheme实现会提供“本地”过程环境作为第一类对象。麻省理工学院的方案提供了一流的顶级环境,但这对于你们的目的来说似乎太重了