2013-07-05 22 views
4

我必須編寫一個面向對象的計數器。首先,函數make-object應該實例化內部狀態爲0的對象a和b,然後調用'methods':inc,:dec和:res(增加,減少,重置)。它應該是這樣的:Lisp:基本的面向對象的計數器

> (setq a (make-object) b (make-object)) 
... 
> (funcall a :inc) 
1 
> (funcall a :inc) 
2 
> (funcall a :res) 
0 
> (funcall a :dec) 
-1 
> (funcall b :inc) 
1 

我的解決方法到目前爲止是這樣的:

(defun make-object() 
    (let ((counter 0)) 
    (list #'(lambda() (incf counter)) 
      #'(lambda() (setf counter 0)) 
      #'(lambda() (decf counter))))) 

隨着

(setq a (make-object) b (make-object)) 

我可以實例A和B的方法調用

(funcall (first a)) 
(funcall (second b)) 
(funcall (third a)) 

我試過了E採用調用與方法「:公司」,而不是「第一」:

(defun myfuncall (var fun) 
    (funcall ((cond ((equal fun ":inc") first) 
        ((equal fun ":res") second) 
        ((equal fun ":dec") third)) 
      var))) 

,但有錯誤

While compiling MYFUNCALL : 
In the form (#1=(COND ((EQUAL FUN ":inc") FIRST) 
         ((EQUAL FUN ":res") SECOND) 
         ((EQUAL FUN ":dec") THIRD)) 
      VAR), #1# is not a symbol or lambda expression. 
    [Condition of type CCL::COMPILE-TIME-PROGRAM-ERROR] 

誰能幫助我嗎?我如何讓funcall爲我做正確的事情?


找到解決方案。

(defun make-object() 
    (let ((count 0)) 
    (lambda (msg) 
     (case msg 
     ((:inc) (incf count)) 
     ((:dec) (decf count)) 
     ((:res) (setq count 0)))))) 

這就是我想要的。

+0

不錯的家庭作業工作夥計XXD – fr4nk

回答

3

這幾乎工作。

(defun myfuncall (var fun) 
    (funcall ((cond ((equal fun ":inc") first) 
        ((equal fun ":res") second) 
        ((equal fun ":dec") third)) 
      var))) 

有一個額外的(...)COND周圍和var形式。你需要刪除它。

first(等)將是一個變量的參考。您需要致電(first var)

一旦你得到了這個工作,你可能想要以不同的方式編寫代碼。如果MAKE-OBJECT將返回單個函數而不是三個函數的列表。這有什麼用?

下一個問題是

((equal fun ":inc") 'first var) 

以上是沒有意義的。您想對var的結果調用功能FIRST。然後這將返回一個函數,然後通過FUNCALL調用。

+0

是的,沒錯。我不想那麼做嗎?我想讓'(funcall a:inc)'像'(funcall(first a))'一樣工作。 – user2553444

+0

@ user2553444:是的,'(first a)'是一個有效的函數調用。 ''第一個var'是沒有用的。 –