Reputation: 41
I have to program an object-oriented counter. First the function make-object should instantiate the objects a and b with internal state 0. Then the 'methods' :inc, :dec and :res (increase, decrease, reset) are called. It should look like this:
> (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
My solution so far looks like this:
(defun make-object ()
(let ((counter 0))
(list #'(lambda () (incf counter))
#'(lambda () (setf counter 0))
#'(lambda () (decf counter)))))
With
(setq a (make-object) b (make-object))
I can instantiate a and b and the methods are called with
(funcall (first a))
(funcall (second b))
(funcall (third a))
I tried the following to call the methods with ":inc" instead of "first":
(defun myfuncall (var fun)
(funcall ((cond ((equal fun ":inc") first)
((equal fun ":res") second)
((equal fun ":dec") third))
var)))
but there's the error
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]
Can anyone help me please? How do I make funcall do the right thing for me?
Found the solution.
(defun make-object ()
(let ((count 0))
(lambda (msg)
(case msg
((:inc) (incf count))
((:dec) (decf count))
((:res) (setq count 0))))))
This does what I wanted.
Upvotes: 4
Views: 175
Reputation: 139251
That's almost working.
(defun myfuncall (var fun)
(funcall ((cond ((equal fun ":inc") first)
((equal fun ":res") second)
((equal fun ":dec") third))
var)))
There is an extra ( ... )
around the COND
and the var
form. You need to remove that.
Also first
(etc) would be a variable reference. You need to call (first var)
.
Once you got that working, you may want to write your code differently. What if MAKE-OBJECT
would return a single function and not a list of three functions. How could that work?
Next problem
((equal fun ":inc") 'first var)
Above makes no sense. You want to call the function FIRST
on the result of var
. This then would return a function, which then gets called via FUNCALL
.
Upvotes: 3