Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Overloading functions in Common Lisp

814 views
Skip to first unread message

hb

unread,
Sep 15, 2005, 7:49:15 PM9/15/05
to
Hi all,

I just wonder if it is possible to overload functions in Common Lisp in

a neat way. What I mean is, can the equal function, for example, be
extended
to support comparing user-defined structs.

I worked around this a bit, and found out a very bad and dangerous way
to do this by saving the old equal function in a variable and
redefining
a new function with name equal.

(setf old-equal #'equal)

(defun equal (obj1 obj2)
<<do some comparison for user-defined structures>>
<<use default equal function for other types>>)

There is no need to say that this is a terrible solution, however it is
the only solution I've found. (By ignoring symbol lock mechanisms :)

I also tried defining equal by defmethod (only a try), it doesn't work
either.

-- hb

Pascal Costanza

unread,
Sep 15, 2005, 8:00:10 PM9/15/05
to
hb wrote:
> Hi all,
>
> I just wonder if it is possible to overload functions in Common Lisp in
>
> a neat way. What I mean is, can the equal function, for example, be
> extended
> to support comparing user-defined structs.
>
> I worked around this a bit, and found out a very bad and dangerous way
> to do this by saving the old equal function in a variable and
> redefining
> a new function with name equal.
>
> (setf old-equal #'equal)
>
> (defun equal (obj1 obj2)
> <<do some comparison for user-defined structures>>
> <<use default equal function for other types>>)
>
> There is no need to say that this is a terrible solution, however it is
> the only solution I've found. (By ignoring symbol lock mechanisms :)

The ANSI specification actually says that you are not allowed to do
that. ("The consequences are unspecified." or some such wording. ;)

The best way is just to define your own function:

(defgeneric my-equal (obj1 obj2))

(defmethod my-equal ((obj1 class1) (obj2 class1))
...)

etc.

If you don't like the requirement to use your own name, or if you would
like to impose the genericity on some existing code, you can shadow the
existing function:

(shadow 'equal)

(defgeneric equal (obj1 obj2)
(:method (obj1 obj2)
"Default method if all other cases fail."
(cl:equal obj1 obj2))) ; calls the original version

(defmethod equal (...) ...)

etc.

Export your own equal from your own package, and import it in the code
in which you want to use the generic version.

Check the specification for defpackage - it actually provides hooks to
define the shadowing and exporting on that level.

Note that, of course, in this way you cannot retroactively change the
definition for code that you don't control yourself. (But that's
probably not a good idea in the first place anyway.)

Pascal

--
OOPSLA'05 tutorial on generic functions & the CLOS Metaobject Protocol
++++ see http://p-cos.net/oopsla05-tutorial.html for more details ++++

Barry Margolin

unread,
Sep 15, 2005, 8:04:28 PM9/15/05
to
In article <1126828155.2...@g44g2000cwa.googlegroups.com>,
"hb" <h...@cs.bilgi.edu.tr> wrote:

> Hi all,
>
> I just wonder if it is possible to overload functions in Common Lisp in
>
> a neat way. What I mean is, can the equal function, for example, be
> extended
> to support comparing user-defined structs.

You can create your own CLOS generic functions to dispatch on the
parameter types. However, you can't change built-in standard functions
to generic functions.

>
> I worked around this a bit, and found out a very bad and dangerous way
> to do this by saving the old equal function in a variable and
> redefining
> a new function with name equal.
>
> (setf old-equal #'equal)

If you're going to do this, I suggest

(setf (symbol-function 'old-equal) #'equal)

Then you can call OLD-EQUAL using normal function call syntax, rather
than FUNCALL.

However, the more common recommendation is to use packages. Create your
own package where you shadow EQUAL. When it wants to call the normal
function, it calls CL:EQUAL. However, this will only affect programs
that use your package, not all the callers of the standard EQUAL.

>
> (defun equal (obj1 obj2)
> <<do some comparison for user-defined structures>>
> <<use default equal function for other types>>)
>
> There is no need to say that this is a terrible solution, however it is
> the only solution I've found. (By ignoring symbol lock mechanisms :)
>
> I also tried defining equal by defmethod (only a try), it doesn't work
> either.

(fmakunbound 'equal)
(defgeneric equal)
(defmethod equal ((x t) (y t))
(old-equal x y))
(defmethod equal ((x mystruct) (y mystruct))
(my-struct-equal x y))

--
Barry Margolin, bar...@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***

drewc

unread,
Sep 15, 2005, 8:56:29 PM9/15/05
to
hb wrote:
> Hi all,
>
> I just wonder if it is possible to overload functions in Common Lisp in
>
> a neat way.

Mu.

> What I mean is, can the equal function, for example, be
> extended
> to support comparing user-defined structs.

This is a FAQ, and the short answer is "sort of but you probably don't
want to do that." :)

or, as Erik Naggum once put it :
'actually, both answers should be "yes", despite the also correct answer
"no" to the first question -- you just have to do it somewhat
differently from what the question implies you would do it, and probably
from what most people would recommend.'

see:
http://groups.google.ca/group/comp.lang.lisp/browse_frm/thread/87de6048c979e7dd/ba394bf77542992d?


--
Drew Crampsie
drewc at tech dot coop
"Never mind the bollocks -- here's the sexp's tools."
-- Karl A. Krueger on comp.lang.lisp

Kent M Pitman

unread,
Sep 15, 2005, 10:15:13 PM9/15/05
to
"hb" <h...@cs.bilgi.edu.tr> writes:

> I just wonder if it is possible to overload functions in Common Lisp

It IS intended that you sometimes define additional methods
on generic functions.

It is NOT intended that you do overloading.

Overloading is the practice of applying _unrelated_ definitions to the
same operator.

The idea behind generic functions is that you first define the "meaning"
of the generic operation in terms of the signature its arguments will take.
Then you define methods that implement this signature for a variety of
types that all satisfy the meaning of the generic function.

> in a neat way. What I mean is, can the equal function, for example,
> be extended to support comparing user-defined structs.

First, your use of "extend" suggests that you don't attach sufficient
import to the idea that the EQUAL operator is _already_ defined on
user-defined structs. It may be that you don't _like_ the way in
which it compares such structs, but you should not conclude that its
effect is ill-defined, just perhaps "not defined to suit your needs".

Once you see that the EQUAL function is already "total", that is, that
it's never an error and always well-defined to call EQUAL on any two
arguments, you realize it cannot be extended.

Second, EQUAL is a function in the Common Lisp package. Such
functions can in general not be redefined nor extended unless the
specification permits it. See
11.1.2.1.2 Constraints on the COMMON-LISP Package for Conforming Programs
http://www.lispworks.com/documentation/HyperSpec/Body/11_abab.htm

So to answer questions of this kind, you want to check the spec.
If you look at CLHS at
http://www.lispworks.com/documentation/HyperSpec/Body/f_equal.htm
for example, you'll see that EQUAL is defined as a function, not a
generic function. So that means you can't customize it.

There _are_ generic functions in CL like PRINT-OBJECT that you _can_
customize with DEFMETHOD. EQUAL is just not one of them.

Related reading about the EQUAL function (my "Parenthetically Speaking"
article about equality):

http://www.nhplace.com/kent/PS/EQUAL.html

> I worked around this a bit, and found out a very bad and dangerous way
> to do this by saving the old equal function in a variable and
> redefining
> a new function with name equal.
>
> (setf old-equal #'equal)
>
> (defun equal (obj1 obj2)
> <<do some comparison for user-defined structures>>
> <<use default equal function for other types>>)
>

This is what shadowing is for.

(defpackage my-package
(:use "COMMON-LISP")
(:shadow "EQUAL"))

(in-package "MY-PACKAGE")

(defmethod equal (x y) ; some people might say MY-PACKAGE:EQUAL here
; to emphasize that this is a different EQUAL than
; CL:EQUAL, but it's optional and hence a style issue

;; MY-PACKAGE:EQUAL is a function that _defaultly_ behaves like CL
;; defines, but which programs can customize to have other behaviors
;; for classes of the relevant kind.
(cl:equal x y))

(defstruct my-frob ...)

(defmethod equal ((x my-frob) (y my-frob))
...)

> There is no need to say that this is a terrible solution, however it is
> the only solution I've found. (By ignoring symbol lock mechanisms :)

I won't say what you already know, but I will highlight that the reasons
it might not be good are:

(a) Implementations or other user programs might rely on what the spec
defines and might be perplexed that your definition causes the documented
semantics to not occur

(b) Implementations are permitted to inline their own special knowledge
for system functions. e.g., a compiler could just rewrite
(cl:equal x y)
to
(system::internal-equal x y)
for some reason you don't know about and your trick might simply
not work and it might confuse you why

> I also tried defining equal by defmethod (only a try), it doesn't work
> either.

That's why you use symbol shadowing. So you can start fresh with a
definition suited to your liking, and without affecting others using
the system-supplied one.

0 new messages