2017-03-13 76 views
0

我正在研究計劃中的作業MetaCircular評估者,並且我需要允許用戶通過將其添加到表中來安裝特殊的表單。這個想法是,當用戶輸入諸如(square 5)之類的東西時,評估者將查找名爲square的表格。如果找到,它將返回lambda聲明,如(lambda (x) (* x x))計劃 - 作爲壞功能對象的Lambda

當代碼返回lambda語句時出現問題。我收到以下錯誤信息:

Error: Bad function object:(lambda (x) (* x x)) 

真是個奇怪的是,我可以傳遞參數到從我的表中檢索功能,它只是我在之前定義的過程體作爲拉姆達聲明,不作爲以lambda

開頭的列表僅供參考,以下代碼不起作用。 exp會像(install-special-form 'square (lambda (x) (* x x))),所以在這種情況下,name計算結果爲squarefunc計算爲(lambda (x) (* x x))

(define (install-eval exp) 
    (define name (cadadr exp)) 
    (define func (caddr exp)) 
    (if (special-form-lookup (list name func)) 
     #f 
     (begin 
     (append! special-forms-table (list name func)) 
     name))) 

下面是一些代碼,不工作:

(define (install exp-list) 
    (append! special-forms-table exp-list)) 
(install (list 'square (lambda (x) (* x x)))) 

我猜我的問題是,當使用不起作用的代碼時,lambda被評估爲報價,而不是實際的lambda?如何獲得我的用戶輸入以存儲可以檢索和使用的實際lambda聲明?

回答

1

您可能將lambda存儲爲符號列表,而不是實際的過程。這就是爲什麼這是行不通的:

(define f '(lambda (x) (* x x))) 
(f 10) 
=> Error: Bad function object: (lambda (x) (* x x)) 

先嚐試評價它:

((eval f) 10) 
=> 100 
+0

工作完美!謝謝! – JazzBullets

+0

而在一個使用'eval'的解釋器中,自由變量的工作原理是什麼? – Sylwester

1

當您返回列表(lambda (x) (* x x))你不能與主機應用它,因爲它會像做('(lambda (x) (* x x)) 5)。嘗試一下。你會得到同樣的錯誤。

當Scheme計算特殊形式(lambda (x) (* x x))時,它會返回一個閉包對象以及它創建時的環境。當你打電話給它時,它會運行與該環境的身體,並添加bingind到x。這需要在您的口譯員中進行模擬,因此通常(lamba (args ...) body)通常評估爲(closure-tag (args ...) environment body)。你的申請需要這些能夠在正確的環境下對身體打電話eval。奧斯卡建議使用eval從長遠來看將不起作用,因爲您將無法在eval的解釋器中關閉,如果您確實擺脫了這種情況,我會認爲它是作弊行爲。