2

この質問の範囲は似ています: In R6RS Scheme, is there a way to get the current environment for use with eval? しかし、私はそれをさらに一歩進めて、このような問題をどのように解決するかを尋ねたいと思います.

私の場合'(+ x y)、任意の評価されていないラムダステートメントであるという点で、私の問題はさらに混乱しています。let の一部である変数への呼び出しが含まれている可能性があるため、評価されていません (また、Scheme は、現在の変数が含まれていない環境でプロシージャが呼び出されるとは信じていないため、未定義の識別子エラーが発生します)。 . 問題は、このスコーピングの悪夢がもはや問題にならないように、コードを再構築するにはどうすればよいかということです。ラムダが呼び出されるたびに、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 はフォームのクラス定義です (たとえば、ポイント)

    '(();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インスタンス変数は、クロージャーを保持する字句スコープ ( ) に入ります。クロージャーはディスパッチャーです。メソッドはディスパッチャー内で定義されたラムダであるため、インスタンス変数はメソッドと同じスコープ内にあります。

于 2013-04-17T06:38:59.287 に答える
0

あなたがlet評価の一部を作ることができれば、それはうまくいくでしょう。以下に例を示します。

動作しないコードに似た(しかしより単純な)もの:

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

let を eval の一部にして動作させる:

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