From: Didier Verna
Subject: POLL: about arguments of invariable type to methods
Date: 
Message-ID: <mux4p5d9i5g.fsf@uzeb.lrde.epita.fr>
       Suppose you have a generic function func (arg1 arg2). Suppose
further that in your application, the dispatch might occur on arg1, but
arg2 will always be of the same type.

How do you guys behave in that situation ? Please select one or several
options below. All choices must be properly justified.

* Option 1 (well, I do nothing special):
  (defmethod func ((arg1 type1) arg2) ...)
  (defmethod func ((arg1 type2) arg2) ...)
  etc.

* Option 2:
  (defmethod func ((arg1 type1) (arg2 theonlytype)) ...)
  (defmethod func ((arg1 type2) (arg2 theonlytype)) ...)
  etc.

* Option 3:
  (defmethod func ((arg1 type1) arg2) (declare (type theonlytype arg2)) ...)
  (defmethod func ((arg1 type2) arg2) (declare (type theonlytype arg2)) ...)
  etc.

* Option 4:
  It depends.

* Option 5:
  / insert whatever you like here /

-- 
Resistance is futile. You will be jazzimilated.

Scientific site:   http://www.lrde.epita.fr/~didier
Music (Jazz) site: http://www.didierverna.com

EPITA/LRDE, 14-16 rue Voltaire, 94276 Le Kremlin-Bic�tre, France
Tel. +33 (0)1 44 08 01 85       Fax. +33 (0)1 53 14 59 22

From: Kenny
Subject: Re: POLL: about arguments of invariable type to methods
Date: 
Message-ID: <48aee75a$0$20946$607ed4bc@cv.net>
Didier Verna wrote:
>        Suppose you have a generic function func (arg1 arg2). Suppose
> further that in your application, the dispatch might occur on arg1, but
> arg2 will always be of the same type.
> 
> How do you guys behave in that situation ? Please select one or several
> options below. All choices must be properly justified.
> 
> 
> * Option 5:

The thought/concern/question does not arise. This only seems like Option 
#1. Conveniently, this is a non-opting option so requires no 
justification. It does however implicitly require you to justify how on 
earth you ever ended up thinking about such a thing and for the love of 
god please don't say "performance".

Your options are:

1. Just trying to kill off the Xah thread
2. Just trying to ask a question dumber than "Does Lisp have a stutter?"
3. Other_______________________.

kenny
From: Tamas K Papp
Subject: Re: POLL: about arguments of invariable type to methods
Date: 
Message-ID: <6h85n2Fjofu6U1@mid.individual.net>
On Fri, 22 Aug 2008 17:35:55 +0200, Didier Verna wrote:

> Suppose you have a generic function func (arg1 arg2). Suppose further
> that in your application, the dispatch might occur on arg1, but arg2
> will always be of the same type.
> 
> How do you guys behave in that situation ? Please select one or several
> options below. All choices must be properly justified.

Mostly 1.

Justification: This is the simplest solution, and I see no reason do to 
otherwise (but please enlighten me if you feel that is necessary :-)  
What would be the benefit of 2 or 3?

Tamas
From: Rainer Joswig
Subject: Re: POLL: about arguments of invariable type to methods
Date: 
Message-ID: <joswig-F0886A.17583622082008@news-europe.giganews.com>
In article <···············@uzeb.lrde.epita.fr>,
 Didier Verna <······@lrde.epita.fr> wrote:

>        Suppose you have a generic function func (arg1 arg2). Suppose
> further that in your application, the dispatch might occur on arg1, but
> arg2 will always be of the same type.
> 
> How do you guys behave in that situation ? Please select one or several
> options below. All choices must be properly justified.
> 
> * Option 1 (well, I do nothing special):
>   (defmethod func ((arg1 type1) arg2) ...)
>   (defmethod func ((arg1 type2) arg2) ...)
>   etc.
> 
> * Option 2:
>   (defmethod func ((arg1 type1) (arg2 theonlytype)) ...)
>   (defmethod func ((arg1 type2) (arg2 theonlytype)) ...)
>   etc.
> 
> * Option 3:
>   (defmethod func ((arg1 type1) arg2) (declare (type theonlytype arg2)) ...)
>   (defmethod func ((arg1 type2) arg2) (declare (type theonlytype arg2)) ...)
>   etc.
> 
> * Option 4:
>   It depends.
> 
> * Option 5:
>   / insert whatever you like here /

