首页 文章

方案:附加到当地环境

提问于
浏览
1

比如说,我想在Scheme中实现“声明式”对象系统,方法是定义对象符号,然后将方法和字段附加到该对象 . 在这样做的时候,我想利用这个对象的本地环境来正确绑定它们在方法中的字段(稍后会添加),例如(一个非常“混乱”的例子):

(define myobj 
(begin
    (define x 5) ; some local field (hard-coded for example)
    (define (dispatch m d)
        (cond ((eq? m 'add-meth) (define localmethod1 d))
              ((eq? m 'inv-meth) (localmethod1 d))))
    dispatch
))
(myobj 'add-meth (lambda (y) (+ y x)) ;want this to bind to x of myobj
(myobj 'inv-meth 3) ;8

不要介意愚蠢的调度机制和硬编码"localmethod1" :)还要注意,在调度程序的定义过程中可能无法使用x . 首先,我在使用define in define(Bad define placement)时遇到问题 .
那么:如何确保lambda中的x绑定到正确的(myobj内部)而不是全局环境中的某些x?
上一篇:有没有办法改变这样的本地化(闭合,对吗?)?

EDIT2:我知道您可以使用“字段”和“方法”等本地列表进行此操作,然后由调度程序对其进行变更 . 我想知道是否有可能改变当地环境(由调度lambda产生) .

2 回答

  • 1

    你是说:

    在调度员定义期间,x可能不可用

    然后你问:

    那么:如何确保lambda中的x绑定到右边的(myobj内部)而不是全局环境中的某个x?

    简短的回答是:你做不到 .

    原因是(参见例如Mit-Scheme manual):

    Scheme是一种具有块结构的静态范围语言 . 在这方面,它就像Algol和Pascal,与Lisp的大多数其他方言不同,除了Common Lisp . Scheme是静态作用域(而不是动态绑定)的事实意味着在调用过程时扩展(并变为当前)的环境是创建过程的环境(即,过程定义的lambda表达式被评估) ),而不是调用过程的环境 . 因为所有其他Scheme绑定表达式都可以用过程表示,所以这决定了所有绑定的行为方式 .

    (强调我的)

  • 3

    Scheme中的 begin 不会产生本地环境 . 要引入局部变量,请使用 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
    

    SICP, Chapter 3提供了如何使对象具有本地状态的良好示例 .

相关问题