Salut,
I am a Lisp beginer.
I'd like to do something like that :
(defclass laclasse ()
((list-of-float :initarg :list-of-float
:initform ()
:accessor list-of-float)
(x1 :initarg :x1
:initform 2.0
:accessor x1
:type float)
(x2 :initarg :x2
:initform 3.0
:accessor x2
:type float)
))
(defmethod compute-x ((c laclasse) (t float))
(+ (* t (x1 c)) (x2 c))
)
(defmethod compute-all ((c laclasse))
(setf (list-of-float c) (mapcar #'compute-x c (list-of-float c)))
)
compute-all does not work as expected, I think just because mapcar wants a 1
argument function.
What can I do ?
Bernard Tatin
"Bernard Tatin" <·············@univ-orleans.fr> writes:
> I am a Lisp beginer.
Bienvenue!
> I'd like to do something like that :
...
> (defmethod compute-all ((c laclasse))
> (setf (list-of-float c) (mapcar #'compute-x c (list-of-float c)))
> )
>
> compute-all does not work as expected, I think just because mapcar wants a 1
> argument function.
The problem that you are running into is that mapcar wants LISTs of the
arguments to the mapping function. In most cases, the argument lists
should be the same size, although mapcar can handle different length
lists -- it just iterates over the smaller list:
(mapcar #'+ '(1 2 3 4 5) '(1 1 1)) => (2 3 4)
In your call, you have a single object c instead of a list. That will
break the code.
> What can I do ?
There are two possibilities. The simplest and most efficient would be
to use an anonymous function (a lambda expression) which will capture
the value of the free variable c (this is called making a closure):
(defmethod compute-all ((c laclasse))
(setf (list-of-float c)
(mapcar #'(lambda (f) (compute-x c f))
(list-of-float c))))
Now this has the effect of producing a function of one variable, but
mapcar could handle more than just this one.
*** You can stop reading now ***
A fancier solution (which I don't actually recommend using) would be to
make an appropriate list for the first argument. This is clever
(obscure?) in that it creates a circular list for the first argument
(effectively an infinitely long list) and relies on mapcar stopping
after it exhausts the finite list.
(Note that if you want to try this by typing in the Lisp listener, make
sure you set *print-circle* to T so that the listener doesn't crash
trying to print a circular data structure)
(defmethod compute-all ((c laclasse))
(let ((list-of-c (list c))) ;; Make a list.
(setf (cdr list-of-c) list-of-c) ;; Make it circular.
(setf (list-of-float c)
(mapcar #'compute-x list-of-c (list-of-float c)))))
--
Thomas A. Russ, USC/Information Sciences Institute ···@isi.edu
"Bernard Tatin" <·············@univ-orleans.fr> writes:
> Salut,
>
> I am a Lisp beginer.
>
> I'd like to do something like that :
>
> (defclass laclasse ()
> ((list-of-float :initarg :list-of-float
> :initform ()
> :accessor list-of-float)
> (x1 :initarg :x1
> :initform 2.0
> :accessor x1
> :type float)
> (x2 :initarg :x2
> :initform 3.0
> :accessor x2
> :type float)
> ))
>
> (defmethod compute-x ((c laclasse) (t float))
> (+ (* t (x1 c)) (x2 c))
> )
Seems you're redefining t, here... not a good idea :-)
> (defmethod compute-all ((c laclasse))
> (setf (list-of-float c) (mapcar #'compute-x c (list-of-float c)))
> )
>
> compute-all does not work as expected, I think just because mapcar wants a 1
> argument function.
>
> What can I do ?
mapcar wants an n-argument function, where n equals the number
of lists passed to it. If you want to pass other arguments to the
function, you could use a closure:
(defmethod compute-all ((c laclasse))
(setf (list-of-float c)
(mapcar #'(lambda (f)
(compute-x c f)) ; c comes from enclosing scope
(list-of-float c))))
--
Raymond Wiker, Orion Systems AS
+47 370 61150
"Bernard Tatin" <·············@univ-orleans.fr> writes:
> (defmethod compute-x ((c laclasse) (t float))
> (+ (* t (x1 c)) (x2 c))
> )
>
> (defmethod compute-all ((c laclasse))
> (setf (list-of-float c) (mapcar #'compute-x c (list-of-float c)))
> )
>
> compute-all does not work as expected, I think just because mapcar wants a 1
> argument function.
Wrap it into a #'(LAMBDA ...) [has been answered in more detail in
another post already].
Also, the name T of your second formal argument to COMPUTE-X is
problematic: T is a constant and cannot be bound. Use another name
there.
Cheers,
Axel
* Bernard Tatin wrote:
> compute-all does not work as expected, I think just because mapcar wants a 1
> argument function.
I'm assuming (from the defclass...) that this isn't homework.
You want to do something like this:
(defmethod compute-all ((c ...))
...
(mapcar #'(lambda (x)
(compute-x c x)) ...)
...)
(Note your definition of COMPUTE-X won't work because you have an
argument called T.)
--tim