If I want runtime type checking, I'm using 2. If I don't care, then 1.

-- 
http://lispm.dyndns.org/
From: Pascal Costanza
Subject: Re: POLL: about arguments of invariable type to methods
Date: 
Message-ID: <6h895lFjrri1U1@mid.individual.net>
Rainer Joswig wrote:
> In article <···············@uzeb.lrde.epita.fr>,
>  Didier Verna <······@lrde.epita.fr> wrote:
> 
>>        Suppose you have a generic function func (arg1 arg2). Suppose
>> further that in your application, the dispatch might occur on arg1, but
>> arg2 will always be of the same type.
>>
>> How do you guys behave in that situation ? Please select one or several
>> options below. All choices must be properly justified.
>>
>> * Option 1 (well, I do nothing special):
>>   (defmethod func ((arg1 type1) arg2) ...)
>>   (defmethod func ((arg1 type2) arg2) ...)
>>   etc.
>>
>> * Option 2:
>>   (defmethod func ((arg1 type1) (arg2 theonlytype)) ...)
>>   (defmethod func ((arg1 type2) (arg2 theonlytype)) ...)
>>   etc.
>>
>> * Option 3:
>>   (defmethod func ((arg1 type1) arg2) (declare (type theonlytype arg2)) ...)
>>   (defmethod func ((arg1 type2) arg2) (declare (type theonlytype arg2)) ...)
>>   etc.
>>
>> * Option 4:
>>   It depends.
>>
>> * Option 5:
>>   / insert whatever you like here /
> 
> If I want runtime type checking, I'm using 2. If I don't care, then 1.

Same here. Because of the additional type check, option 2 probably 
incurs a (minor) performance overhead. Therefore, most of the time, I 
typically specialize as few arguments as possible, although the runtime 
type check is actually a very good reason as well.

Option 3, I don't like. I think type declarations should only be used 
where performance is really important, and that doesn't seem to mesh 
well with generic functions.

This is a case where I think there is something missing in CLOS, 
actually. The CLOS MOP has this (very badly worded) case where 
slot-value-using-class shouldn't be specialized on its second argument. 
There is an option missing in the defgeneric form which allows you to 
announce this. For example, :argument-precedence-order could be allowed 
to declare a subset of the required arguments, which would mean that 
unmentioned parameters must not be specialized in methods for that 
generic function. I think that would be a useful extension.



Pascal

-- 
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Rainer Joswig
Subject: Re: POLL: about arguments of invariable type to methods
Date: 
Message-ID: <joswig-16341E.19230522082008@news-europe.giganews.com>
In article <··············@mid.individual.net>,
 Pascal Costanza <··@p-cos.net> wrote:

> Rainer Joswig wrote:
> > In article <···············@uzeb.lrde.epita.fr>,
> >  Didier Verna <······@lrde.epita.fr> wrote:
> > 
> >>        Suppose you have a generic function func (arg1 arg2). Suppose
> >> further that in your application, the dispatch might occur on arg1, but
> >> arg2 will always be of the same type.
> >>
> >> How do you guys behave in that situation ? Please select one or several
> >> options below. All choices must be properly justified.
> >>
> >> * Option 1 (well, I do nothing special):
> >>   (defmethod func ((arg1 type1) arg2) ...)
> >>   (defmethod func ((arg1 type2) arg2) ...)
> >>   etc.
> >>
> >> * Option 2:
> >>   (defmethod func ((arg1 type1) (arg2 theonlytype)) ...)
> >>   (defmethod func ((arg1 type2) (arg2 theonlytype)) ...)
> >>   etc.
> >>
> >> * Option 3:
> >>   (defmethod func ((arg1 type1) arg2) (declare (type theonlytype arg2)) ...)
> >>   (defmethod func ((arg1 type2) arg2) (declare (type theonlytype arg2)) ...)
> >>   etc.
> >>
> >> * Option 4:
> >>   It depends.
> >>
> >> * Option 5:
> >>   / insert whatever you like here /
> > 
> > If I want runtime type checking, I'm using 2. If I don't care, then 1.
> 
> Same here. Because of the additional type check, option 2 probably 
> incurs a (minor) performance overhead. Therefore, most of the time, I 
> typically specialize as few arguments as possible, although the runtime 
> type check is actually a very good reason as well.

