T
Thomas A. Russ
Seamus MacRae said:(e-mail address removed) wrote:
Eh, I don't see any namespace related anything in that. I do see
manually managed dispatch tables and plenty of other migraine-inducers
though.
Precisely. It doesn't enter into this at all, in most cases.
It is nicely in the background for when you need it, but it doesn't
intrude into your day-to-day programming most of the time.
Suppose you created all of that stuff and then someone else wanted to
frobnobdicate their quux objects. Now they have to mess with the
defgeneric ... etc. in your namespace, in your source code...
Um, no.
They don't need to do anything with DEFGENERIC at all, since that
function is already present.
They just add their own method by just doing
(defmethod frobnicate ((foo quux) (baz quux))
..body)
and this method gets added. They do this in their own source code.
They don't need to do anything to your source code.
Perhaps you were confused because the poster to which you were replying
used one of the alternate convenience techniques for adding methods to a
generic function.
That is ONE way to do it, but in Lisp there are often multiple ways to
accomplish the same thing. In this case, there is also a stand-alone
DEFMETHOD that could be used instead. Having a lot of flexibility in a
language takes some getting used to, but the philosophy of Lisp is to
provide a wide range of tools and techniques and rely upon programmers
being smart enough to pick the tool that is most appropriate to the
problem at hand.
I think one thing people are missing here is that real software projects
are typically worked on by teams, and even lone developers typically use
third-party and system libraries. That divides the typical project's
code base, from a particular developer's viewpoint, into "my code" and
"everyone else's code", and generally limits them to making changes to,
or putting things into the namespaces in, "my code" only.
The days of the lone hacker building a whole system from the ground up
singlehandedly are mostly gone, for better or for worse.
Languages that don't provide for other use-cases, and in particular ones
that don't play nice with modularising code, version control, or
testing-distinct-from-going-live, will increasingly be marginalized.
Well, that is one of the nice things about CLOS and being able to add
additional methods or even entire functions to existing objects (such as
in libraries) where you don't have access to the source code. There
have been lots of large systems built with lisp, and these things have
been given a fair amount of thought. Just because the solution is
different from Java's solution doesn't make it ineffective.
See again my hammer and picnic blanket analogy for why you might want to
be able to do new things with existing objects. Suppose you wanted to
graph a tree of objects. java.lang.Class doesn't have a graph()
method, and you can't add one. In CLOS you just define a graph method,
specializing as necessary, say if you wanted to render Class and
Interface differently.
It's far more general than that.
Results 1 - 10 of about 8,950 from dictionary.com for noun.
Results 1 - 10 of about 1,470 from dictionary.com for verb.
The implication of these two Google searches is that nouns are about six
times more numerous than verbs.
I doubt the scientific validity of this, but we'll let that pass.
It still doesn't follow that one would choose a methodology that makes
one or the other of these approaches MORE difficult, when one can
instead have a methodology where adding a noun or adding a verb are
equally easy. That seems a no-brainer to me.
It stands to reason that needing a new noun to use with existing verbs
might be about six times more frequent than needing a new verb to use
with existing nouns.
So, you advocate then arbitrarily making about 1/6th of your work harder
than it needs to be because, well it's only 16% of the time?
The case at issue is when there's a pre-existing generic function with
the desired name, in library code or otherwise where I couldn't fiddle
with it (except as a lone-wolf hacker), and in a namespace I shouldn't
put my own stuff in (except as a lone-wolf hacker).
Um. You are making unwarranted assumptions again.
1) You are expected to use pre-existing generic functions. That's how
you extend the existing library code base.
2) You are NOT expected to even have access to the source code. You
don't need it. You shouldn't mess with it. All you need to know is
what the API for the generic function is. That is all you need know
is the signature and the semantics (the latter so you know that this
is actually the generic function you want).
3) The name already exists in the namespace, so you aren't changing the
namespace at all. (BTW: Namespaces in Common Lisp are exactly
that. They are NAMEspaces and only concern themselves with the
resolution of names. They don't get overloaded with notions of
functions, classes, or anything extraneous like that)
4) Assuming that you are extending the generic function in a reasonable
manner, for example by adding methods that dispatch on types that
you have defined, then there is no "lone-wolf hacker" part to this
at all. It is a controlled extension of the library. It is no more
"lone-wolf hacker" than subclassing a library class in Java would be.
The hypothesis at issue is that this metaclass, or whatever, already
exists and I'm not free to modify that code.
So far so code.
There is an existing function or class.
You are not free to modify that code.
That doesn't stop you from either creating a subclass of that library
class or extending the generic function by adding methods. YOU DO NOT
NEED ACCESS TO THE ORIGINAL CODE TO ADD METHODS. No more so than you
need access to the source code in Java to create a subclass.
Perhaps that is the analogy that you need to understand this. In Common
Lisp adding a method to a generic function is the same as creating a new
subclass of an existing class. It extends the generic function by
allowing it to apply to a new combination of method argument types. It
is, in essence, adding a dynamically dispatched "subclass" to the
generic function.
We'll not get into metaclasses, because they don't really exist in Java.
Of course they are, but methods are in packages, and packages create
namespaces, and not everyone on a large project (or a typical project
even) will be able to make changes to things in every namespace.
Methods are not in packages.
Now there is some potential for confusion here, because both Java and
Common Lisp have things called "packages", but they are not quite the
same.
A Common Lisp package is simply a namespace. It controls the mapping
from surface strings to symbols. Symbols are first class objects in
Common Lisp. Symbols are used as the namees of things in Common Lisp,
but the package system affects only the mapping of strings to names when
lisp code (or data) is read.
Only symbols are in packages.
There is a difference between using and making changes. Even if you
can't (or shouldn't) make changes to a namespace, you can still use the
existing names that are in there. Just as you can subclass any class
you like (except Java final classes), you can extend any generic
function in Common Lisp. That doesn't change the namespace. It merely
extends the generic function, much as sublasses extend their parents.