I am writing a bunch of classes, for which I need some methods. Thus
I'll have something like:
(defgeneric m (this))
(defmethod m ((this class-1))
...)
(defmethod m ((this class-2))
...)
But I also need to define (m NIL). The only way I found to do that is to
use the class T:
(defmethod m ((this t))
(assert (null this))
...)
I'm not satisfied with this because I'd like it to be clearer about how
it is a special case for NIL, and not a fall-through case for any random
object.
Is there any standard, or usual, way to handle this?
use the eql speciailizer.
(defmethod m ((this (eql nil)))
(special-case-for-nil-here))
And you don't need to special an object of type t.
Just do:
(defmethod m (this)
)
To make a default method.
Philippe Lorin <············@gmail.com> writes:
> But I also need to define (m NIL). The only way I found to do that is
> to use the class T:
>
> (defmethod m ((this t))
> (assert (null this))
> ...)
>
> I'm not satisfied with this because I'd like it to be clearer about
> how it is a special case for NIL, and not a fall-through case for any
> random object.
>
> Is there any standard, or usual, way to handle this?
The system class NULL includes NIL (and only NIL).
(defmethod m ((this null)) ...)
Zach
The argument specialization is based usually on a specific class, eg
(defmethod m ((this my-class))... will be called when (m my-arg..) and
my-arg is of type my-class. If you have a specialization of ((this
nil)), you're asking for objects of type NIL. This is a true class in
CL, but it is an empty set. No objects can be of type NIL. But you can
use an EQL specializer. This specializes the method to a specific
object. Try (defmethod m ((this (eql nil)))...
Philippe Lorin <············@gmail.com> writes:
> I am writing a bunch of classes, for which I need some methods. Thus
> I'll have something like:
>
> (defgeneric m (this))
>
> (defmethod m ((this class-1))
> ...)
>
> (defmethod m ((this class-2))
> ...)
>
> But I also need to define (m NIL). The only way I found to do that is
> to use the class T:
>
> (defmethod m ((this t))
> (assert (null this))
> ...)
>
> I'm not satisfied with this because I'd like it to be clearer about
> how it is a special case for NIL, and not a fall-through case for any
> random object.
>
> Is there any standard, or usual, way to handle this?
NIL = {}
NULL = {NIL}
What good would that do to define a method that can be called on NO object?
(this NULL) is equivalent to (this (eql nil))
since there's only one element in NULL.
--
__Pascal Bourguignon__ http://www.informatimago.com/
Grace personified,
I leap into the window.
I meant to do that.
From: Marcin 'Qrczak' Kowalczyk
Subject: Re: How best to handle NIL in generics?
Date:
Message-ID: <87slv1o6gy.fsf@qrnik.zagroda>
···@zedat.fu-berlin.de (Stefan Ram) writes:
> The possibility of such a notation is a difference between
> programming languages and mathematics: In mathematics, there
> can not be a function of no arguments except the empty
> function (or, for some non-standard definition of "function").
When "function" means a pure mathematical mapping, functions with no
arguments are isomorphic with functions from a 1-element sets, not
with empty functions (from empty sets), and further with their values
at this single point.
--
__("< Marcin Kowalczyk
\__/ ······@knm.org.pl
^^ http://qrnik.knm.org.pl/~qrczak/
Stefan Ram wrote:
> Marcin 'Qrczak' Kowalczyk <······@knm.org.pl> writes:
>
>>>In mathematics, there can not be a function of no arguments
>>>except the empty function (or, for some non-standard
>>>definition of "function").
>>
>>When "function" means a pure mathematical mapping, functions
>>with no arguments are isomorphic with functions from a
>>1-element sets, not with empty functions (from empty sets), and
>>further with their values at this single point.
>
>
> In mathematics, a function is a functional relation, i.e., a
> set of pairs meeting certain criteria (plus the information
> about its domain and range).
>
> The function "f" might be given as the set {(1,2)}, which
> means that "f(1)=2", while f is not defined for any other
> value than "1".
>
> Now, I would like to see the set of pairs for a "function
> with no arguments" that still is supposed to have a value,
> as you seem to mention it.
>
Your definition of function only supports functions of one argument. To
support more than one argument, the parameter must be an ordered
sequence (a list). The function binary-+ would be defined by the set
{(1, 2), 3), (1, -5), -4), ...}. We can even describe the function +
(variable-arguments) in this way:
{(1, 1), ((1, 2), 3), ((1,2,3), 6), ((1,2,3,4), 10), ...}.
It's just a small extension to allow no arguments from here. Just add
the pair ((), 0) to that set.
-- MJF
Stefan Ram wrote:
> M Jared Finder <·····@hpalace.com> writes:
>
>>The function binary-+ would be defined by the set {(1, 2), 3),
>>(1, -5), -4), ...}. We can even describe the function +
>>(variable-arguments) in this way: {(1, 1), ((1, 2), 3),
>>((1,2,3), 6), ((1,2,3,4), 10), ...}.
>
> That is only one possibility to define functions of multiple
> arguments, and it would not be the way that I prefer.
>
> I'd rather prefer a definition as genuine multi-argument
> functions, i.e.,
>
> { (1, 2, 3), (1, -5, -4), ... }
>
> So that the type of the function "single-argument" or
> "multi-argument" is part of the function itself, not of
> its interpretation.
But that doesn't generalize to variable-argument relations, where the
number of inputs and the number of outputs can vary from call to call.
You have to separate the input-tuple from the output-tuple!
>>It's just a small extension to allow no arguments from here.
>>Just add the pair ((), 0) to that set.
>
> To me that would be a function from one argument, i.e., "()".
> Even if I would accept and follow all your definitions, this
> interpretation would still be possible.
No, it's a function of no arguments. Like all functions, it takes a
n-tuple as input; n happens to be zero.
-- MJF
From: Marcin 'Qrczak' Kowalczyk
Subject: Re: How best to handle NIL in generics?
Date:
Message-ID: <87wtkdny75.fsf@qrnik.zagroda>
···@zedat.fu-berlin.de (Stefan Ram) writes:
> I'd rather prefer a definition as genuine multi-argument
> functions, i.e.,
>
> { (1, 2, 3), (1, -5, -4), ... }
With this formulation a function of no arguments is still not the
empty function but a set containing a single 1-tuple containing
the result.
Of course it's isomorphic to the value itself (since a mathematical
function pure and thus its only effect is returning a value), and thus
it's not used in mathematics when the arity is statically known.
--
__("< Marcin Kowalczyk
\__/ ······@knm.org.pl
^^ http://qrnik.knm.org.pl/~qrczak/
Marcin 'Qrczak' Kowalczyk wrote:
> ···@zedat.fu-berlin.de (Stefan Ram) writes:
>
> > The possibility of such a notation is a difference between
> > programming languages and mathematics: In mathematics, there
> > can not be a function of no arguments except the empty
> > function (or, for some non-standard definition of "function").
>
> When "function" means a pure mathematical mapping, functions with no
> arguments are isomorphic with functions from a 1-element sets, not
> with empty functions (from empty sets), and further with their values
> at this single point.
Concrete example: arrays with no dimensions.
An array with zero dimensions actually has one element. There is
exactly one valid expression which indexes into the array: in Common
Lisp, (aref <array>). It stands for that element.
From: Marcin 'Qrczak' Kowalczyk
Subject: Re: How best to handle NIL in generics?
Date:
Message-ID: <87vezxeavw.fsf@qrnik.zagroda>
···@zedat.fu-berlin.de (Stefan Ram) writes:
> In mathematics, a function is a functional relation, i.e., a
> set of pairs meeting certain criteria (plus the information
> about its domain and range).
And a multi-argument function is a single-argument function from the
cartesian product of domains of arguments.
> The function "f" might be given as the set {(1,2)}, which
> means that "f(1)=2", while f is not defined for any other
> value than "1".
>
> Now, I would like to see the set of pairs for a "function
> with no arguments" that still is supposed to have a value,
> as you seem to mention it.
>
{(*, 3)}, where * is the only element of the null cartesian product.
--
__("< Marcin Kowalczyk
\__/ ······@knm.org.pl
^^ http://qrnik.knm.org.pl/~qrczak/
From: Marcin 'Qrczak' Kowalczyk
Subject: Re: How best to handle NIL in generics?
Date:
Message-ID: <8764rxwhul.fsf@qrnik.zagroda>
···@zedat.fu-berlin.de (Stefan Ram) writes:
> The assertion
>
> "A multi-argument function is a single-argument function."
>
> (similar to the one I have quoted above) sounds like a
> contradiction to me,
Ok, "is isomorphic to" or "can be emulated with".
> This would be a function that takes "*" as its only argument,
> so its domain "{*}" is non-empty.
That's what I meant to say. A function with no arguments is not
a function with an empty domain, but with one-element domain.
--
__("< Marcin Kowalczyk
\__/ ······@knm.org.pl
^^ http://qrnik.knm.org.pl/~qrczak/
Marcin 'Qrczak' Kowalczyk <······@knm.org.pl> writes:
>
> ···@zedat.fu-berlin.de (Stefan Ram) writes:
>
> > The possibility of such a notation is a difference between
> > programming languages and mathematics: In mathematics, there
> > can not be a function of no arguments except the empty
> > function (or, for some non-standard definition of "function").
>
> When "function" means a pure mathematical mapping, functions with no
> arguments are isomorphic with functions from a 1-element sets, not
> with empty functions (from empty sets), and further with their values
> at this single point.
Is this just a fancy way of saying that mathematical functions with no
arguments are the same as constants?
--
Thomas A. Russ, USC/Information Sciences Institute
Philippe Lorin wrote:
> I am writing a bunch of classes, for which I need some methods. Thus
> I'll have something like:
>
> (defgeneric m (this))
>
> (defmethod m ((this class-1))
> ...)
>
> (defmethod m ((this class-2))
> ...)
>
> But I also need to define (m NIL). The only way I found to do that is to
> use the class T:
>
> (defmethod m ((this t))
> (assert (null this))
> ...)
>
> I'm not satisfied with this because I'd like it to be clearer about how
> it is a special case for NIL, and not a fall-through case for any random
> object.
>
> Is there any standard, or usual, way to handle this?
Other people have responded to your original question.
One thing that I might add, is that I like to see
method definitions (just like normal function definitions)
with variable names that I can recognize while I'm
scanning the function. That is, not "this."
So for instance, if your methods applied to geometric
shapes, your method definitions might look like:
(defgeneric m (shape))
(defmethod m ((square square))
...)
(defmethod m ((triangle triangle))
...)
Larry
Laurence Kramer <·······@cs.cmu.edu> writes:
> (defgeneric m (shape))
>
> (defmethod m ((square square))
> ...)
>
> (defmethod m ((triangle triangle))
> ...)
I would rather use:
(defmethod m ((shape square)) ...)
(defmethod m ((shape triangle)) ...)
otherwise copy-pasting is a PITA.
And lisp is multiparadigm. If you want to program C++ in Lisp and use
THIS, or program Smalltalk in Lisp and use SELF, why not. ;-)
--
__Pascal Bourguignon__ http://www.informatimago.com/
This is a signature virus. Add me to your signature and help me to live
Pascal Bourguignon wrote:
> And lisp is multiparadigm. If you want to program C++ in Lisp and use
> THIS, or program Smalltalk in Lisp and use SELF, why not. ;-)
I had the notion of writing a tiny, partial Forth'ish control "language"
for a small program I want to translate from Python to Lisp as part of a
learning exercise. Actually, it struck me that something like Lisp might
be very good for playing around with and learning Forth concepts,
because if you run into something that would have been limitation in a
Forth implementation that you would have used, then you can always
"cheat" and get Lisp to do some of the heavy lifting.
From: Tim Daly Jr.
Subject: Re: How best to handle NIL in generics?
Date:
Message-ID: <87r7akf03q.fsf@beer.intern>
Pascal Bourguignon <····@mouse-potato.com> writes:
> I would rather use:
> (defmethod m ((shape square)) ...)
> (defmethod m ((shape triangle)) ...)
> otherwise copy-pasting is a PITA.
>
> And lisp is multiparadigm. If you want to program C++ in Lisp and use
> THIS, or program Smalltalk in Lisp and use SELF, why not. ;-)
>
List might be multi-paradigm, but this is the first time I've seen
copy-&-pasting on the list!!
--
-Tim
From: Tim Daly Jr.
Subject: Re: How best to handle NIL in generics?
Date:
Message-ID: <87mzl8f01u.fsf@beer.intern>
···@tenkan.org (Tim Daly Jr.) writes:
> Pascal Bourguignon <····@mouse-potato.com> writes:
>
> > I would rather use:
> > (defmethod m ((shape square)) ...)
> > (defmethod m ((shape triangle)) ...)
> > otherwise copy-pasting is a PITA.
> >
> > And lisp is multiparadigm. If you want to program C++ in Lisp and use
> > THIS, or program Smalltalk in Lisp and use SELF, why not. ;-)
> >
>
> List might be multi-paradigm, but this is the first time I've seen
> copy-&-pasting on the list!!
"Lisp"... :)
--
-Tim
···@tenkan.org (Tim Daly Jr.) writes:
> Pascal Bourguignon <····@mouse-potato.com> writes:
>
>> I would rather use:
>> (defmethod m ((shape square)) ...)
>> (defmethod m ((shape triangle)) ...)
>> otherwise copy-pasting is a PITA.
>>
>> And lisp is multiparadigm. If you want to program C++ in Lisp and use
>> THIS, or program Smalltalk in Lisp and use SELF, why not. ;-)
>>
>
> List might be multi-paradigm, but this is the first time I've seen
> copy-&-pasting on the list!!
Well if we only consider the two lines of lisp above, you don't think
I typed them both, do you?
--
__Pascal Bourguignon__ http://www.informatimago.com/
In a World without Walls and Fences,
who needs Windows and Gates?
Larry wrote:
> One thing that I might add, is that I like to see
> method definitions (just like normal function definitions)
> with variable names that I can recognize while I'm
> scanning the function. That is, not "this."
Interesting. However, I can't say I understand the gain. I don't find
it's harder to recognize "this" than something else. But I do find that
having multiple meanings for one symbol is not helping (it doesn't help
reading, and it doesn't help searching); and if I need to move/copy code
around, or change a class's name, using "this" saves work. Finally, one
could argue that "this", having a conventional meaning, is more informative.
I'd be interested to know what other people do about this. Is there some
consensus around the issue?
Philippe Lorin wrote:
> Larry wrote:
>
>> One thing that I might add, is that I like to see
>> method definitions (just like normal function definitions)
>> with variable names that I can recognize while I'm
>> scanning the function. That is, not "this."
>
>
> Interesting. However, I can't say I understand the gain. I don't find
> it's harder to recognize "this" than something else. But I do find that
> having multiple meanings for one symbol is not helping (it doesn't help
> reading, and it doesn't help searching); and if I need to move/copy code
> around, or change a class's name, using "this" saves work. Finally, one
> could argue that "this", having a conventional meaning, is more
> informative.
No, "this" has absolutely no semantics at all.
When I took my first programming course many, many
years ago, I was instructed to give variables meaningful
names. This helps when one is trying to understand the
semantics of a function/method.
Plus, in Lisp, methods can dispatch on more than one
class. So, if one of the class variables is named
"this," what is the second one named? "That?"
No, if you had a method that dispatched on both
say a geometrical shape and its color, you'd
define the method like:
(defmethod m ((triangle triangle)(color color))
...)
I'm not opposed to Pascal's use of "shape" as
a variable as opposed to something more specific
such as "triangle," however I feel there is some
benefit in having variables that are as specific
as possible given the context. (There are some
benefits that outweigh cut and paste.)
Larry
Laurence Kramer wrote:
> Philippe Lorin wrote:
> > around, or change a class's name, using "this" saves work. Finally, one
> > could argue that "this", having a conventional meaning, is more
> > informative.
>
> No, "this" has absolutely no semantics at all.
> When I took my first programming course many, many
> years ago, I was instructed to give variables meaningful
> names. This helps when one is trying to understand the
> semantics of a function/method.
However, in methods, you have not only the name, but the type (at least
for the specializable parameters). The type tells you a lot about the
parameter, which means that the name can carry less information.
When I program in C and C++, I often use very short parameter names.
This is a very good thing; it tells the code reader that the object
isn't some special instance of its type. Everything you need know about
the object is implied from the function's semantics and that object's
type.
Example? How about something like:
void tree_insert(tree_t *t, tree_node_t *n)
{
}
in the prototype, I'd drop the names completely:
void tree_insert(tree_t *, tree_node_t *);
The names of the types tell you all you need to know. Now in a language
with generic variables, you'd do it differently:
(defun tree-insert (tree node) ...)
Same information, but since types aren't declared, the names are made
meaningful.
> Plus, in Lisp, methods can dispatch on more than one
> class. So, if one of the class variables is named
> "this," what is the second one named? "That?"
Done it before. I'm sure that in the past I have written something
like:
list_insert_before(node_t *this, node_t *that);
If we need three args, we can switch to Japanese, which has this (close
to me), that (close to you) and that (far from both of us):
(defmethod make-triangle ((kore point) (sore point) (are point))
...)
This is sure to become a ``sore point'' for the maintainers.
*Boom-ching*.
> (defmethod m ((triangle triangle)(color color))
> ...)
That's boring repetition, like having to write Class::Class() in C++.
How about:
(defmethod m ((triangle tr) (color co))
...)
Note how you used a single letter for the method, haha. :) Ironic.
"Kaz Kylheku" <········@gmail.com> writes:
> in the prototype, I'd drop the names completely:
>
> void tree_insert(tree_t *, tree_node_t *);
It's not wise:
void tree_substitute(tree_t *, tree_node_t *, tree_node_t *);
which by which?
void tree_substitute(tree_t* tree,tree_node_t* new,tree_node_t* old);
is better documented.
Happily, in lisp we don't have to generate any header.
--
__Pascal Bourguignon__ http://www.informatimago.com/
Grace personified,
I leap into the window.
I meant to do that.
Kaz Kylheku wrote:
[snip, ...]
>
> (defmethod m ((triangle tr) (color co))
> ...)
>
> Note how you used a single letter for the method, haha. :) Ironic.
>
Yes. I was a little lazy in using the OP's original method name.
Larry
Laurence Kramer wrote:
> No, "this" has absolutely no semantics at all.
Ok, maybe I was not precise enough; I'm not talking about the meaning of
"this" in Lisp ("triangle" has no more meaning than "this" there), but
its meaning in the field of OOP. Say "this" to a non-English programmer
and he understands something useful. I'd call that the meaning of
"this", and I expect a variable named "this" or "self" to have a strong
connection to it.
> When I took my first programming course many, many
> years ago, I was instructed to give variables meaningful
> names. This helps when one is trying to understand the
> semantics of a function/method.
I might care about what you were instructed to do if I were writing my
first program, but this is only an argument of authority. The fact that
it was long ago is relevant though, presuming it implies you've
encountered and tried various ways of naming variables. I do want to
consider the outcome of your experience -- personnally, I've used my
share of IndexOfTheFirstLetter monsters (I'm not suggesting "triangle"
is of that kind, just digressing a bit), but I got tired of writing, but
also, and more importantly, reading and speaking them; now I prefer
using a short name and commenting it so that the meaning gets written
only once. Still, I'm not sure about searching, as it's easier when the
name is not too short (specifically, not a too common substring of other
names), but it gets harder when a lot of names share parts, like, say,
"index-of-".)
I do agree that meaningful names help understanding (if I may say it
so... obviously ;) ). But this has to be balanced with other issues
(redundancy, concision...); and meaning can't be made independent of
context, so it's a problem of how much context you're wanting to retain
in the name. I can't see how "square" is meaningful in something like:
(defmethod m ((square square))
...)
since the type is already mentionned. Call it "s" and there's no
information loss, but greater readability (to me) and maintainability.
I'm not against "square" in something like:
(defun f (square)
...)
I'd also take into account how often the name is used, one-shot
arguments getting a longer (or rather, less shortened) name.
> Plus, in Lisp, methods can dispatch on more than one
> class. So, if one of the class variables is named
> "this," what is the second one named? "That?"
No one size fits all. I see no gain in ensuring we're able to generalize
from multimethods to all methods. I don't even think that "this" should
be used in all methods; only when it makes sense.
However, I would welcome a standard pronoun for "accusative-this" (and
I'd expect computer languages in the future to use that kind of thing).
I find myself wanting it sometimes. I don't feel "that" is obvious
enough. Or kore/sore/are for that matter ^^ .
> No, if you had a method that dispatched on both
> say a geometrical shape and its color, you'd
> define the method like:
>
> (defmethod m ((triangle triangle)(color color))
> ...)
I agree with you here. I may prefer "((tr triangle) (cl color))" but I
would probably not use "this". Maybe it depends on what the method does,
though; for instance if it is meant to change the color of triangle.
> I'm not opposed to Pascal's use of "shape" as
> a variable as opposed to something more specific
> such as "triangle," however I feel there is some
> benefit in having variables that are as specific
> as possible given the context. (There are some
> benefits that outweigh cut and paste.)
Don't take it wrong, but I'm tempted to say I'd prefer "as UNspecific as
possible given the context" ;) . For instance, if I'm computing the sum
of some series, and no other sum in the local context, I'd just call it
"sum", or "s" with a comment -- not "sum-of-the-series". And if it's
meant to be the result of the enclosing function, I'd call it just that
-- "result".
Philippe Lorin <············@gmail.com> writes:
>
> Laurence Kramer wrote:
> > No, "this" has absolutely no semantics at all.
>
> Ok, maybe I was not precise enough; I'm not talking about the meaning of
> "this" in Lisp ("triangle" has no more meaning than "this" there), but
> its meaning in the field of OOP. Say "this" to a non-English programmer
> and he understands something useful. I'd call that the meaning of
> "this", and I expect a variable named "this" or "self" to have a strong
> connection to it.
The real problem with "this" or "self" as a method argument name is that
it perpetuates the idea of a distinguished object or parameter. In
effect, the owner of the method. This sort of ownership is appropriate
in single-dispatch paradigms where the method really does belong to a
particular argument.
In the general CLOS case, though, the method belongs to the function,
and not to any particular argument, and so there is an active reason to
disparage the use of "this" or "self" as arguments.
Exceptions could be for cases where the generic function really is
tightly bound to a single class. For example, I would not find it
objectionable to use a name like that as the argument of an accessor
function for a CLOS slot.
======
My personal preference among them is "self", though that's probably just
a holdover from the flavors days.
--
Thomas A. Russ, USC/Information Sciences Institute
Philippe Lorin wrote:
[snip, ...]
>
> (defmethod m ((square square))
> ...)
>
> since the type is already mentionned. Call it "s" and there's no
> information loss, but greater readability (to me) and maintainability.
Ah, I see where you're coming from. I'm not worried
about preserving the type information. You're right.
That's clear from the method definition. What I'm
concerned about is a good convention for naming variables.
If the method is long and hairy and I'm scanning through
it trying to figure out what it does, I don't want to
encounter a variable like "s", or "this" or "that" as
those variable names could refer to anything. If you
like shorter names, "sq" is acceptable.
>
>
> I'm not against "square" in something like:
>
> (defun f (square)
> ...)
In Lisp there's really not much difference between generic functions
(methods) and functions. I don't see why one would use a "nice"
variable name in a function and an obfuscated one in a method.
And when I see Lisp code with methods that use the variables
"this" or "self" I say to myself, that code was probably written
by a Java or C++ person that hasn't yet grokked that CLOS methods
are more expressive than what they're used to (i.e., they're not
tied to a particular class).
Larry