It's also kind of a 'gate'. Within the method the value
of the parameter is of the class described (unless there
is some assignment or some other magic). I think the compiler
can take advantage of it.

It also helps during debugging. If one always passes objects
via normal parameters (without type check / method dispatch), then a runtime
type error may happen deep in the program (with a long stack backtrace).
If the classes are mentioned in the parameter list, the right method
will be called or a missing method will be reported early.
 
> Option 3, I don't like. I think type declarations should only be used 
> where performance is really important, and that doesn't seem to mesh 
> well with generic functions.
> 
> This is a case where I think there is something missing in CLOS, 
> actually. The CLOS MOP has this (very badly worded) case where 
> slot-value-using-class shouldn't be specialized on its second argument. 
> There is an option missing in the defgeneric form which allows you to 
> announce this. For example, :argument-precedence-order could be allowed 
> to declare a subset of the required arguments, which would mean that 
> unmentioned parameters must not be specialized in methods for that 
> generic function. I think that would be a useful extension.
> 
> 
> 
> Pascal

-- 
http://lispm.dyndns.org/
From: Pascal Costanza
Subject: Re: POLL: about arguments of invariable type to methods
Date: 
Message-ID: <6h8cbsFk2qu3U1@mid.individual.net>
Rainer Joswig wrote:
> In article <··············@mid.individual.net>,
>  Pascal Costanza <··@p-cos.net> wrote:
> 
>> Rainer Joswig wrote:
>>> In article <···············@uzeb.lrde.epita.fr>,
>>>  Didier Verna <······@lrde.epita.fr> wrote:
>>>
>>>>        Suppose you have a generic function func (arg1 arg2). Suppose
>>>> further that in your application, the dispatch might occur on arg1, but
>>>> arg2 will always be of the same type.
>>>>
>>>> How do you guys behave in that situation ? Please select one or several
>>>> options below. All choices must be properly justified.
>>>>
>>>> * Option 1 (well, I do nothing special):
>>>>   (defmethod func ((arg1 type1) arg2) ...)
>>>>   (defmethod func ((arg1 type2) arg2) ...)
>>>>   etc.
>>>>
>>>> * Option 2:
>>>>   (defmethod func ((arg1 type1) (arg2 theonlytype)) ...)
>>>>   (defmethod func ((arg1 type2) (arg2 theonlytype)) ...)
>>>>   etc.
>>>>
>>>> * Option 3:
>>>>   (defmethod func ((arg1 type1) arg2) (declare (type theonlytype arg2)) ...)
>>>>   (defmethod func ((arg1 type2) arg2) (declare (type theonlytype arg2)) ...)
>>>>   etc.
>>>>
>>>> * Option 4:
>>>>   It depends.
>>>>
>>>> * Option 5:
>>>>   / insert whatever you like here /
>>> If I want runtime type checking, I'm using 2. If I don't care, then 1.
>> Same here. Because of the additional type check, option 2 probably 
>> incurs a (minor) performance overhead. Therefore, most of the time, I 
>> typically specialize as few arguments as possible, although the runtime 
>> type check is actually a very good reason as well.
> 
> It's also kind of a 'gate'. Within the method the value
> of the parameter is of the class described (unless there
> is some assignment or some other magic). I think the compiler
> can take advantage of it.
> 
> It also helps during debugging. If one always passes objects
> via normal parameters (without type check / method dispatch), then a runtime
> type error may happen deep in the program (with a long stack backtrace).
> If the classes are mentioned in the parameter list, the right method
> will be called or a missing method will be reported early.

True, that's a very good argument for option 2.


Pascal


-- 
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Didier Verna
Subject: Re: POLL: about arguments of invariable type to methods
Date: 
Message-ID: <muxwsi899gt.fsf@uzeb.lrde.epita.fr>
Rainer Joswig <······@lisp.de> wrote:

> It's also kind of a 'gate'. Within the method the value of the
> parameter is of the class described (unless there is some assignment
> or some other magic). I think the compiler can take advantage of it.

  But just like with a declaration, right ?

