在Scheme中的lambda中使用let变量

时间:2013-04-17 04:30:28

标签: scope scheme

这个问题的范围类似于:In R6RS Scheme, is there a way to get the current environment for use with 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)))))

2 个答案:

答案 0 :(得分: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)中。关闭是调度员。这些方法是在调度程序中定义的lambdas,因此实例变量与方法在同一范围内。

答案 1 :(得分:0)

如果你可以使let成为eval的一部分,那么它就可以了。以下是一个例子:

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

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

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

(define (hello m)
  (eval `(let ((msg ,m))
           (print msg))))