Thomas said:
[We'll ignore the fact that + in Common Lisp is not a generic function,
but rather a built-in function that does coercion. We'll also ignore
the fact that complex numbers are built-in to Common Lisp, since
neither fact affects the larger issue here.]
Now you can see where the problem will show up. If I want to add a
Complex noun, now I have to add a plus(Complex, Complex) to plus. Which
means I have to modify something in the system package. Uh-oh!
Well, this paragraph is great up until you get to "Uh-oh!".
Which means we have a second "uh-oh": the fact that Thomas A. Russ does
not consider it an "uh-oh" that someone has to modify something in the
system package. Uh-oh!
There is not "Uh-oh!" in Common Lisp at this point. In fact, that it
precisely the point of all of this. You can do this. It is natural.
It is not a problem. You just do it.
You just do it, and then your coworkers string you up by your toenails
and leave you hanging from the sprinkler head above the office Xerox
machine overnight.
Well, why not use a system that makes either one just as easy?
Because no such system exists. It would require needing to scope both
nouns and verbs separately, instead of the verb being disambiguated
based on the noun or vice versa so only one of the two needed
disambiguation by the programmer. Now the programmer has to worry his
head about both!
Then it doesn't matter which is more frequent, because either option
is handled exactly the same way.
Yes. Instead of 84% of the job being easy and the other 16% of it being
hard, or 84% of it being hard and the other 16% being easy, 84% of it is
hard and the other 16% of it is also hard.
That leads to a nicer, more uniform way of
operating with the language, so that the entire language model is easier
to understand.
Easier to understand! You're a laugh riot. Java's basic language model
can be grasped in a day. You've spent more than a week attempting to
convey Lisp's to the people of comp.lang.java.programmer and have
apparently thus confused at least two of them and probably most of them.
Either you're all exceptionally bad at explaining things, down to the
last man, or Lisp is emphatically NOT "easier to understand".
Because you have to monkey around in someone else's namespace and in
someone else's code to add quux.frobnobdicate() when there's already a
frobnobdicate verb and you're addign the quux noun.
I thought I'd explained this?
BTW, in Common Lisp, namespaces are not tied to classes at all.
Big mistake.
They are their own separate entity, so any effect based on namespaces
is equally easy
which is to say, about as easy as ascending Everest without any special
equipment or any clothing and living to tell the tale
regardless of whether you are talking about new classes,
new generic functions or new methods for existing generic functions.
Right. So here is a class of problem where one particular object system
gets in your way.
The solution adopted by CLOS apparently being to make an object system
that gets in the way for EVERY class of problem!
See, for example, my nice hammer and picnic blanket analogy elsewhere
in this thread.
See, for example, the demolition of your hammer and picnic blanket
analogy elsewhere in this thread.
The error in this analysis is conflating the notion of a namespace with
that of a class or function/method.
I did no such thing. I only assumed that classes and/or
functions/methods live IN namespaces.
I assumed that there were three possible ways to resolve names:
package.class.method (perhaps with inheritance) (Java uses this)
package.method.class
package1.class.package2.method
that is, either packages namespace classes which namespace methods (Java
model), packages namespace methods which namespace classes (don't know
what uses this), or packages namespace both methods and classes.
You seem to be saying that Lisp does the last of the three.
The problem, partly, is the combinatorical explosion of possible package
pairs in every invocation of a method when there are now two packages
involved in resolving every method invocation instead of one.
Regardless, there are no errors in my analysis. Ever.
One uniform mechanism that handles both cases with equal ease.
Equality of ease isn't the be all and end all. Making it hard in all
cases is worse than making it easy in some cases and hard in others, as
a general rule.
That is one reason I think the Common Lisp object model is superior.
Another is multiple-dispatch, but that's a completely different
discussion.
Heartburn macros upset stomach, dispatch tables diarrhea! Yay, Pepto-Bismol!
Well, part of that may be conditioning
Nope. I'm a human being, not one of Pavlov's dogs, and the suggestion
otherwise is frankly insulting.
Well, actually that's perhaps a bit strong. Typically the solution to
this is to either write wrapper classes or interfaces to add the new
functionality or else to use static methods on some utility class so
you can write methods that affect classes to which you don't have
source code access.
Perhaps that is the price of encapsulation and having a non-hairy name
resolution system. The amount of bug-hunting time saved by encapsulation
alone in the history of OO probably makes it worth it.
Well, the workaround does have the minor problem that you don't get
dynamic dispatch for the static methods.
Make the utility class have subclasses and change the static method to a
polymorphic one. Well, it still can't be polymorphic in the arguments,
but it can still use the polymorphic methods OF the arguments.
So if you want to have a
hierarchy of classes with different methods, you lose the benefits of
dynamic dispatch and have to manage that yourself. That sounds to me to
be a bit more tedious and potentially error-prone.
It's going to be no matter what. If you want to add more classes and
more methods both, or more classes with dispatch of a two-argument
method based on the types of both parameters, then no simple inheritance
system is going to work and you'll have to manually specify what to do
for every possible pair ... somehow.
When it's one dimensional, you can use inheritance and have each
subclass take care of itself.
As soon as it's two-or-more dimensional, you can't. Some of the
information about class X or whatever is going to be scattered about,
and there's going to be something like a switch statement, pointer
array, or other explicit dispatch mechanism in the source code.
Lisp just sticks you with this by default instead of letting the cases
that CAN be easy actually BE easy.
And yet, oddly enough, in practice there don't seem to be any. It works
just fine.
So you claim. Color me skeptical.
First of all, you don't "change the verb". You simply add a method.
Which changes the verb.
Adding a method to a class is changing the class, right?
Lisp methods live in generic functions instead of classes, right?
Ergo adding a method to a genetic function changes the generic function.
(Subclassing a class doesn't change the base class. But subclassing a
class creates a new class that has its own name and is in its own
package. Adding a method to a generic function does not create a new
generic function that has its own name and is in its own package. It
adds to the existing generic function instead, thus changing it.)
And there is absolutely no reason that the code for your new class has
to be scattered anywhere. You can, if the organization makes the most
sense for your application, put the method definitions IN THE SAME FILE
as the class definition. If it makes more sense to organize around the
generic function instead, then you can. Or you can even mix it.
Your coworkers are going to have SO much fun trying to guess where you
put everything.
Yes ouch.
Simply a misunderstanding of how Common Lisp programs are organized.
I have misunderstood nothing. According to you, Common Lisp programs are
organized at the whims of individual programmers. Not conducive to
scaling up to a large development team, mind you.
This debate really puts you at a bit of a disadvantage,
etc. etc. etc.
I think I've had quite enough of being insulted by you.
The rest of your text has been deleted unread, with one small exception.
Well, we think that there is a fundamental difference between different
sorts of close and prefer to make sure they have different names.
So instead of everything you can "close" having a "close" method, you
end up "close"ing one type, "shut"ting another, "slam"ming a third,
"plug"ging a fourth, and onward to increasingly unintuitive and
unguessable names? Wow, that must REALLY help code readability.