Calling another overloaded method in Lisp - lisp

I couldn't find out if this was possible, and just used a (rather ugly) workaround.
Assume we've got a class structure as below:
(defclass a () ())
(defclass b (a) ())
and the method:
(defmethod print-object ((a1 a) stream)
(format stream "instance of A "))
now, I want to call print for 'a then print for 'b, assuming a "type-cast" function exists:
(defmethod print-object ((b1 b) stream)
(prin1 (type-cast b1 'a) stream)
(format stream "instance of B "))
My workaround is to create an object of type a within print-object of b, then call prin1
(defmethod print-object ((b1 b) stream)
(let ((a1 (make-instance 'a)))
(prin1 a1 stream))
(format stream "instance of B "))
I tried coerce and ended up with infinite loop. I just realized I can try using find-method and call-method (would it work?). Or should I try a solution with :around?

COERCE does not work with CLOS objects. You can change the class of an instance with CHANGE-CLASS, but that's usually not a good idea.
CALL-NEXT-METHOD
You can call the next applicable method: CALL-NEXT-METHOD. Note that you can't call a specific method that way, just the next one. Most of the time this is what one would use in CLOS. The task is then during method definition to set up the generic function in such a way, using primary, :around, :before and :after methods, that the right behavior emerges.
Calling specific functions when all else fails
There is an esoteric way to call a specific method:
(funcall (method-function (find-method #'print-object
nil
(list (find-class 'a)
(find-class t))))
(make-instance 'b)
t)
In above code, the function METHOD-FUNCTION is not part of ANSI Common Lisp, but provided in many implementations by the Metaobject Protocol (MOP).

Coerce doesn't create new object because b1 is already has type (subtype) of a already.
All you need is call-next-method:
(defmethod print-object ((a1 a) stream)
(format stream "instance of A "))
(defmethod print-object ((b1 b) stream)
(call-next-method) ; by default same arguments are used: b1 and stream
(format stream "instance of B "))

Following the example on process locks by Sonya Keene (Object-Oriented Programming in COMMON LISP: A Programmer's Guide to CLOS), you can use an :after method
(defmethod print-object ((a1 a) stream)
(format stream "instance of A "))
(defmethod print-object :after ((b1 b) stream)
(format stream "instance of B "))
This will give
CL-USER> (make-instance 'b)
instance of A instance of B

Related

Different initialization, Common Lisp

Can I mimic different constructors in CL?
To elaborate -- in, say, C++, I can make different constructors for the same class depending on what arguments are passed.
Can I do this with CLOS? Probably having different initialize-instances key args or something like that?
One approach to doing this is to have a secondary initialization method:
(defclass myclass ()
((s1 :initarg :s1 :accessor s1)))
(defgeneric initialize-myclass (dispatch class &key))
(defmethod initialize-instance :after ((c myclass) &rest args &key (dispatch 'normal)
&allow-other-keys)
(apply #'initialize-myclass dispatch c args))
(defmethod initialize-myclass ((dispatch (eql 'normal)) (class myclass) &key))
(defmethod initialize-myclass ((dispatch (eql 'special)) (class myclass)
&key x &allow-other-keys)
(print x))
Now you can say
(make-instance 'myclass :dispatch 'special ...)
For instance. Note this is not necessarily a good way of doing it, but it does work, and I've used it. Note also I may have got the keyword-argument defaulting wrong: I never remember where you need to say &allow-other-keys & where you don't, and where the right place to say it is.
The basic problem here is that we want an additional thing to dispatch on: initialize-instance can dispatch on the class of the object being defined, but that's all it can dispatch on. In particular it can't dispatch on one of its keyword arguments because you can't do that in CLOS. But we can take one of its keyword arguments (dispatch here) and 'bless' it as a positional argument to a secondary initialization generic function, which then can dispatch on that argument.
Well, initialize-instance is typically defined as an :after method to run some sort of post-processing once the instance has been initialized through make-instance. What you might do is use parametric polymorphism (dispatching on parameters) and have different methods initialize your instance based on the parameters supplied. Consider the following example:
CL-USER> (defclass my-class ()
((a :initarg :a
:accessor my-class-a)))
#<STANDARD-CLASS COMMON-LISP-USER::MY-CLASS>
CL-USER> (defmethod make-my-class ((a number))
(make-instance 'my-class :a (format nil "Look ma, a number ~a" a)))
#<STANDARD-METHOD COMMON-LISP-USER::MAKE-MY-CLASS (NUMBER) {1016445273}>
CL-USER> (defmethod make-my-class ((a string))
(make-instance 'my-class :a (format nil "Look ma, a string ~a" a)))
#<STANDARD-METHOD COMMON-LISP-USER::MAKE-MY-CLASS (STRING) {10166065C3}>
CL-USER> (make-my-class 10)
#<MY-CLASS {1016690E33}>
CL-USER> (my-class-a *)
"Look ma, a number 10"
CL-USER> (make-my-class "foo")
#<MY-CLASS {1016694CD3}>
CL-USER> (my-class-a *)
"Look ma, a string foo"
As you can see, the method make-my-class dispatches on its argument and initializes my-class accordingly.

in clojure language what <'a> really is

actually i am trying to perfectly understand clojure and particularly symbols
(def a 1)
(type a)
;;=>java.lang.Long
(type 'a)
;;=>clojure.lang.Symbol
I know that type is a function so its arguments get evaluated first so i perfectly understand why the code above work this way .In the flowing code i decided to delay the evaluation using macro
(defmacro m-type [x] (type x))
(m-type a)
;;==>clojure.lang.Symbol
and i am fine with that but what i fail to uderstand is this:
(m-type 'a)
;;=>clojure.lang.Cons
why the type of 'a is a cons
the character ' is interpreted by the clojure reader as a reader-macro which expands to a list containing the symbol quote followed by whatever follows the ', so in your call to (m-type 'a) the 'a is expanding to:
user> (macroexpand-1 ''a)
(quote a)
then calling type on the list (quote a) which is a Cons.
This may be a bit more clear if we make the m-type macro print the arguments as it sees them while it is evaluating:
user> (defmacro m-type [x] (println "x is " x) (type x))
#'user/m-type
user> (m-type 'a)
x is (quote a)
clojure.lang.Cons

'('(LIST) 'NIL 'NIL) should be a lambda expression in (hanoi('('(list)'()'())))

I'm trying to implement the Towers of Hanoi.I'm not printing out anything between my recursive calls yet, but I keep getting an error saying
'('(LIST) 'NIL 'NIL) should be a lambda expression
I've read that the reason this happens is because of a problem with the parenthesis, however I cannot seem to find what my problem is. I think it's happening in the pass-list function when I am trying to call the hanoi function. My code:
(defun pass-list(list)
(hanoi('('(list)'()'())))
)
(defun hanoi ('('(1) '(2) '(3)))
(hanoi '('(cdr 1) '(cons(car 1) 2) '(3)))
(hanoi '('(cons(car 3)1) '(2)'(cdr 3)))
)
This code has many syntax problems; there are erroneous quotes all over the place, and it looks like you're trying to use numbers as variables, which will not work. The source of the particular error message that you mentioned comes from
(hanoi('('(list)'()'())))
First, understand that the quotes in 'x and '(a b c) are shorthand for the forms (quote x) and (quote (a b c)), and that (quote anything) is the syntax for getting anything, without anything being evaluated. So '(1 2 3) gives you the list (1 2 3), and '1 gives you 1. quote is just a symbol though, and can be present in other lists, so '('(list)'()'()) is the same as (quote ((quote (list)) (quote ()) (quote ()))) which evaluates to the list ((quote (list)) (quote ()) (quote ())). Since () can also be written nil (or NIL), this last is the same as ('(list) 'NIL 'NIL). In Common Lisp, function calls look like
(function arg1 arg2 ...)
where each argi is a form, and function is either a symbol (e.g., list, hanoi, car) or a list, in which case it must be a lambda expression, e.g., (lambda (x) (+ x x)). So, in your line
(hanoi('('(list)'()'())))
we have a function call. function is hanoi, and arg1 is ('('(list)'()'())). But how will this arg1 be evaluated? Well, it's a list, which means it's a function application. What's the function part? It's
'('(list)'()'())
which is the same as
'('(list 'NIL 'NIL))
But as I just said, the only kind of list that can be function is a lambda expression. This clearly isn't a lambda expression, so you get the error that you're seeing.
I can't be sure, but it looks like you were aiming for something like the following. The line marked with ** is sort of problematic, because you're calling hanoi with some arguments, and when it returns (if it ever returns; it seems to me like you'd recurse forever in this case), you don't do anything with the result. It's ignored, and then you go onto the third line.
(defun pass-list(list)
(hanoi (list list) '() '()))
(defun hanoi (a b c)
(hanoi (rest a) (cons (first a) b) c) ; **
(hanoi (cons (first c) a) b (rest c)))
If hanoi is supposed to take a single list as an argument, and that list is supposed to contain three lists (I'm not sure why you'd do it that way instead of having hanoi take just three arguments, but that's a different question, I suppose), it's easy enough to modify; just take an argument abc and extract the first, second, and third lists from it, and pass a single list to hanoi on the recursive call:
(defun hanoi (abc)
(let ((a (first abc))
(b (second abc))
(c (third abc)))
(hanoi (list (rest a) (cons (first a) b) c))
(hanoi (list (cons (first c) a) b (rest c)))))
I'd actually probably use destructuring-bind here to simplify getting a, b, and c out of abc:
(defun hanoi (abc)
(destructuring-bind (a b c) abc
(hanoi (list (rest a) (cons (first a) b) c))
(hanoi (list (cons (first c) a) b (rest c)))))

Trouble with Lisp macros

I'm trying to write a macro in Lisp that re-implements let using itself. This is a trivial exercise which has no practical purpose; however after giving a response to a related question, I realized I should probably learn more about macros. They're touted as one of the great things about Lisp, but I rarely use them.
Anyway, here's what I tried first:
(defmacro mylet (args &rest exp) `(let ,args (dolist (x ,exp) x)))
but when I try something like:
(mylet ((a 5) (b 2)) (print (+ a b)))
this throws up an error:
#1=(PRINT (+ A B)) is not a symbol or lambda expression in the form (#1#) .
args (a and b) are set properly, but the print statement doesn't work. I think it's because I'm using two levels of indirection-- referring to a variable that I've created within the macro. But I can't seem to figure out how to fix it! Any ideas?
Your macro expands to:
(LET ((A 5) (B 2))
(DOLIST (X ((PRINT (+ A B)))) X))
which is invalid because ((PRINT (+ A B))) is not a valid expression. There is also an issue that using an interned symbol in macro expansion can lead to variable capture, but that is not directly relevant (read more in PCL).
Using DOLIST here is unnecessary, and compilcated to get right (you would have to convert all subforms to anonymous function in order to stick them in a list, funcall them in sequence and then store the final result in order to conform to PROGN behaviour). You can just use PROGN, or, since LET includes an implicit PROGN, just splice the body using the ,# feature of backquote mechanism:
(defmacro mylet (args &body exp) `(let ,args ,(cons 'progn exp)))
(defmacro mylet (args &body exp) `(let ,args ,#exp))

Common Lisp: non-nil arguments and their names to alist, how?

I am quite new to Common Lisp and programming, and I'm trying to write a certain function that turns all non-nil args into an alist. The only way I can think of so far is:
(let ((temp nil))
(if arg1
(setf temp (acons 'arg1 arg1 nil)))
(if arg2
(setf temp (acons 'arg2 arg2 temp)))
...
(if arg20-ish
(setf temp (acons 'arg20-ish arg20-ish temp)))
(do-something-with temp))
which does not seem very elegant, it would be messy with many arguments and when these need to be changed. I am looking for a smarter way to do this, both for the sake of writing this particular function and for learning how to think in Lisp and/or functional programming.
The tricky part for me is figuring out how to get the names of the arguments or what symbol to use, without hand coding each case. If &rest provided arg names it would be easy to filter out NILs with loop or mapcar, but since it doesn't, I can't see how to "automate" this.
I'm totally interested in other solutions than the one described, if people think this way is unnatural.
Edit: Below is an example of what I am trying to do:
An object is created, with a non-fixed number of data pairs and some tags, e.g.:
user = "someone"
creation-time = (get-universal-time)
color-of-sky = "blue"
temperature-in-celsius = 32
language = "Common Lisp"
...
tags = '("one" "two" "three")
These properties (i.e. key/arg names) could be different each time. The new object will then be added to a collection; I thought the array might work well since I want constant access time and only need a numeric ID.
The collection will hold more and more such custom objects, indefinitely.
I want to be able to quickly access all objects matching any combination of any of the tags used in these objects.
Since the array is supposed to store more and more data over a long period, I don't want to parse every item in it each time I need to search for a tag. Thus I also store the index of each object with a given tag in a hash-table, under the tag name. I have written this function, what I find difficult is figuring out how to collect the data and turn it into an alist or anything that I can easily parse, index, and store.
This macro will define a function that turns its non-nil arguments into an alist bound during execution of the body:
(defmacro defnamed (fun-name alist-sym (&rest args) &body body)
`(defun ,fun-name (,#args)
(let ((,alist-sym))
,#(mapcar
(lambda (s)
`(when ,s
(push (cons ',s ,s) ,alist-sym)))
(reverse args))
,#body)))
Demonstration:
(defnamed make-my alist (a b c)
alist)
(make-my 1 NIL 3)
=> ((A . 1) (C . 3))
Here's a sort of solution using macros:
(defmacro named-args (fun-name alist-sym (&rest syms) &body body)
`(defun ,fun-name (&key ,#syms)
(declare (special ,#syms))
(let ((,alist-sym
(loop
for s in ',syms
collecting (cons s (symbol-value s)))))
,#body)))
You can then use it with something like
(named-args f u (a b c)
(format t "~A~%" u))
which expands to
(DEFUN F (&KEY A B C)
(DECLARE (SPECIAL A B C))
(LET ((U
(LOOP FOR S IN '(A B C)
COLLECTING (CONS S (SYMBOL-VALUE S)))))
(FORMAT T "~A~%" U)))
Finally, calling will give
(f :a 3) => ((A . 3) (B) (C))
Note that we need the special declaration otherwise symbol-value doesn't work (you need a global binding for symbol-value). I couldn't find a way to get rid of that.
Looking at your question again, it looks like you actually don't want the keyword arguments that didn't get passed. In which case you could parse a &rest argument (although that's a flat list, so you'd need to map along it in twos) or you could modify the macro as follows:
(defmacro named-args (fun-name alist-sym (&rest syms) &body body)
`(defun ,fun-name (&key ,#syms)
(declare (special ,#syms))
(let ((,alist-sym
(loop
for s in ',syms
when (symbol-value s)
collecting (cons s (symbol-value s)))))
,#body)))
and then you get
(f :a 3) => ((A . 3))