4

我必须编写一个面向对象的计数器。首先,函数 make-object 应该用内部状态 0 实例化对象 a 和 b。然后调用 'methods' :inc、:dec 和 :res(增加、减少、重置)。它应该如下所示:

> (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))

我尝试了以下使用“:inc”而不是“first”来调用方法:

(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))))))

这就是我想要的。

4

1 回答 1

3

这几乎可以工作了。

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

和表格( ... )周围有一个额外的东西。你需要删除它。CONDvar

此外first(etc) 将是一个变量引用。你需要打电话(first var)

一旦你开始工作,你可能想要以不同的方式编写你的代码。如果MAKE-OBJECT将返回一个函数而不是三个函数的列表怎么办。那怎么能行?

下一个问题

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

上面没有意义。你想调用函数FIRST的结果var。然后这将返回一个函数,然后通过FUNCALL.

于 2013-07-05T11:48:42.073 回答