2

这个问题的范围类似于:在 R6RS 方案中,有没有办法让当前环境与 eval 一起使用?但我想更进一步,问你如何补救这样的事情。

我的问题进一步令人困惑,因为在我的情况下'(+ x y)是任意未评估的 lambda 语句。未评估,因为它可能包含对作为 let 一部分的变量的调用(并且由于 Scheme 不相信该过程将在包含这些变量的环境中调用,而当前的环境不包含这些变量,因此它会触发未定义的标识符错误) . 所以问题就变成了:我怎样才能重组我的代码,这样这个范围界定的噩梦就不再是问题了?每当调用 lambda 时,我仍然希望能够使用 let 中的环境变量。

我在用着Pretty Big

目的是在 Scheme 中创建类。到目前为止,我的方法相当大(没有双关语),但看起来像:

    (define (dispatch msg methods args)
      (if (null? methods) (display "Method signature not found.")
          (let (
                (m-name (caar methods))
                (m-args (cadar methods))
                (m-body (caddar methods)))
            (if (and (eq? msg (caar methods)) (eq? (length args) (length (cadar methods))))
                `(lambda ,m-args ,m-body)
                (dispatch msg (cdr methods) args)))))

    (define (build-lets c-def)
      (let (
            (i-vars (cadr c-def))
            (meths (caddr c-def)))
        (eval `(append ',i-vars (list (list 'methods '',meths))))))

    (define (new c-def . args)
      (apply (eval `(lambda ,(map cadr (cadr c-def))
               (let* ,(build-lets c-def)
                 (lambda (msg . args)
                   (letrec ((meth (dispatch msg methods args)))
                     (apply meth args))))))
             args))

其中 c-def 是形式的类 def(比如一个点)

    '(();Name of parent
      ((yvalue y) (xvalue x)) ;Instance variables: (i-var constructor-arg)
      ((getx () xvalue) ;Methods, ((name args body) ...)
       (setx (x) (set! xvalue x)))))
4

2 回答 2

3

这并没有实现您想到的所有语法,但它可能说明了干净地实现它所需的技术。

(define-syntax make-object
  (syntax-rules ()
    [(__ ([ivar ival] ...) ([method-name args body ...] ...))
      (let ([ivar ival] ...)
        (λ (msg . oargs)
          (cond
            [(eq? 'method-name msg)
              (apply (λ args body ...) oargs)] ...
            [else
              (error 'object-system "unknown message" msg)])))]))

(define o (make-object ([xvalue 'x])
                       ([getx () xvalue]
                        [setx (x) (set! xvalue x)])))

(o 'getx) => x
(o 'setx 'blah)
(o 'getx) => blah

诀窍是编写一个使闭包的宏。实例变量进入let包含闭包的词法范围(the)。闭包是调度程序。这些方法是在调度程序中定义的 lambda,因此实例变量与方法在同一范围内。

于 2013-04-17T06:38:59.287 回答
0

如果您可以let参与评估,那么它将起作用。下面是一个例子:

与您的代码类似(但更简单)的东西不起作用:

(define (hello m)
  (let ((msg m))
    (eval '(print msg))))

让 eval 的一部分使它起作用:

(define (hello m)
  (eval `(let ((msg ,m))
           (print msg))))
于 2013-04-17T05:51:37.050 回答