2013-04-17 21 views
2

此問題與範圍類似於:In R6RS Scheme, is there a way to get the current environment for use with eval?,但我想進一步探討一下,並且詢問如何解決此類問題。在計劃中使用lambda中的let變量

我的問題進一步混淆了,在我的情況下,'(+ x y)是一個任意的未評估lambda表達式。未評估,因爲它可能包含對變量的一部分的調用(因爲Scheme不相信程序將在包含那些變量的環境中被調用,當前變量不包含這些變量時,它會引發未定義的標識符錯誤) 。所以問題變成:我如何重構我的代碼,使得這個範圍噩夢不再是問題?我希望在調用lambda時仍然可以使用let中的環境變量。

我使用Pretty Big

的目的是在方案創建類。我的做法,到目前爲止是相當大的(沒有雙關語意),但看起來像:

(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))))) 
+0

我不確定你想要做什麼,你有一些示例代碼? –

+0

@ ChrisJester-Young我想他想弄清楚一個方法,讓'(let((x 1))(eval'(* x 2)))''返回'2'。 –

+0

@Maxwell完全正確 – JPatnode

回答

3

這沒有按」 t實現所有你想到的語法,但它可能會說明實現它所需的技術。

(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)。關閉是調度員。這些方法是在調度程序中定義的lambda,因此實例變量與方法在同一範圍內。

+0

這正是我需要讓我走向正確的方向。謝謝! – JPatnode

0

如果可以的話使let eval的一部分,然後它將工作。下面是一個例子:

類似的東西(但更簡單)對您的代碼不工作:

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

製作讓EVAL的一部分,使得它的工作原理:

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