From: Peter Seibel
Subject: Help me overcome yet another bit of Java/Python brain damage
Date: 
Message-ID: <e500013c.0205142112.46a4c204@posting.google.com>
I'm sure this is just another case of my brain not yet having become
One with the Lisp Way but here's my problem:

In languages like Java and Python (to take two examples) that only
have single dispatch, classes act as a namespace. So if I have (in
Java) two classes:

 class A {
    public void foo() { ... }
 }

 class B {
    public void foo() { ... }
 }

then I can have an instances of A and B and can call x.foo() and the
name is resolved appropriately depending on the type of x.

Obviously in Common Lisp I can define a generic function and methods
specialized on A and B to get the equivalent dispatching behavior.
That's not my problem.

What I haven't been able to wrap my brain around is how to use
packages or whatever mechanisms are appropriate to keep the namespace
of my program tidy. If A and B are related they might well be defined
in the same package and then there's only one name for foo and I can
import it into my namespace so that's not really a problem. But
suppose the classes A and B are defined in totally different
libraries, perhaps written by different folks. I assume that they
would then be in different packages. In that case each method foo
would really be <some-package>:foo, assuming they're both exported,
right? So does that mean that if I'm writing a program that wants to
use both classes I have to always qualify which foo I want? That makes
sense given that the relation between the two simple name's 'foo' is
really just coincidental. But it does make things a bit more verbose.

I guess the sort of automatic qualification I get from Java and Python
would be impossible (or at least pretty tricky) in the face of
multi-methods but it is sort of nice. Is there some technique I'm
missing here? Or do I just suck it up and stop worrying about the
verbosity?

I suspect that I may be overusing packages--due to my Java-induced
brain damage I feel compelled to put everything in its own namespace
but that seems to be causing me more problems than it's solving.
Doctor it hurts ... etc. Any advice, either about what to do or what
to read to learn about these issues, would be appreciated.

-Peter

-- 
Peter Seibel
·····@javamonkey.com

From: Thomas F. Burdick
Subject: Re: Help me overcome yet another bit of Java/Python brain damage
Date: 
Message-ID: <xcvwuu528nu.fsf@monsoon.OCF.Berkeley.EDU>
·····@javamonkey.com (Peter Seibel) writes:

> I'm sure this is just another case of my brain not yet having become
> One with the Lisp Way but here's my problem:
> 
> In languages like Java and Python (to take two examples) that only
> have single dispatch, classes act as a namespace. So if I have (in
> Java) two classes:
> 
>  class A {
>     public void foo() { ... }
>  }
> 
>  class B {
>     public void foo() { ... }
>  }
> 
> then I can have an instances of A and B and can call x.foo() and the
> name is resolved appropriately depending on the type of x.
> 
> Obviously in Common Lisp I can define a generic function and methods
> specialized on A and B to get the equivalent dispatching behavior.
> That's not my problem.
> 
> What I haven't been able to wrap my brain around is how to use
> packages or whatever mechanisms are appropriate to keep the namespace
> of my program tidy.

I think the problem you might be having is that you're still thinking
about methods as belonging to classes.  They don't, they're parts of
generic functions.  Your classes are your data structures, and you
should organize them into packages as you see fit.  Your GF's should
also be organized into packages appropriate for them as generic
functions.  I'd reccomend using the DEFGENERIC form, and /not/ putting
it right after a DEFCLASS form.  And if it's an interface function,
don't let it be implicit from a DEFMETHOD, define the generic function
on its own, think out its argument list and write its docstring
seperate from any specific method defined on it.

> If A and B are related they might well be defined in the same
> package and then there's only one name for foo and I can import it
> into my namespace so that's not really a problem. But suppose the
> classes A and B are defined in totally different libraries, perhaps
> written by different folks. I assume that they would then be in
> different packages. In that case each method foo would really be
> <some-package>:foo, assuming they're both exported, right? So does
> that mean that if I'm writing a program that wants to use both
> classes I have to always qualify which foo I want? That makes sense
> given that the relation between the two simple name's 'foo' is
> really just coincidental. But it does make things a bit more
> verbose.

You can also import one of them, and not the other.

> I guess the sort of automatic qualification I get from Java and Python
> would be impossible (or at least pretty tricky) in the face of
> multi-methods but it is sort of nice. Is there some technique I'm
> missing here? Or do I just suck it up and stop worrying about the
> verbosity?
> 
> I suspect that I may be overusing packages--due to my Java-induced
> brain damage I feel compelled to put everything in its own namespace
> but that seems to be causing me more problems than it's solving.
> Doctor it hurts ... etc. Any advice, either about what to do or what
> to read to learn about these issues, would be appreciated.

If you define small packages, the number of symbols exported tends to
be small enough that you don't often get name clashes when importing
from a bunch of them.  Or, I don't.  Plus, when you *do* get a name
clash, the number of GF's in the package you can't import from is
probably small, so you won't be having to qualify your names all over
the place.  I've also been known to make up little packages solely for
the purpose of exporting a small number of symbols imported from
another package, to avoid name-clashes.

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | No to Imperialist war |                        
     ,--'    _,'   | Wage class war!       |                        
    /       /      `-----------------------'                        
   (   -.  |                               
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Gabe Garza
Subject: Re: Help me overcome yet another bit of Java/Python brain damage
Date: 
Message-ID: <1ycdsxva.fsf@anubis.kynopolis.org>
·····@javamonkey.com (Peter Seibel) writes:


> What I haven't been able to wrap my brain around is how to use
> packages or whatever mechanisms are appropriate to keep the
> namespace of my program tidy. <snip> But suppose the classes A and B
> are defined in totally different libraries, perhaps written by
> different folks. <snip> In that case each method foo would really be
> <some-package>:foo, assuming they're both exported, right? So does
> that mean that if I'm writing a program that wants to use both
> classes I have to always qualify which foo I want?

In general, yes.  "FOO" could mean "send an RFC 1035 compliant packet
to udp port 53 of 4.2.2.3" in one package and "send an RFC 2324
compliant request to tcp port 80 of my coffee pot" in another. The
nice thing about packages is that they let people call a rose whatever
they want without bothering other people. :)

If you ever do have a case where "FOO" means a similiar thing in both
packages, you can always write a "FOO" function in whatever package
you're working in that unifies the two.  If that gets monotonous,
write a macro to do it for you (at this point I'll attach the disclaimer
that I'm just beginning to "get" CLOS--hopefully if I'm doing
something incorrect or there's a nicer way someone will speak up):

* 
(defmacro def-unified-generic-function (new-name &rest generic-function-names)
  `(defun ,new-name (&rest args)
     (dolist (name ',generic-function-names)
       (when (compute-applicable-methods (symbol-function name) args)
         (return (apply (symbol-function name) args))))))