> It also helps during debugging. If one always passes objects via
> normal parameters (without type check / method dispatch), then a
> runtime type error may happen deep in the program (with a long stack
> backtrace). If the classes are mentioned in the parameter list, the
> right method will be called or a missing method will be reported
> early.

  Same here: but just like with a declaration, right ?

I'm often oscillating between writing things the simple/shortest way
(without type decl) because declarations clutter the code and are a
nuisance to readability (and sometimes to maintainability as well, when
performance is not an issue), and telling the compiler everything I
know, exactly for the reason you mention above. But there, I would
rather use type decls.

So I guess the real question is the differences there are in using
either type decls or specializers when you compile with different
debug/optimize qualities.

-- 
Resistance is futile. You will be jazzimilated.

Scientific site:   http://www.lrde.epita.fr/~didier
Music (Jazz) site: http://www.didierverna.com

EPITA/LRDE, 14-16 rue Voltaire, 94276 Le Kremlin-Bic�tre, France
Tel. +33 (0)1 44 08 01 85       Fax. +33 (0)1 53 14 59 22
From: Tobias C. Rittweiler
Subject: Re: POLL: about arguments of invariable type to methods
Date: 
Message-ID: <87abf4ri9v.fsf@freebits.de>
Didier Verna <······@lrde.epita.fr> writes:

> Rainer Joswig <······@lisp.de> wrote:
>
> > It's also kind of a 'gate'. Within the method the value of the
> > parameter is of the class described (unless there is some assignment
> > or some other magic). I think the compiler can take advantage of it.
>
>   But just like with a declaration, right ?

No, like CHECK-TYPE.

  -T.
From: Rainer Joswig
Subject: Re: POLL: about arguments of invariable type to methods
Date: 
Message-ID: <joswig-58D30B.21022522082008@news-europe.giganews.com>
In article <···············@uzeb.lrde.epita.fr>,
 Didier Verna <······@lrde.epita.fr> wrote:

> Rainer Joswig <······@lisp.de> wrote:
> 
> > It's also kind of a 'gate'. Within the method the value of the
> > parameter is of the class described (unless there is some assignment
> > or some other magic). I think the compiler can take advantage of it.
> 
>   But just like with a declaration, right ?
> 
> > It also helps during debugging. If one always passes objects via
> > normal parameters (without type check / method dispatch), then a
> > runtime type error may happen deep in the program (with a long stack
> > backtrace). If the classes are mentioned in the parameter list, the
> > right method will be called or a missing method will be reported
> > early.
> 
>   Same here: but just like with a declaration, right ?

No.

* declarations can be safely ignored by a Common Lisp implementation.
  ANSI Common Lisp does not require an implementation to do
  anything with (declare (type ...)).

* ANSI CL does not really say what a compiler has to do if
  it looks at these declarations.

* A compiler may just use the declarations to create
  specialized code - not more.

* Doing runtime type checks based on type declarations
  is not that usual. SBCL will do it. Many others won't.

It would be more comparable to a use of CHECK-TYPE.

> 
> I'm often oscillating between writing things the simple/shortest way
> (without type decl) because declarations clutter the code and are a
> nuisance to readability (and sometimes to maintainability as well, when
> performance is not an issue), and telling the compiler everything I
> know, exactly for the reason you mention above. But there, I would
> rather use type decls.

Type declarations are somehow internal to functions.

Using method parameter lists to describe the expected
classes of arguments is visible from the outside.
One can just check the available methods or print a
method. Based on generic functions there is the
idea of a 'protocol'.


CL-USER 6 > (defun foo (a) (declare (fixnum a)) a)
FOO

CL-USER 7 > (compile *)
FOO
NIL
NIL

CL-USER 8 > #'foo
#<Function FOO 4060010A2C>

You see only a function.




CL-USER 9 > (defmethod bar ((a fixnum)) a)
#<STANDARD-METHOD BAR NIL (FIXNUM) 4020005A6B>


The method shows for what classes it is defined. 

> 
> So I guess the real question is the differences there are in using
> either type decls or specializers when you compile with different
> debug/optimize qualities.

-- 
http://lispm.dyndns.org/
From: Didier Verna
Subject: Re: POLL: about arguments of invariable type to methods
Date: 
Message-ID: <muxsksw95ae.fsf@uzeb.lrde.epita.fr>
Rainer Joswig <······@lisp.de> wrote:

