Alessio said:
Sure they do. Either two identical names collide, or they reside in
distinct namespaces. You just insinuated that methods and classes do not
reside in distinct namespaces (quoted material, very top of this post).
Therefore if one of each with the same name resides in a single one,
they collide. It's elementary logic, Alessio.
Only if he/she wants to use MY:frobnobdicate with YOUR:quux, which may
or may not make sense depending on what MY:frobnobdicate and YOUR:quux
mean.
In your example, though, this combination was used, along with all three
other combinations of whose frobnobdicate and whose quux.
it probably does not make much sense to do
(defmethod db-library

pen-transaction ((transaction-manager picture-
library:jpeg-picture)) ...whatever...)
I don't see why not. Storing jpegs as BLOBs in a DB is not unheard-of.
You can have encapsulation even if packages are not tied to classes,
since packages have the concept of internal ("private") and external
("public") symbols.
You can have THAT level of encapsulation in C, FFS. (Using or
withholding "extern" and with judicious omissions from the .h file.)
Which, due to the generality of symbols,
automatically can make private/public anything - classes, functions,
variables, anything that can be named by a symbol.
But only at the granularity of whole packages. Not single classes or
smaller scales, aside from what Series elsewhere described as the
"natural encapsulation" of functions whereby ordinarily changes to the
function's body that don't change its signature or semantics don't break
code elsewhere in the program.
You *need* to specify 2 packages only if you have imported *neither*
symbol in your package, which is quite unusual. Else, you can use
symbols unqualified, and this is the general case.
Verb collisions are the issue. So many things will have close methods,
for example. If you use several of them in one area, you'll only be able
to import one and you'll have to FQ the others. Unless of course the
library designer did as someone else recently suggested here and cracked
open his thesaurus. (Yuk.)
This is the flipside to the many-times-more-nouns-than-verbs thing. A
lot of verb collisions occur among a small set of especially
frequently-used verbs. The power-law scaling of word frequencies serves
to amplify the difference of nearly an order of magnitude in the numbers
of nouns vs. verbs.
Guess what? It has, it's the class named T.
They have a problem with code readability or something? That reads like
true, a temporary, or, worst, a generic type parameter, not a class name.
Nobody mentioned method combinations, and I won't now - already too
many things being discussed - but that's another of the big strengths
of CLOS.
I'll interpret this as "another of the big headaches of CLOS". It sounds
like one of the biggest headaches of Lisp is the sheer amount of stuff,
special forms, &c. that you'd have to learn to be able to read other
peoples' code written in the stuff. OK, perl is much worse, but still.
A fantasy example:
(defgeneric print (object medium))
(defmethod print ((object text) (medium terminal)) ...)
(defmethod print ((object text) (medium laser-printer)) ...)
(defmethod print ((object image) (medium terminal)) ...)
(defmethod print ((object image) (medium laser-printer)) ...)
This is easy to express in CLOS, not that easy to express in Java or C+
+ or Python or any other single-dispatch OO system.
Eh, Java has already expressed this and very easily. Look at the Java2D
API. Corresponding to "text" and "image" we have Shape and subclasses,
which can draw themselves onto a Graphics2D (polymorphically). And
Graphics2D is gotten by various means, but is itself a polymorphic class
that knows how to turn turtle-graphics commands using the generic
Graphics2D interface into results on particular media. If you're
prepping a print job you'll draw on one subclass of Graphics2D, if on a
window you'll get another. No terminals though, Java2D is all about
bitmapped graphics.
For your example a Java programmer might make a Printable interface with
a printOn(Medium) method specified. Implementations would call Medium
methods such as outputString(String), toggleBold(), or whatever was
supported. VT100Terminal would send appropriate escape sequences for
things like toggleBold() and the string for outputString(String) to
System.out. LaserPrinter would send suitable printer control commands to
the parallel port.
Then you could have aText.printOn(aVT100), etc.
I don't know what you were hoping to do with images there; error when
the target was a terminal and print on a printer? That might require
Java2D and adding a getGraphics() to Medium, returning null for
VT100Terminal -- an OOB not-available value printOn would check for.
Image might attempt to gracefully degrade showing a Lynx-style "[IMAGE]"
or attempting to cruft up an ASCII-art approximation using some
algorithm or another, or just complain with an exception. Alternatively,
Medium could throw a GraphicsUnsupportedException or similar from
getGraphics() instead of returning null if the target didn't support
graphics.
All of this with single dispatch.
Where I find myself most wanting double dispatch is when there's two
type hierarchies that need some combined operations, but there's no
natural way to orthogonalize the operations. With most forms of drawing
or printing, though, you can turn the document into a series of
primitive operations of some kind at the document end, and implement the
primitive operations on the medium end. The Graphics2D class is a good
one to check out as its API contains such a set of primitive operations.
http://java.sun.com/javase/6/docs/api/java/awt/Graphics2D.html
A lot of the methods are inherited from
http://java.sun.com/javase/6/docs/api/java/awt/Graphics.html
One option is to arbitrarily make one of the two classes "more
important":
interface Printable {
public void printOn(Medium medium);
}
class Text implements Printable {
public void printOn(Medium medium) {
if(medium instanceof Terminal) {
...
} else if(medium instanceof LaserPrinter) {
...
} else {
throw new IllegalArgumentException("Don't know how to print " +
this + " on " + medium);
}
}
}
...same for Image...
Bletcherous. See above for the alternative that avoids switch, enum,
instanceof, or any other similar kludge.
Another option is to concentrate the printing code in a third class:
abstract class Printer {
public void print(Printable object, Medium medium) {
if((object instanceof Text) && (medium instanceof Terminal)) {
...
} else ... //you get the idea
}
}
Neither option is good imho, since both force you to explicitly code
dispatch tables and manually maintain them - exactly what you DON'T
have to do with CLOS.
Except that a) I just showed how to avoid doing so -- in this case at
least -- in Java, and b) Anonymous C Lisper does exactly that with CLOS
to judge by his one major post containing sample Lisp code.
That statement makes several insulting and false insinuations about me.
I'm sorry, but I genuinely think [repeats insults]
Think what you want, but please restrain the urge to blurt out uncivil
things in public. Weren't you taught any manners as a child?
Then, it changes the class
It does not.
*in this context*, the following analogy more or less holds:
generic function --> abstract class
method --> concrete class
more specific method --> concrete subclass
Except when you subclass a class, you're making an altered copy in
essence; when you add to a generic method, you're fiddling with the
original, not a copy, and maybe it wasn't "yours".
See above re: MY:frobnobdicate with YOUR:quux.
The generic function is not changed any more than the abstract class
is.
Sure it is. The abstract class still contains exactly the same methods.
The generic function contains new ones. Viewing both as lists, one grew
and one didn't.
That's subjective, and I won't debate it here. I prefer the there's-
more-than-one-way-to-do-it philosophy, but it's just personal
preference.
It's a preference that suggests you tend to work alone or on a small
team. Working on a large team results in there's-too-many-ways-to-do-it
being a very real possibility, with everyone doing the same "it"
differently and everyone having to know every single language feature,
however obscure.
Without the javadocs Java's standard library might plausibly have caused
some trouble of a similar nature by its sheer size. It helps though that
there's generally only one or a few clearly-near-optimum use patterns
for a given job, and that everything (mostly) has descriptive names too.
ListIterator and MessageDigest are names that convey quite a bit about
what they do; defgeneric and #:cl #:foo somewhat less so.
Which topic came up again; see above.
I personally don't think Java the language + standard library is
generally bloated. I believe some widely-adopted practices, and some
widely-used libraries, do favor bloat in Java.
I'd agree with that assessment. But I didn't say *you specifically* said
Java code looked like vomit. Certainly *one* of you did, though, a few
days ago, and others appeared to hold comparable opinions.
I also don't think Java looks like vomit, if you don't make it look
like that. Though I do think that expressing some things in Java is
not as easy as in Lisp.
Including especially the things that will fry your coworkers' brains, no
doubt. (Though you can be pretty evil with the reflection API, static
initializers and constructors with side effects, asserts with side
effects, ClassLoader tricks, and so forth.)
For what I know, both Java and Common Lisp have been accused of being
"bloated" for a period of their respective history.
Java's library and Common Lisp's object system, I'll bet. But users
don't have to learn the whole library and do have to learn the whole
object system...
I can only say - only personal experience, no scientific data - that
writing both Java and Common Lisp, I generally find Common Lisp more
expressive and more readable, even if I have much more experience in
Java than in Lisp. This might simply mean Lisp is more close than Java
to my own way of thinking.
Subjective statements like that cannot resolve many of the questions
here; at worst they might fan the flames, though maybe with "Lew"
apparently bowing out of it the worst of those are over.
I actually don't think most people here disagree with my main thesis,
which is that Java and Lisp have relative tradeoffs, with neither
invariably superior to the other. The sticking points all seem to
involve specific things claimed to make Lisp superior at one time or
another by only a handful of the most extreme pro-Lisp partisans, and
why these features don't *actually* do so.