2013-06-26 23 views
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)))) 

有沒有人知道爲什麼在計劃中無法做到這一點?

+1

您需要查看DrRacket中LET的語法定義。 Common Lisp示例是有效的,但我不會在我的代碼中使用它。 –

+0

@Reiner Joswig你爲什麼不在代碼中使用它? –

+1

我會用CLOS代替。上面的使用使得調試變得更加困難,並且它防止了編譯器將DEFUN表單識別爲函數定義。在這裏面,DEFUN不再是頂級形式。 –

回答

10

您無法在Scheme中定義頂級以外的頂級綁定。 (並且在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-incfmy-decf定義發送到外部define-values,這是真正的頂級定義發生的地方。

+1

作爲我曾經對我說過的老師:「Scheme是一個現代的Lisp」。 –

+1

+1爲迄今最好的方式:) – Khaledvic

3

克里斯的解決方案是什麼,我會在這種情況下使用,但這裏的‘讓我們在拉姆達’,它可以派上用場,如果你增加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) 
0

不太優雅,但非常簡單:根據其是Scheme還是CL,定義頂級變量,然後將它們set!setf放入let內部的lambdas。