>>   Same here: but just like with a declaration, right ?
>
> No.

  OK, fair enough.

-- 
Resistance is futile. You will be jazzimilated.

Scientific site:   http://www.lrde.epita.fr/~didier
Music (Jazz) site: http://www.didierverna.com

EPITA/LRDE, 14-16 rue Voltaire, 94276 Le Kremlin-Bic�tre, France
Tel. +33 (0)1 44 08 01 85       Fax. +33 (0)1 53 14 59 22
From: Kaz Kylheku
Subject: Re: POLL: about arguments of invariable type to methods
Date: 
Message-ID: <20080822144823.951@gmail.com>
On 2008-08-22, Didier Verna <······@lrde.epita.fr> wrote:
>
>        Suppose you have a generic function func (arg1 arg2). Suppose
> further that in your application, the dispatch might occur on arg1, but
> arg2 will always be of the same type.
>
> How do you guys behave in that situation ? Please select one or several
> options below. All choices must be properly justified.
>
> * Option 1 (well, I do nothing special):
>   (defmethod func ((arg1 type1) arg2) ...)
>   (defmethod func ((arg1 type2) arg2) ...)
>   etc.

This is the best option. Just because some datum is currently observed to be of
the same type all the time doesn't mean that this observation has to be
enshrined in the form of a restriction.

Suppose that FUNC does nothing with ARG2 other than pass it down to some other
method which is capable of handling various types of ARG2. Adding premature
restrictions into FUNC simply causes it to be less transparent.

> * Option 2:
>   (defmethod func ((arg1 type1) (arg2 theonlytype)) ...)
>   (defmethod func ((arg1 type2) (arg2 theonlytype)) ...)
>   etc.

Of course, here ARG2 may be not just exactly of THEONLYTYPE, but any subtype of
that type. So you haven't closed the door against type variation.  The only
difference between option 1 and 2 is that 2 cuts a deeper, narrower slice of
the class hierarchy for ARG2.

What do you achieve by providing a single method of FUNC which specialized ARG2
to THEONLYTYPE? What you achieve is that dispatching FUNC won't work unless the
second argument is in that subtree of the class hirearchy.

What would be the reason for wanting do do that? The reason would be that FUNC
does things with ARG2 that only work with that slice of the class hierarchy.

Well, this is incorrect reasoning, because in Lisp, we can extend methods to
work with anything we want at any time.

Just because the methods used by FUNC to work with ARG2 currently don't work
with anything other than THEONLYTYPE doesn't mean that they won't be able to do
that in the future.  We may in fact be able to make FUNC handle values of ARG2
which are outside of THEONLYTYPE, and we may be able to do this by changing
only the generic functions called by FUNC, without touching FUNC itself.

CLOS is not like the object system of some OO programming languages in which
inheritance determines what methods are applicable to an object.

Option 2 resembles Java or C++, where arg2 has to be statically declared to be
something derived from TheOnlyType so that func can properly work with it as
TheOnlyType. It can't simply be a of type Object, because the Object class
doesn't have all of the the methods that are needed to operate on TheOnlyType.

In Lisp, we don't have this problem. The object's type is known even in a
method where it appears as a parameter specialized to T. Methods don't belong
to a class, but to a generic function, etc.

> * Option 3:
>   (defmethod func ((arg1 type1) arg2) (declare (type theonlytype arg2)) ...)
>   (defmethod func ((arg1 type2) arg2) (declare (type theonlytype arg2)) ...)
>   etc.

Type declarations are largely pointless except when you're optimizing.  Other
than that, the only value is that a Lisp compiler may be able to give you a
compile-time warning here that you have a type mismatch. Declarations are
potentially dangerous, because you're telling the compiler that you promise
that the object is of that type. If you reduce safety, the compiler may
generate code which assumes that it's working on an object of that type.

If you want to assert that some incoming parameter has a given type, try
CHECK-TYPE. This is largely pointless in most CLOS code, because you can
develop the methods to make any type work. It makes sense when the object is
really some basic type dressed up as a class (string, number, cons ...) and the
method's body uses non-generic functions to operate on it.

E.g. dumb example:

 (defmethod associate-with-name ((object sometype) name)
   ;; name is a string or symbol
   (check-type name (or string symbol))
   ...)

Even here, I would suspect that it's premature to be doing such a check.