3

Common Lisp では、次のコードのスニペットを (SBCL で) 構文エラーを通知されることなく評価できます。

(let ((x 0))
   (defun my-incf (y)
     (setf x (+ x y)))
   (defun my-decf (y)
     (setf x (- x y))))
MY-DECF

CL-USER> (my-incf 1)
1
CL-USER> (my-incf 1)
2
CL-USER> (my-decf 1)
1
CL-USER> (my-decf 1)
0

対応するコードのスキーム スニペットを評価しようとすると (DrRacket で):

(let ((x 0))
  (define (my-incf y)
    (set! x (+ x y)))
  (define (my-decf y)
    (set! x (- x y))))

構文エラーを通知します。

begin (possibly implicit): no expression after a sequence of internal definitions in: (begin (define (my-incf y) (set! x (+ x y))) (define (my-decf y) (set! x (- x y))))

これがSchemeで実行できない理由を誰かが知っていますか?

4

3 に答える 3

10

スキームでは、トップレベルの外でトップレベルのバインディングを定義することはできません。(そして、 a の内部letは間違いなくトップレベルの外にあります --- 代わりに、トップレベルにエクスポートされない内部定義がありました。) ただし、 を使用するdefine-valuesと、必要なことを実行できます。 :

(define-values (my-incf my-decf)
  (let ((x 0))
    (values (lambda (y)
              (set! x (+ x y))
              x)
            (lambda (y)
              (set! x (- x y))
              x))))

ただし、コードを読みやすくするために、内部定義を引き続き使用できます。

(define-values (my-incf my-decf)
  (let ((x 0))
    (define (my-incf y)
      (set! x (+ x y))
      x)
    (define (my-decf y)
      (set! x (- x y))
      x)
    (values my-incf my-decf)))

両方の長所。:-) この場合、valuesは内部my-incfおよびmy-decf定義を外部define-valuesに送信します。ここで、実際のトップレベルの定義が行われます。

于 2013-06-26T23:48:16.530 に答える
3

この場合、Chris のソリューションを使用しますが、「Let over Lambda」の精神に基づいた別のソリューションを次に示します。これは、x の操作数を増やす場合に役立ちます。

(define inc-dec
  (let ((x 0))
    (lambda (msg y)
      (case msg
        ((incf) (set! x (+ x y)))
        ((decf) (set! x (- x y)))
        (else (error "wot?")))
      x)))


(inc-dec 'incf 1)
(inc-dec 'incf 1)
(inc-dec 'decf 1)
(inc-dec 'decf 1)
于 2013-06-27T08:43:41.857 に答える
0

エレガントではありませんが、非常に単純です。トップレベルの変数を定義してから、Schemeset!かCL かに応じて、setf内部からラムダに変換します。let

于 2013-06-28T07:05:16.433 に答える