DEF-UNIFIED-GENERIC-FUNCTION

* (make-package :a)
#<The A package, 0/9 internal, 0/9 external>

* (make-package :b)
#<The B package, 0/9 internal, 0/9 external>

* (defmethod a::foo ((a (eql 'frog))) 'ribbit)
#<Standard-Method A::FOO ((EQL FROG)) {49609FAD}>

* (defmethod b::foo ((a (eql 'dog))) 'woof)
#<Standard-Method B::FOO ((EQL DOG)) {49614805}>

* (def-unified-generic-function foo a::foo b::foo)
FOO

* (foo 'frog)
RIBBIT

* (foo 'dog)
WOOF

> Or do I just suck it up and stop worrying about the verbosity?

Never stop worrying about verbosity. :)

> Peter Seibel
> ·····@javamonkey.com
        ^^^^^^^^^^

According to Internic, lispmonkey.com is up for grabs.  Lisp users are
evidently pleasantly tasteful. ;)

Gabe Garza
From: Espen Vestre
Subject: Re: Help me overcome yet another bit of Java/Python brain damage
Date: 
Message-ID: <kwit5pkgqi.fsf@merced.netfonds.no>
·····@javamonkey.com (Peter Seibel) writes:

> multi-methods but it is sort of nice. Is there some technique I'm
> missing here? Or do I just suck it up and stop worrying about the
> verbosity?

if the two foo methods can be seen as 'related' and you are in control of
both namespaces, they might be a candidate for a generic function, and
all you have to do is to harmonize the argument list.

Whether you should worry about the verbosity or not depends a lot on
your program. If your program to a large extent uses symbols from a
given package, then it's probably a good idea to USE that package,
to avoid programs that consist almost entirely of package-qualified
symbols.

However, IMHO it's not very often that you want to USE more than one
package (not counting CL). Programs with package-qualified symbols 
can be easier to read.

(Also remember that your packages can have two names, a long descriptive
 one and a short nickname)
-- 
  (espen)
From: Barry Margolin
Subject: Re: Help me overcome yet another bit of Java/Python brain damage
Date: 
Message-ID: <d5vE8.6$rd4.92@paloalto-snr2.gtei.net>
In article <····························@posting.google.com>,
Peter Seibel <·····@javamonkey.com> wrote:
>What I haven't been able to wrap my brain around is how to use
>packages or whatever mechanisms are appropriate to keep the namespace
>of my program tidy. If A and B are related they might well be defined
>in the same package and then there's only one name for foo and I can
>import it into my namespace so that's not really a problem. But
>suppose the classes A and B are defined in totally different
>libraries, perhaps written by different folks. I assume that they
>would then be in different packages. In that case each method foo
>would really be <some-package>:foo, assuming they're both exported,
>right? So does that mean that if I'm writing a program that wants to
>use both classes I have to always qualify which foo I want? That makes
>sense given that the relation between the two simple name's 'foo' is
>really just coincidental. But it does make things a bit more verbose.

Yes, but this verbosity is useful, as it makes the program less ambiguous,
both to the Lisp implementation and also to readers.

Suppose you see an expression like x.drive().  If x's can be some kind of
motor vehicle, then "drive" refers to operating the vehicle, but if x can
be a screw, this presumably refers to the action done by a screwdriver.
Without knowing what x can be, you don't know what this expression is
about.

The other languages you refer to deal with this by requiring static typing
of variables and functions.  So you can look at x's declaration to
determine whether it's a vehicle or a screw.  Lisp is dynamically typed
(those other languages support dynamic typing, but the dynamic type must be
a subtype of the declared static type), so you can't look at the program
and tell which drive() is intended (Lisp supports declarations as well, but
they're not required and are intended for optimization purposes, not
changing the program semantics).

-- 
Barry Margolin, ······@genuity.net
Genuity, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Gareth McCaughan
Subject: Re: Help me overcome yet another bit of Java/Python brain damage
Date: 
Message-ID: <slrnae5rkj.2jpc.Gareth.McCaughan@g.local>
Barry Margolin wrote:

[Peter Seibel:]
> > What I haven't been able to wrap my brain around is how to use
> > packages or whatever mechanisms are appropriate to keep the namespace
> > of my program tidy. If A and B are related they might well be defined
> > in the same package and then there's only one name for foo and I can
> > import it into my namespace so that's not really a problem. But
> > suppose the classes A and B are defined in totally different
> > libraries, perhaps written by different folks. I assume that they
> > would then be in different packages. In that case each method foo
> > would really be <some-package>:foo, assuming they're both exported,
> > right? So does that mean that if I'm writing a program that wants to
> > use both classes I have to always qualify which foo I want? That makes
> > sense given that the relation between the two simple name's 'foo' is
> > really just coincidental. But it does make things a bit more verbose.
> 
> Yes, but this verbosity is useful, as it makes the program less ambiguous,
> both to the Lisp implementation and also to readers.
...
> The other languages you refer to deal with this by requiring static typing
> of variables and functions.  So you can look at x's declaration to
> determine whether it's a vehicle or a screw.

Actually, no. Python is as dynamically typed as Common Lisp.
Method invocation is done dynamically, by looking things up
in hash tables.

-- 
Gareth McCaughan  ················@pobox.com
.sig under construc
From: Marco Antoniotti
Subject: Re: Help me overcome yet another bit of Java/Python brain damage
Date: 
Message-ID: <y6coffgoyc0.fsf@octagon.mrl.nyu.edu>
················@pobox.com (Gareth McCaughan) writes:

> Barry Margolin wrote:
> 
        ...
> ...
> > The other languages you refer to deal with this by requiring static typing
> > of variables and functions.  So you can look at x's declaration to
> > determine whether it's a vehicle or a screw.
> 
> Actually, no. Python is as dynamically typed as Common Lisp.
> Method invocation is done dynamically, by looking things up
> in hash tables.

Ok.  The bets are open.  How long before they re-invent mutlimethods? :)

Cheers

-- 
Marco Antoniotti ========================================================
NYU Courant Bioinformatics Group        tel. +1 - 212 - 998 3488
719 Broadway 12th Floor                 fax  +1 - 212 - 995 4122
New York, NY 10003, USA                 http://bioinformatics.cat.nyu.edu
                    "Hello New York! We'll do what we can!"
                           Bill Murray in `Ghostbusters'.
From: Coby Beck
Subject: Re: Help me overcome yet another bit of Java/Python brain damage
Date: 
Message-ID: <U4SE8.1499$Za.32113@news2.calgary.shaw.ca>
Marco Antoniotti <·······@cs.nyu.edu> wrote in message
····················@octagon.mrl.nyu.edu...
>
> ················@pobox.com (Gareth McCaughan) writes:
> > Actually, no. Python is as dynamically typed as Common Lisp.
> > Method invocation is done dynamically, by looking things up
> > in hash tables.
>
> Ok.  The bets are open.  How long before they re-invent mutlimethods? :)
>

I'm sure you were joking, but here's a serious bet - never.  In Python
methods are defined inside the class definition and they use the obj.method
syntax, so I don't think they wanted to leave that door open.

--
Coby Beck
(remove #\Space "coby 101 @ bigpond . com")
From: Peter Seibel
Subject: Re: Help me overcome yet another bit of Java/Python brain damage
Date: 
Message-ID: <e500013c.0205161645.620e23df@posting.google.com>
"Coby Beck" <·····@mercury.bc.ca> wrote in message news:<···················@news2.calgary.shaw.ca>...
> Marco Antoniotti <·······@cs.nyu.edu> wrote in message
> ····················@octagon.mrl.nyu.edu...
> >
> > ················@pobox.com (Gareth McCaughan) writes:
> > > Actually, no. Python is as dynamically typed as Common Lisp.
> > > Method invocation is done dynamically, by looking things up
> > > in hash tables.
> >
> > Ok.  The bets are open.  How long before they re-invent mutlimethods? :)
> >
> 
> I'm sure you were joking, but here's a serious bet - never.  In Python
> methods are defined inside the class definition and they use the obj.method
> syntax, so I don't think they wanted to leave that door open.

Just out of curiosity, how common is it to really use methods that are
specialized on more than one parameter. I can certainly imagine some
circumstances where it would be quite nice but it also seems (to my
perhaps single-dispatch-language-damaged brain) that specializing on
more than one argument frequently could cause a combinitorial
explosion of methods. Am I missing something or do folks mostly (for
some value of 'mostly') end up using single-dispatch even though it's
possible to use multiple-dispatch?

-Peter

-- 
Peter Seibel
·····@javamonkey.com
From: Erik Naggum
Subject: Re: Help me overcome yet another bit of Java/Python brain damage
Date: 
Message-ID: <3230587176877052@naggum.net>
* Peter Seibel
| Just out of curiosity, how common is it to really use methods that are
| specialized on more than one parameter.

  Any time you have more than one argument to a generic function.  This is
  actually _really_ common.

| I can certainly imagine some circumstances where it would be quite nice
| but it also seems (to my perhaps single-dispatch-language-damaged brain)
| that specializing on more than one argument frequently could cause a
| combinitorial explosion of methods.

  It is not what things could do that should worry you, but what you
  actually do.  Freedom is not a problem to the responsible programmer.

| Am I missing something or do folks mostly (for some value of 'mostly')
| end up using single-dispatch even though it's possible to use
| multiple-dispatch?

  The dispatch is always on all required arguments.  The only way to have
  have single dispatch is to have only one required argument.  If you think
  that specifying the type of a required argument as t means it is no
  longer part of the dispatch, you are simply in error.
-- 
  In a fight against something, the fight has value, victory has none.
  In a fight for something, the fight is a loss, victory merely relief.

  70 percent of American adults do not understand the scientific process.
From: Barry Margolin
Subject: Re: Help me overcome yet another bit of Java/Python brain damage
Date: 
Message-ID: <DL8F8.3$JV3.173@paloalto-snr1.gtei.net>
In article <················@naggum.net>, Erik Naggum  <····@naggum.net> wrote:
>* Peter Seibel
>| Just out of curiosity, how common is it to really use methods that are
>| specialized on more than one parameter.
>
>  Any time you have more than one argument to a generic function.  This is
>  actually _really_ common.
...
>  The dispatch is always on all required arguments.

(not (eq dispatched-on specialized-on))

If all the methods for a generic function have T as the specializer for a
particular argument, then it's effectively not specialized on that
argument.  We even have an abbreviated notation for this case: writing just
the parameter name in the lambda-list, rather than (<name> <specializer>).

I think the intent of Peter's question was: how common is it to use methods
that have non-T specializers on more than one parameter?

-- 
Barry Margolin, ······@genuity.net
Genuity, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Duane Rettig
Subject: Re: Help me overcome yet another bit of Java/Python brain damage
Date: 
Message-ID: <4n0uysm0v.fsf@beta.franz.com>
Barry Margolin <······@genuity.net> writes:

> In article <················@naggum.net>, Erik Naggum  <····@naggum.net> wrote:
> >* Peter Seibel
> >| Just out of curiosity, how common is it to really use methods that are
> >| specialized on more than one parameter.
> >
> >  Any time you have more than one argument to a generic function.  This is
> >  actually _really_ common.
> ...
> >  The dispatch is always on all required arguments.
> 
> (not (eq dispatched-on specialized-on))
> 
> If all the methods for a generic function have T as the specializer for a
> particular argument, then it's effectively not specialized on that
> argument.  We even have an abbreviated notation for this case: writing just
> the parameter name in the lambda-list, rather than (<name> <specializer>).
> 
> I think the intent of Peter's question was: how common is it to use methods
> that have non-T specializers on more than one parameter?

Why not count them?  Obviously, results will vary for each application,
but by doing so one can get a feel for how often the feature is used.

In the following form, the excl::get-objects is Allegro CL specific,
but it is the easiest way I know of to get all objects of a particular
type.  Other styles of accomplishing the same goal can be used,
and most of the rest should be pretty portable to mop-compliant CLs.

In this case an Allegro CL 6.1 alisp had 60 out of 1180 use multiple
non-T specializations.

You could also pprint this result to see the whole list, but I didn't
do that.

CL-USER(1): (flet ((count-spec (spec-list)
		     (let ((count 0))
		       (dolist (spec spec-list count)
			 (unless (eq spec (find-class t))
			   (incf count))))))
	      (let* (res1 res2
		     (a (excl::get-objects 12))
		     (size (aref a 0)))
		(dotimes (i size)
		  (let ((instance (aref a (1+ i))))
		    (when (and (typep instance 'standard-method)
			       (slot-boundp instance 'excl::specializers))
		      (push (cons instance
				  (mop:method-specializers instance))
			    res1))))
		(dolist (meth-spec res1)
		  (when (> (count-spec (cdr meth-spec)) 1)
		    (push meth-spec res2)))
		(format t "Total: ~d  Multiple: ~d~%"
			(length res1) (length res2))
		res2))
Total: 1180  Multiple: 60
((#<STANDARD-METHOD ADD-METHOD (STANDARD-GENERIC-FUNCTION METHOD)>
  #<ACLMOP:FUNCALLABLE-STANDARD-CLASS STANDARD-GENERIC-FUNCTION>
  #<STANDARD-CLASS METHOD>)
 (#<STANDARD-METHOD ACLMOP:SLOT-VALUE-USING-CLASS
    (ACLMOP:FUNCALLABLE-STANDARD-CLASS STANDARD-OBJECT T)>
  #<STANDARD-CLASS ACLMOP:FUNCALLABLE-STANDARD-CLASS>
  #<STANDARD-CLASS STANDARD-OBJECT> #<BUILT-IN-CLASS T>)
 (#<STANDARD-METHOD ACLMOP:SLOT-VALUE-USING-CLASS
    (STANDARD-CLASS STANDARD-OBJECT T)>
  #<STANDARD-CLASS STANDARD-CLASS> #<STANDARD-CLASS STANDARD-OBJECT>
  #<BUILT-IN-CLASS T>)
 (#<STANDARD-METHOD (SETF ACLMOP:SLOT-VALUE-USING-CLASS)
    (T ACLMOP:FUNCALLABLE-STANDARD-CLASS STANDARD-OBJECT T)>
  #<BUILT-IN-CLASS T>
  #<STANDARD-CLASS ACLMOP:FUNCALLABLE-STANDARD-CLASS>
  #<STANDARD-CLASS STANDARD-OBJECT> #<BUILT-IN-CLASS T>)
 (#<STANDARD-METHOD (SETF ACLMOP:SLOT-VALUE-USING-CLASS)
    (T STANDARD-CLASS STANDARD-OBJECT T)>
  #<BUILT-IN-CLASS T> #<STANDARD-CLASS STANDARD-CLASS>
  #<STANDARD-CLASS STANDARD-OBJECT> #<BUILT-IN-CLASS T>)
 (#<STANDARD-METHOD ACLMOP:VALIDATE-SUPERCLASS
    (CLASS ACLMOP:FORWARD-REFERENCED-CLASS)>
  #<STANDARD-CLASS CLASS>
  #<STANDARD-CLASS ACLMOP:FORWARD-REFERENCED-CLASS>)
 (#<STANDARD-METHOD ACLMOP:VALIDATE-SUPERCLASS (CLASS BUILT-IN-CLASS)>
  #<STANDARD-CLASS CLASS> #<STANDARD-CLASS BUILT-IN-CLASS>)
 (#<STANDARD-METHOD ACLMOP:VALIDATE-SUPERCLASS
    (ACLMOP:FUNCALLABLE-STANDARD-CLASS
     ACLMOP:FUNCALLABLE-STANDARD-CLASS)>
  #<STANDARD-CLASS ACLMOP:FUNCALLABLE-STANDARD-CLASS>
  #<STANDARD-CLASS ACLMOP:FUNCALLABLE-STANDARD-CLASS>)
 (#<STANDARD-METHOD ACLMOP:VALIDATE-SUPERCLASS
    (STANDARD-CLASS STANDARD-CLASS)>
  #<STANDARD-CLASS STANDARD-CLASS> #<STANDARD-CLASS STANDARD-CLASS>)
 (#<STANDARD-METHOD ACLMOP:VALIDATE-SUPERCLASS (CLASS CLASS)>
  #<STANDARD-CLASS CLASS> #<STANDARD-CLASS CLASS>)
 ...)
CL-USER(2): 

-- 
Duane Rettig          Franz Inc.            http://www.franz.com/ (www)
1995 University Ave Suite 275  Berkeley, CA 94704
Phone: (510) 548-3600; FAX: (510) 548-8253   ·····@Franz.COM (internet)
From: Kenny Tilton
Subject: Re: Help me overcome yet another bit of Java/Python brain damage
Date: 
Message-ID: <3CE58672.E478BE3E@nyc.rr.com>
Using the inscrutable:

(let ((xgf 0) (xgm 0) (xma 0) (xma2 0)(xmd 0)(xmd2 0))
  (dolist (p '(cl1+ model dbmodel osgraphics mdgraphics archos) (list
xgf xma xma2 xgm xmd xmd2))
    (let ((pkg (find-package p)))
      (do-symbols (sym pkg)
        (multiple-value-bind (sym stat)
            (find-symbol (symbol-name sym) pkg)
          (unless (eql stat :inherited)
            (when (fboundp sym)
              (let ((fn (symbol-function sym)))
                (when (typep fn 'standard-generic-function)
                  (incf xgf)
                  (let ((args
(GENERIC-FUNCTION-ARGUMENT-PRECEDENCE-ORDER fn)) yup)
                    (when (> (length args) 1)
                      (incf xma)
                      (let ((gms (generic-function-methods fn)))
                        (incf xgm (length gms))
                        (dolist (gm gms)
                          (let ((specs (method-specializers gm)))
                            (when (> (count-if-not (lambda (spec) (eql
spec (find-class t))) specs) 1)
                              (incf xmd))
                            (when (find-if-not (lambda (spec) (eql spec
(find-class t))) (rest specs))
                              (setf yup t)
                              (incf xmd2))
                            ))
                        (when yup (incf xma2))))))))))))))

...our little app turns out as: (1040 245 68 702 77 192) Nuff said?

That's 1040 generic functions, only 245 of which even have more than one
argument. I wager lots of slot accessors in the other 800. Skipping the
68 awhile, we find 702 methods defined on the interesting 245 gfs. 77 of
the 702 methods specialize on more than one argument, but 192 of them
specialize on other than the first argument (a better measure, I think).
Using that better measure, 68 of the 245 multi-arg GFs need
multi-methods.

But! This does not matter. It is not a question of how common is the
requirement. This whole thing seems a lot like the multiple inheritance
debate. Sure, you can struggle by without it, but why fight the current?
Sometimes you need it, so it is a Good Thing. btw, it's no good arguing
reductio ad absurdum: "sometimes" is understood to be restricted to
normal programming situations.

Duane Rettig wrote:
> Why not count them?  

-- 

 kenny tilton
 clinisys, inc
 ---------------------------------------------------------------
"Harvey has overcome not only time and space but any objections."
                                                        Elwood P. Dowd
From: Peter Seibel
Subject: Re: Help me overcome yet another bit of Java/Python brain damage
Date: 
Message-ID: <e500013c.0205181904.59aa0099@posting.google.com>
Kenny Tilton <·······@nyc.rr.com> wrote in message news:<·················@nyc.rr.com>...

[snip extremely cool demonstration of the reflective power of lisp]

> But! This does not matter. It is not a question of how common is the
> requirement. This whole thing seems a lot like the multiple inheritance
> debate. Sure, you can struggle by without it, but why fight the current?
> Sometimes you need it, so it is a Good Thing. btw, it's no good arguing
> reductio ad absurdum: "sometimes" is understood to be restricted to
> normal programming situations.

Fair enough. I was just trying to get a sense of where multi-methods
fit in the Lisp programmer's bag of tricks, not whether they should be
used or not. Another way to phrase my question could be: "How often do
seasoned Lisp programmers find that the requirements of their program
naturally lead to using multi-methods, so that I--not having had the
experience to develop reliable judgement in these matters myself--can
get some sense of whether I'm over using or under using them." Just
looking for a rule of thumb.

-Peter

-- 
Peter Seibel
·····@javamonkey.com
From: Kenny Tilton
Subject: Re: Help me overcome yet another bit of Java/Python brain damage
Date: 
Message-ID: <3CE739DC.7918B79C@nyc.rr.com>
Peter Seibel wrote:
> 
> Another way to phrase my question could be: "How often do
> seasoned Lisp programmers find that the requirements of their program
> naturally lead to using multi-methods, so that I--not having had the
> experience to develop reliable judgement in these matters myself--can
> get some sense of whether I'm over using or under using them."

Someone looking at my code once remarked he had never seen lambdas used
so much. What a way to look at code! Reminded me of Emperor Joseph II's
"Too many notes, my dear Mozart."

I have many direct ways of knowing when I am writing crud; why look to
arbitrary measures?

OTOH, having belatedly grasped the power of special variables in one
role within our app, I have now noticed another place where they will
serve beautifully, and I was led to all this only by a couple of folks
here on c.l.l, singing their praises, so maybe there is something to
your scheme of assessing code quality by comparing one's feature usage
rate with those of the Masters. :)

-- 

 kenny tilton
 clinisys, inc
 ---------------------------------------------------------------
"Harvey has overcome not only time and space but any objections."
                                                        Elwood P. Dowd
From: Peter Seibel
Subject: Re: Help me overcome yet another bit of Java/Python brain damage
Date: 
Message-ID: <e500013c.0205191223.32ec622@posting.google.com>
Kenny Tilton <·······@nyc.rr.com> wrote in message news:<·················@nyc.rr.com>...
> Peter Seibel wrote:
> > 
> > Another way to phrase my question could be: "How often do
> > seasoned Lisp programmers find that the requirements of their program
> > naturally lead to using multi-methods, so that I--not having had the
> > experience to develop reliable judgement in these matters myself--can
> > get some sense of whether I'm over using or under using them."
> 
> Someone looking at my code once remarked he had never seen lambdas used
> so much. What a way to look at code! Reminded me of Emperor Joseph II's
> "Too many notes, my dear Mozart."
> 
> I have many direct ways of knowing when I am writing crud; why look to
> arbitrary measures?

Because *I* don't yet have direct ways of knowing. For Lisp, that is.
And I don't want to just apply my own judgement that has been honed in
other contexts (Java) to a context (Lisp) where it is as likely to
mislead me as to provide good guidence. Or that's my theory. Anyway,
I'm sure as I write more and more code I'll form my own judgements
that apply well to Lisp and will be perfectly happy to use any feature
whenever it seems called for.

> OTOH, having belatedly grasped the power of special variables in one
> role within our app, I have now noticed another place where they will
> serve beautifully, and I was led to all this only by a couple of folks
> here on c.l.l, singing their praises, so maybe there is something to
> your scheme of assessing code quality by comparing one's feature usage
> rate with those of the Masters. :)

That's exactly right. It's like learning how to paint or compose or
play an instrument: as a beginner, knowing nothing you're better off
imitating the Masters as it's unlikely you'll spontaneously invent
something better. As you gain your own experience you eventually
develop your own understanding of why the Masters use certain forms or
techniques and, more important, an understanding of when you ought to
break the "rules". Anyway, that's my philosophy. There are others.

-Peter

-- 
Peter Seibel
·····@javamonkey.com
From: Joe Marshall
Subject: Re: Help me overcome yet another bit of Java/Python brain damage
Date: 
Message-ID: <bkZE8.6138$Bn5.2636911@typhoon.ne.ipsvc.net>
"Peter Seibel" <·····@javamonkey.com> wrote in message ·································@posting.google.com...
>
> Just out of curiosity, how common is it to really use methods that are
> specialized on more than one parameter.

Quite frequently.

> I can certainly imagine some
> circumstances where it would be quite nice but it also seems (to my
> perhaps single-dispatch-language-damaged brain) that specializing on
> more than one argument frequently could cause a combinitorial
> explosion of methods.

It could, but remember that type T covers a lot of ground.  It is rare
that a `generic' function has behavior so complicated that it makes
sense to specify its actions separately for lots of `leaf' types.

> Am I missing something or do folks mostly (for
> some value of 'mostly') end up using single-dispatch even though it's
> possible to use multiple-dispatch?

You just haven't written enough code using multi-dispatch.
From: Barry Margolin
Subject: Re: Help me overcome yet another bit of Java/Python brain damage
Date: 
Message-ID: <w2dF8.19$JV3.84@paloalto-snr1.gtei.net>
In article <······················@typhoon.ne.ipsvc.net>,
Joe Marshall <·············@attbi.com> wrote:
>
>"Peter Seibel" <·····@javamonkey.com> wrote in message
>·································@posting.google.com...
>> I can certainly imagine some
>> circumstances where it would be quite nice but it also seems (to my
>> perhaps single-dispatch-language-damaged brain) that specializing on
>> more than one argument frequently could cause a combinitorial
>> explosion of methods.
>
>It could, but remember that type T covers a lot of ground.  It is rare
>that a `generic' function has behavior so complicated that it makes
>sense to specify its actions separately for lots of `leaf' types.

To expand on this, what you're likely to see is a bunch of methods that
specialize on different types of parameter 1, a bunch that specialize on
parameter 2, and maybe a small number that specialize on specific
combinations of both parameters.  Also, these latter cases will most often
involve mid-level classes, not lots of classes at the bottom of the
hierarchy.  While the possibility exists to enumerate all the combinations
of classes, it's not usually necessary -- most activities generalize pretty
well.

-- 
Barry Margolin, ······@genuity.net
Genuity, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Marco Antoniotti
Subject: Re: Help me overcome yet another bit of Java/Python brain damage
Date: 
Message-ID: <y6cwuu2zthi.fsf@octagon.mrl.nyu.edu>
·····@javamonkey.com (Peter Seibel) writes:

> "Coby Beck" <·····@mercury.bc.ca> wrote in message news:<···················@news2.calgary.shaw.ca>...

        ...

> Just out of curiosity, how common is it to really use methods that are
> specialized on more than one parameter. I can certainly imagine some
> circumstances where it would be quite nice but it also seems (to my
> perhaps single-dispatch-language-damaged brain) that specializing on
> more than one argument frequently could cause a combinitorial
> explosion of methods. Am I missing something or do folks mostly (for
> some value of 'mostly') end up using single-dispatch even though it's
> possible to use multiple-dispatch?

The question is not how common it is, but whether there are situations
that warrant it.  The answer to that is the "Visitor Pattern", how it
looks in Python, C++ and Java, and it looks in CL.

Apart from that I find myself using a lot of EQL specializers these
days.  Multimethods are perfect for this, and you get some of the
pattern matching that you have in *ML languages.

        (defgeneric foo (x y))

        (defmethod foo ((x some-class) (y t))
           (error 'unimplemented))

        (defmethod foo ((x some-class) (y (eql :something))) ...)
        (defmethod foo ((x some-class) (y (eql :somethingelse))) ...)


and so on.  In this ways it becomes trivial to do "per case" (or was
it "data driven"?) programming.

This, IMHO is enough to warrant multimethods.

Cheeers

-- 
Marco Antoniotti ========================================================
NYU Courant Bioinformatics Group        tel. +1 - 212 - 998 3488
719 Broadway 12th Floor                 fax  +1 - 212 - 995 4122
New York, NY 10003, USA                 http://bioinformatics.cat.nyu.edu
                    "Hello New York! We'll do what we can!"
                           Bill Murray in `Ghostbusters'.
From: Barry Margolin
Subject: Re: Help me overcome yet another bit of Java/Python brain damage
Date: 
Message-ID: <I8aF8.13$JV3.61@paloalto-snr1.gtei.net>
In article <···············@octagon.mrl.nyu.edu>,
Marco Antoniotti  <·······@cs.nyu.edu> wrote:
>The question is not how common it is, but whether there are situations
>that warrant it.

Is that really the right question?  You can come up with situations that
warrant just about anything, but no language can have everything.  So
whether a feature is really warranted depends on how important those
situations are (and commonness will probably be a factor in this), how hard
it is to accomplish them without the feature being built into the language,
and the impact adding the feature has on the rest of the language.

-- 
Barry Margolin, ······@genuity.net
Genuity, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Marco Antoniotti
Subject: Re: Help me overcome yet another bit of Java/Python brain damage
Date: 
Message-ID: <y6coffezjsc.fsf@octagon.mrl.nyu.edu>
Barry Margolin <······@genuity.net> writes:

> In article <···············@octagon.mrl.nyu.edu>,
> Marco Antoniotti  <·······@cs.nyu.edu> wrote:
> >The question is not how common it is, but whether there are situations
> >that warrant it.
> 
> Is that really the right question?  You can come up with situations that
> warrant just about anything, but no language can have everything.  So
> whether a feature is really warranted depends on how important those
> situations are (and commonness will probably be a factor in this), how hard
> it is to accomplish them without the feature being built into the language,
> and the impact adding the feature has on the rest of the language.

Well, I will agree with your statement.  Let's say that I was kind of
answering the argument that I perceived being there (in Coby's message
I believe), that went like: why do you need mutlimethods at all?

Since we do have multimethods, and since they are useful, I came up
with my rethorical argument as well.

Cheers

-- 
Marco Antoniotti ========================================================
NYU Courant Bioinformatics Group        tel. +1 - 212 - 998 3488
719 Broadway 12th Floor                 fax  +1 - 212 - 995 4122
New York, NY 10003, USA                 http://bioinformatics.cat.nyu.edu
                    "Hello New York! We'll do what we can!"
                           Bill Murray in `Ghostbusters'.
From: Coby Beck
Subject: Re: Help me overcome yet another bit of Java/Python brain damage
Date: 
Message-ID: <47eF8.91261$xS2.7194767@news1.calgary.shaw.ca>
Marco Antoniotti <·······@cs.nyu.edu> wrote in message
····················@octagon.mrl.nyu.edu...
>
> Barry Margolin <······@genuity.net> writes:
> > Is that really the right question?  You can come up with situations that
> > warrant just about anything, but no language can have everything.  So
> > whether a feature is really warranted depends on how important those
> > situations are (and commonness will probably be a factor in this), how
hard
> > it is to accomplish them without the feature being built into the
language,
> > and the impact adding the feature has on the rest of the language.
>
> Well, I will agree with your statement.  Let's say that I was kind of
> answering the argument that I perceived being there (in Coby's message
> I believe), that went like: why do you need mutlimethods at all?

Actually it was Peter Seibel, the OP who asked it below one of my messages.

> Since we do have multimethods, and since they are useful, I came up
> with my rethorical argument as well.

I agree they are useful.  I can't say I use them very often, but I am always
aware of that choice and usually quite happy when it is the solution of the
day.  Barry's point of allowing for specializing on the second parameter is
another way it is useful.

--
Coby Beck
(remove #\Space "coby 101 @ bigpond . com")
From: Thomas F. Burdick
Subject: Re: Help me overcome yet another bit of Java/Python brain damage
Date: 
Message-ID: <xcvznyxb917.fsf@apocalypse.OCF.Berkeley.EDU>
·····@javamonkey.com (Peter Seibel) writes:

> "Coby Beck" <·····@mercury.bc.ca> wrote in message news:<···················@news2.calgary.shaw.ca>...
> > Marco Antoniotti <·······@cs.nyu.edu> wrote in message
> > ····················@octagon.mrl.nyu.edu...
> > >
> > > ················@pobox.com (Gareth McCaughan) writes:
> > > > Actually, no. Python is as dynamically typed as Common Lisp.
> > > > Method invocation is done dynamically, by looking things up
> > > > in hash tables.
> > >
> > > Ok.  The bets are open.  How long before they re-invent mutlimethods? :)
> > >
> > 
> > I'm sure you were joking, but here's a serious bet - never.  In Python
> > methods are defined inside the class definition and they use the obj.method
> > syntax, so I don't think they wanted to leave that door open.
> 
> Just out of curiosity, how common is it to really use methods that are
> specialized on more than one parameter. I can certainly imagine some
> circumstances where it would be quite nice but it also seems (to my
> perhaps single-dispatch-language-damaged brain) that specializing on
> more than one argument frequently could cause a combinitorial
> explosion of methods. Am I missing something or do folks mostly (for
> some value of 'mostly') end up using single-dispatch even though it's
> possible to use multiple-dispatch?

I think I know what kind of potential combinatorial explosion you are
referring to, but it's only an issue if you write your code poorly.
For example, say I have some function that does MOP stuff:

  (defgeneric foo (class1 class2 class3))

The problem is that I use CMUCL, which has kind of a disjoint between
the MOP and the rest of CLOS.  MOP:FIND-CLASS and CL:FIND-CLASS return
different objects, so it makes it unusually important to accept
symbolic class names.  So, I want to be able to have any of the
arguments be sybols or classes.  While that gives (expt 2 3) possible
combinations, I only have to write (+ 3 1) methods.

  (defmethod foo ((class1 symbol) class2 class3)
    (foo (mop:find-class class1) class2 class3))

  (defmethod foo (class1 (class2 symbol) class3)
    (foo class1 (mop:find-class class2) class3))

  (defmethod foo (class1 class2 (class3 symbol))
    (foo class1 class2 (mop:find-class class3)))

  (defmethod foo ((class1 mop:standard-class)
                  (class2 mop:standard-class)
                  (class3 mop:standard-class))
    (do-something-useful))

This is pretty standard OOP fare, but maybe the very different syntax
dazzled you a bit?

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | No to Imperialist war |                        
     ,--'    _,'   | Wage class war!       |                        
    /       /      `-----------------------'                        
   (   -.  |                               
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Peter Seibel
Subject: Re: Help me overcome yet another bit of Java/Python brain damage
Date: 
Message-ID: <e500013c.0205181913.4c411033@posting.google.com>
···@apocalypse.OCF.Berkeley.EDU (Thomas F. Burdick) wrote in message news:<···············@apocalypse.OCF.Berkeley.EDU>...
> ·····@javamonkey.com (Peter Seibel) writes:

[snip]
 
> > Just out of curiosity, how common is it to really use methods that are
> > specialized on more than one parameter. I can certainly imagine some
> > circumstances where it would be quite nice but it also seems (to my
> > perhaps single-dispatch-language-damaged brain) that specializing on
> > more than one argument frequently could cause a combinitorial
> > explosion of methods. Am I missing something or do folks mostly (for
> > some value of 'mostly') end up using single-dispatch even though it's
> > possible to use multiple-dispatch?
> 
> I think I know what kind of potential combinatorial explosion you are
> referring to, but it's only an issue if you write your code poorly.
> For example, say I have some function that does MOP stuff:
> 
>   (defgeneric foo (class1 class2 class3))
> 
> The problem is that I use CMUCL, which has kind of a disjoint between
> the MOP and the rest of CLOS.  MOP:FIND-CLASS and CL:FIND-CLASS return
> different objects, so it makes it unusually important to accept
> symbolic class names.  So, I want to be able to have any of the
> arguments be sybols or classes.  While that gives (expt 2 3) possible
> combinations, I only have to write (+ 3 1) methods.
> 
>   (defmethod foo ((class1 symbol) class2 class3)
>     (foo (mop:find-class class1) class2 class3))
> 
>   (defmethod foo (class1 (class2 symbol) class3)
>     (foo class1 (mop:find-class class2) class3))
> 
>   (defmethod foo (class1 class2 (class3 symbol))
>     (foo class1 class2 (mop:find-class class3)))
> 
>   (defmethod foo ((class1 mop:standard-class)
>                   (class2 mop:standard-class)
>                   (class3 mop:standard-class))
>     (do-something-useful))
> 
> This is pretty standard OOP fare, but maybe the very different syntax
> dazzled you a bit?

There's lots of things that dazzle me about Lisp. ;-) But for whatever
reason I hadn't thought of this technique (probably because I haven't,
as another poster surmised, actually written enough multi-method-based
code) which in retrospect is an obvious analogue to using overloaded
methods in, say, Java, to  implement the equivalent of &optional
arguments. Thanks.

-Peter

-- 
Peter Seibel
·····@javamonkey.com

> 
> -- 
>            /|_     .-----------------------.                        
>          ,'  .\  / | No to Imperialist war |                        
>      ,--'    _,'   | Wage class war!       |                        
>     /       /      `-----------------------'                        
>    (   -.  |                               
>    |     ) |                               
>   (`-.  '--.)                              
>    `. )----'
From: Michael Hudson
Subject: Re: Help me overcome yet another bit of Java/Python brain damage
Date: 
Message-ID: <lkbsbgou17.fsf@pc150.maths.bris.ac.uk>
Marco Antoniotti <·······@cs.nyu.edu> writes:

> ················@pobox.com (Gareth McCaughan) writes:
> 
> > Actually, no. Python is as dynamically typed as Common Lisp.
> > Method invocation is done dynamically, by looking things up
> > in hash tables.
> 
> Ok.  The bets are open.  How long before they re-invent mutlimethods? :)

I've tried.  It's hard to come up with a sensible syntax.

Oh?  You didn't really expect an answer?  Never mind.

Cheers,
M.

-- 
  I don't remember any dirty green trousers.
                                             -- Ian Jackson, ucam.chat
From: Marco Antoniotti
Subject: Re: Help me overcome yet another bit of Java/Python brain damage
Date: 
Message-ID: <y6cg00sorqt.fsf@octagon.mrl.nyu.edu>
Michael Hudson <···@python.net> writes:

> Marco Antoniotti <·······@cs.nyu.edu> writes:
> 
> > ················@pobox.com (Gareth McCaughan) writes:
> > 
> > > Actually, no. Python is as dynamically typed as Common Lisp.
> > > Method invocation is done dynamically, by looking things up
> > > in hash tables.
> > 
> > Ok.  The bets are open.  How long before they re-invent mutlimethods? :)
> 
> I've tried.  It's hard to come up with a sensible syntax.

Syntax? :)

> 
> Oh?  You didn't really expect an answer?  Never mind.

No.  I just want to take bets :)  I may make money off this :)

Cheers

-- 
Marco Antoniotti ========================================================
NYU Courant Bioinformatics Group        tel. +1 - 212 - 998 3488
719 Broadway 12th Floor                 fax  +1 - 212 - 995 4122
New York, NY 10003, USA                 http://bioinformatics.cat.nyu.edu
                    "Hello New York! We'll do what we can!"
                           Bill Murray in `Ghostbusters'.
From: Edward O'Connor
Subject: Re: Help me overcome yet another bit of Java/Python brain damage
Date: 
Message-ID: <873cwrbwwd.fsf@stewart.floobin.cx>
> > Actually, no. Python is as dynamically typed as Common Lisp.
> > Method invocation is done dynamically, by looking things up in
> > hash tables.
> 
> Ok. The bets are open. How long before they re-invent
> mutlimethods? :)

Quoting from:
http://mail.python.org/pipermail/python-announce-list/2000-January/000419.html

"I'd like to announce the existence of Multimethod.py, a package
that implements real (eg, CLOS/Cecil/Dylan) multimethods for
Python. These are nifty for oodles of reasons,[...]

"You can find it on my webpage at:

  <URI:http://www.sff.net/people/neelk/open-source>"


Ted

-- 
Edward O'Connor
···@oconnor.cx
From: Marco Antoniotti
Subject: Re: Help me overcome yet another bit of Java/Python brain damage
Date: 
Message-ID: <y6c8z6jpvtv.fsf@octagon.mrl.nyu.edu>
Edward O'Connor <···@oconnor.cx> writes:

> > > Actually, no. Python is as dynamically typed as Common Lisp.
> > > Method invocation is done dynamically, by looking things up in
> > > hash tables.
> > 
> > Ok. The bets are open. How long before they re-invent
> > mutlimethods? :)
> 
> Quoting from:
> http://mail.python.org/pipermail/python-announce-list/2000-January/000419.html
> 
> "I'd like to announce the existence of Multimethod.py, a package
> that implements real (eg, CLOS/Cecil/Dylan) multimethods for
> Python. These are nifty for oodles of reasons,[...]
> 
> "You can find it on my webpage at:
> 
>   <URI:http://www.sff.net/people/neelk/open-source>"
> 
> 
> Ted

Good. You win.  Unfortunately nobody had bet anything yet. :)

So Python can now claim yet another re-invention of the wheel :)

Cheers

-- 
Marco Antoniotti ========================================================
NYU Courant Bioinformatics Group        tel. +1 - 212 - 998 3488
719 Broadway 12th Floor                 fax  +1 - 212 - 995 4122
New York, NY 10003, USA                 http://bioinformatics.cat.nyu.edu
                    "Hello New York! We'll do what we can!"
                           Bill Murray in `Ghostbusters'.
From: Kenny Tilton
Subject: Re: Help me overcome yet another bit of Java/Python brain damage
Date: 
Message-ID: <3CE47A03.FFF8D74D@nyc.rr.com>
Marco Antoniotti wrote:
> So Python can now claim yet another re-invention of the wheel :)

I see it as the day being that much closer when someone in the Python
camp notices they are so close to CL that they may as well close up shop
and use CL.

Come to think of it, we should do a Trojan horse on them: send in our
best and brightest to add macros and special variables to Python, keep
it up until the light goes on.

:)

-- 

 kenny tilton
 clinisys, inc
 ---------------------------------------------------------------
"Harvey has overcome not only time and space but any objections."
                                                        Elwood P. Dowd
From: Hannah Schroeter
Subject: Re: Help me overcome yet another bit of Java/Python brain damage
Date: 
Message-ID: <acaqfr$46p$1@c3po.schlund.de>
Hello!

In article <·················@nyc.rr.com>,
Kenny Tilton  <·······@nyc.rr.com> wrote:

>Come to think of it, we should do a Trojan horse on them: send in our
>best and brightest to add macros and special variables to Python, keep
>it up until the light goes on.

How about writing a reader macro for CL which transforms Python
syntax into your runn-of-the-mill Lisp code? Something like the
elisp emulation package, IIRC in clocc :-)

Kind regards,

Hannah.