The answer is, it doesn't modify any existing code.
It follows, then, that you were incorrect about it adding more
dispatches.
It clearly is, by inspection.
The resemlance to a table is only to illustrate to a human reader the
behaviour of the dispatch table
It is structured as a table, and it manages dispatch. It is therefore,
by definition, a dispatch table.
Regardless, this is a mere quibble over terminology. Whether or not
you call it a "dispatch table" or, for that matter, a "frobulator", it
is the thing to which more dispatches are added to add more methods to
the generic function. "A rose by any other name" and so forth.
In the running Lisp image.
Certainly not -- the macro runs at compile time, not at run time. It
therefore cannot "put" anything anywhere, except into the code that
replaces its invocation.
Lisp programs aren't just executed one
statement at a time -- there's an "image" of all the symbols, classes,
functions, closures, methods, etc that are in use at the time.
This is true of any running computer program; a running C program will
contain the main method, other functions, and assorted data in memory
at any given time (albeit the functions and the like will not be first-
class objects, though pointers to functions can be manipulated in C).
It is irrelevant, though, to the dispatch-table issue, since no such
image has yet been instantiated if the program has not yet been run
and therefore particularly if it has not yet even been compiled.
Again, it's not in the source code -- it's in the Lisp image. Lisp
source just includes macros, which modify the Lisp image to update (or
generate, if you're creating a new generic fn) the dispatch tables /in
the Lisp image/.
This is incoherent. Macros may still exist at run time as first-class
objects, but they are only evaluated at compile time. At compile time,
obviously, the program does not yet exist in a runnable form.
Therefore it cannot be running, and no such image exists. Therefore,
the macro cannot store anything into that image, since it does not
exist yet.
The most it can do is generate, in its output, instructions that, when
subsequently executed when the program is run, will attempt to
construct a dispatch table in main memory. This runs into difficulties
if there is no "central clearinghouse" (e.g. created by the defgeneric
macro's output, with that output having run before any of the
defmethod macro outputs) around which to coordinate the effort. There
is a problem of symmetry breaking here, and the possibility of a data
race.
They don't have to coordinate, because the generated code deals with
the dispatch table.
The generated code is what would have to directly do the coordinating,
of course.
Well, they are "state maintained in the system's internals". It's just
state that can be generated by code, the same way that code in Java or
C++ generates some state in the system's internals.
The distinction at issue is between "low-level internals not directly
user-accessible, but which the compiler and runtime can therefore
consider trusted" and "program data generated and maintained by user-
written code, which the compiler and runtime cannot therefore consider
trusted". It is a shame that our communication difficulties apparently
force the use of such long and cumbersome ways of referring to
concepts that are understood by much shorter names within most groups
of computer programmers.
The compiler will give a warning.
That contradicts the use of the word "just" in the lines quoted above
that are five levels deeper than this line.
Although LITERALLY it's silent, there is quite the visual cue when little
red underlines start appearing in your code
So, someone does use Cusp rather than emacs. Interesting.
OK, that's reading too much meaning into what I said.
It is reading only what was there. If you did not intend the meaning
of the word "just", then you should not have used that word there to
begin with.
I've actually been corrected about that. However, it would still apply
only to the currently running Lisp image. So if, for example, you were
using a library, and a DEFMETHOD form in your code extended the
library, somebody else working in a project with you could still use
the same library code, from the same file, as you and the DEFMETHOD
form in /your/ code would not affect them.
Until your respective pieces of code were combined, as seems likely
given your hypothesis that the both of you were working on the same
project.
They do share the same name. A package doesn't know the difference
between them.
These statements inherently contradict one another. If the package
didn't know the difference between them, then the result would be
this:
add package:name -> some function definition
add package:name -> some class definition
<overwrites, since package doesn't tell functions and classes apart>
Output:
package:name -> some class definition
For this to be avoided, the package has to not merely associate a
symbol with a pointer of some kind to its referent, but it also has to
key those associations not on the symbol alone but also on some sort
of type tag:
add package:name(function) -> some function definition
add package:name(class) -> some class definition
<does not overwrite>
Output:
package:name(function) -> some function definition
package:name(class) -> some class definition
However, when EVAL hits a name, it knows the difference /
in context/ between a variable, function call, etc. The package
doesn't have to know.
It does, if only implicitly. If EVAL changes the name "name" to a
symbol using whatever scope-resolution rules, and then changes the
symbol "package:name" to a symbol/type-tag pair "package:name(class)"
that is then the lookup key in the package system for the referent
pointer, then you may be technically correct, in that the package
system may consider the type-tag in this hypothetical implementation
to be a "magic cookie" without meaning to it other than with respect
to equality comparisons (and, under the hood, probably hash codes).
However, it could then be fairly stated that the package system knows
something about classes, functions, and the like -- it just doesn't
know that it knows.
I was mistaken
Ah.
but not in the way that you thought.
These tiresome personal attacks do not constitute rational arguments
in favor of either Lisp or Java, Adlai.
These ideas don't translate so cleanly between Lisp and Java, because
only symbols are "public" or "private". The code itself is still
accessible to anybody who has the symbol reference.
The same is true in Java, in a certain sense:
public class Foo {
private static class X implements Runnable () {
public void run () {
System.out.println("Hello, world!");
}
}
public static Runnable getRunnable () {
return new X();
}
}
public class Main {
public static void main (String[] args) {
Foo.getRunnable().run();
}
}
=> "Hello, world!"
You can think of "Foo" as a package within which "getRunnable" is an
exported symbol and "X" is not, and therefore "X.run" is also not.
However, "getRunnable" provides access to an instance of X, and thus
(indirectly) to a reference to X.run, by means of polymorphic
dispatch. This is what allows Main's main method to invoke the run()
method.
A similar situation exists with reflection used in combination with
setAccessible(true).
Perhaps in this particular regard Java and Lisp are not so different
after all, aside from the very obvious syntax differences.
Firstly, Lisp has a lot more freedom, in the sense that "private"
stuff is not inaccessible; this does mean that you have to rely on
people not to use private things in a way that will cause them to
break.
The issue was that Lisp also does less to discourage this practice
than Java does, and apparently completely lacks a security model for
situations such as browsers running untrusted code, though admittedly
the latter scenario could not even have been envisioned in 1956, when
the closest anyone had come to guessing the future existence of
anything like the Web was Vannevar Bush with his concept of a "memex".
Which would have been mechanical, to the Web as a Babbage analytical
engine would have been to a computer.
However, multimethod dispatch is done in a very safe and
predictable way, so it's not a risk to allow user-defined code do
"call-next-method" to something which could be considered "private" to
an imported package.
This does not parse, but it nonetheless emits the distinctive odor of
handwavium, a notoriously dangerous and unstable substance, especially
when introduced into a high-temperature usenet thread such as this
one.
Yes, I could get to the dispatch table. I have no clue how to do it,
although I could find out by examining the macroexpansion of
DEFGENERIC and DEFMETHOD, and then essentially writing that code by
hand. However, this is not done, unless somebody wants to create their
own object system; it would be like editing the Java compiler by hand,
yourself.
Intermediate, I should say, closer to editing the source code for
java.lang.ClassLoader, or maybe even to simply subclassing that.
The Lisp image is the program state when running. Macros operate at
compile time, before (that build of) the program can possibly have
run.
We assume (and I think I speak for others who have posted in response
to you and Seamus) that when somebody else says something that seems
wrong, it's a "thinko", rather than a real mistake.
I fail to see the distinction, though I note that you are once again
presuming to speak for other people -- this time a large number of
them.
A thinko is like a typo, but on the scale of ideas -- it's an easily
identifiable MISTAKE
This statement directly contradicts the preceding one, which implied
some sort of distinction existed between a "thinko" and a "mistake".
gugamilare seems, from other things he's said in this group in the
past, to be more knowledgeable in Lisp than I am. If he writes
something that could be read a bit ambiguously, I'm assuming it's
because of a) the fact that English doesn't seem to be his first
language (which is NO PROBLEM WHATSOEVER, you just have to THINK), and
This might be interpreted in two ways itself: one, that English not
being one's first language is not a problem for a budding Lisp
programmer; or two, as a personal attack. I do sincerely hope your
intended meaning was not the latter.
b) he's assuming that the people reading his comments are familiar
with basic Common Lisp concepts.
Given that the comments in question have been crossposted to
comp.lang.java.programmer, such an assumption would appear to be
rather suspect.
See what I said in my previous paragraph, it applies here too. By the
way, I would assume that somebody saying that the sky was green would
also be a THINKO -- maybe they meant to type blue, or meant to talk
about grass. These things happen when people are multitasking, as we
all often have to. I would assume that the person I'm talking with has
made a thinko unless they repeat the same mistake several times, in
different phrasings, and defend it when somebody tries to correct
them.
Your paragraph above seems to consist partly of excuse-making. The
more serious problem, however, is that it presupposes that all readers
of such contradictory pairs of posts will have some easy means of
deciding which statement, if either, was accurate. That is quite
evidently not the case when the posts at issue are crossposted to a
newsgroup whose population cannot, by and large, be expected to have
the necessary knowledge to make that judgment, and can therefore only
go by what people have said.
Particularly, when a statement is made that will participate in such a
contradiction, but is the first such statement made so that the others
do not yet exist, and that first statement is an erroneous one, there
is not, as yet, even a contradiction to call that statement into
question. Of course, the statement may lead immediately to an
illogical conclusion, and in some cases here that has happened. In
other cases, however, it is only when a large group of statements is
taken together than they collectively imply something preposterous,
and then until one of those statements is contradicted, it is possible
for none of them to stand out as particularly suspect, at least as
judged by a lay person.
In a way, it is similar to how lack of static typing can obfuscate the
source of a problem that is caused by a type error in the code. All
statements that touch the problem data are viable suspects, and one
must start with the point where something finally blew up, a clash of
some sort between an expected and an actual type, and then work one's
way backwards to find out which was in error, the expectation or the
actual type, and where this error initially occurred.
Perhaps you should solve this the way dynamic-typing advocates like
you so often do, by unit-testing everything to death. Proofreading one
another's usenet posts might be a good way to start. You might also
use such a mechanism as a means of dispassionate review and a source
of a "cooling off" delay, to reduce the amount of personal attacks and
other illogical, emotional, and unwanted noise that currently leaks
unproductively into both newsgroups.