Re: Seeking computer-programming job (Sunnyvale, CA)

S

Seamus MacRae

I said:
I'm not exactly sure when the first windowed version of Emacs

No, no, no! I want REAL windows, not those split-screen views that the
emacs documentation oh-so-helpfully mislabeles as "windows" and that I
found to be more trouble than they were worth.
 
S

Seamus MacRae

Thomas said:
Actually, it's really closing in on 30 years.

The zmacs variant was a windowed program since sometime around 1980.

Once more, and with feeling: the ability to divide the text display into
separate side-by-side or vertically-stacked chunks viewing separate
documents is to real windows as the Wright Brothers' first biplane is to
a Boeing 747.

The emacs documentation calls those panes "windows", and we call that
biplane an "aeroplane", but really, they're almost nothing alike, except
that the one does let you see two things at once and the other does fly.
This was used in the Lisp machine, which was also one of the first
single-user workstation designs. It was also one of the early uses of
bit-mapped (as opposed to character or vector) displays.

This is rather ironic, seeing as a bit-mapped display was wasted on
pretty much all of the computer programs that existed in those days, the
best of which were like emacs, with full-screen editing capability at
least, and the majority of which were more like ed or ex or gdb.

Perhaps they ran some experimental new programs on those that actually
used the display to its full potential, but the real revolution that was
yet to come was in having everyday tools (such as text editors) use it.

Hindsight though is always 20/20. Back then they probably thought it was
useful for visualizing function graphs and geometric shapes, and little
else. Photo-sharing, doodling, desktop publishing, DeviantArt, and such
mundanities as using graphics to ease the user's interaction with
multiple concurrent jobs, none could be easily anticipated.

Well, except maybe at Xerox Parc, where they apparently had a primitive
but recognizable GUI and a mouse several decades ago, but their
ahead-of-its-time idea never took off until Apple shamelessly copied
them and loosed the Macintosh upon the world (after the earlier, much
less successful Lisa).
 
S

Seamus MacRae

Jussi said:
Emacs Lisp is a full-scale programming language. Most of Emacs is
written in it.

It is still an internal scripting language, however, which means one of
two things are true. Either the editor lets it send arbitrary commands
to the host operating system and use arbitrary APIs of the host
operating system, in which case anything analogous to the "Concept
virus" that afflicted Word users years ago will be devastating, or the
editor does not, in which case it is limited in its expressiveness to
what the editor groks, which would mean a curses (or ncurses, not a lot
of difference) interface in this case.

Which greatly limits the ability of SLIME to present a reasonable user
interface, in turn.
There is a screenshot of a window that seems to match Adlai's
description, more or less.

An emacs "window", or an xterm window? (Not that either is likely to
impress me much.)
The link to the mailing list works, and development
seems to be active.

That's perhaps the saddest thing I've read today. All those
contributors, laboring on a product that's already trapped in a
technological cul-de-sac. It's like a dinosaur carefully incubating her
eggs while, in the sky, a certain comet looms larger and larger.
(I don't mean this as a flame, and I don't see how this can be
construed as such. If it happens, it happens, and so be it.)

This disclaimer strikes me as odd, since your post was clearly not a
flame. This thread has plenty of flames in it, most of them by Lew and a
few by Series Explosion or whatever it was, but your post is nothing
like those.
 
S

Seamus MacRae

Pascal said:
Seamus MacRae said:
Adlai said:
I forgot a few notes:
[1] from page 191 of On Lisp, by Paul Graham
[2] www.gigamonkeys.com
[3] http://www.psg.com/~dlamkins/sl/
By the way, for the (1+ n)th time, SLIME Emacs is a modern IDE. It
has
all the functionality that you've described an IDE should have. The
ONE thing it doesn't have is popping out stuff into neat little help
bubbles, but that's cosmetic, not a functionality.
Being able to see a nicely organized workspace with visible context
for displayed informaton, instead of just one page of text at a time
in one window, is "cosmetic, not functionality"? Pardon me if I
disagree.

No pardon for the ignorant!

Now *this* is a flame.
Here is a typical emacs screenshot: http://collison.ie/code/slime-repl-pics.png
It's as graphic an application as any other.

That's a REPL in a Lisp system of some sort, not emacs. Emacs is a
terminal window displaying a rectangular array of letters, numbers, and
punctuation, looking something like (pardon my rusty memory)

lorem ipsum dolor est whatever-the-****-the-rest-was blah
blah blah blah blah blah blah blah blah blah blah blah blah
blah blah blah blah blah blah blah blah blah blah blah blah
blah blah blah blah blah blah blah blah blah blah blah blah
blah blah blah blah blah blah blah blah blah blah blah blah
blah blah blah blah blah blah blah blah blah blah blah blah
blah blah blah blah blah blah blah blah blah blah blah blah
blah blah blah blah blah blah blah blah blah blah blah blah
blah blah blah blah blah blah blah blah blah blah blah blah
blah blah blah blah blah blah blah blah blah blah blah blah
--16:24-----------------------------------(Fundamental)-75%--
M-x: doctor

inside the xterm's window borders.
What difference between a paperclip and a bubble?

Relevance?

We were comparing a talking paperclip and M-x doctor. The former at
least *tried* to help users actually use the application and remember
its key-bindings. M-x doctor just lets you vent your frustration. :)

Perhaps you were thinking of balloon help, which only pops up when users
hover on something they want more information about, or in some other
circumstances (like new mail arriving), at least if it's well designed.
No cutesy animations, no psychoanalysis, just straight up useful
information. I'm too used to having the Javadocs for a method I'm
calling available at a glance to ever go back to some primitive editor
that requires me to switch tasks to a web browser, or even type some
hard-to-remember key combination to view the Javadocs within the editor
and another to close them and return to my source code. NetBeans can be
set up (and my copy has been set up) to show them in a pane in the lower
left part of the screen for whatever I'm doing, and I don't have to do
more than move my eyes to see the first part. I only have to actually do
something with the user interface to see more than the first several
lines, and a lot of times, the summary in the first few lines tells me
whatever I needed to know.

Please don't continue to argue with me about which tool better suits my
workflow. I've used both, and the answer is NetBeans.
 
S

Seamus MacRae

Adlai said:
Enter lexical scoping. If you look in the example code I presented
from On Lisp, the variable IT is bound within a LET form. This means
that IT has that meaning, within the lexical (read: word/language
dependant) scope of the LET form. It's actually quite similar to the
scope of local variables within a method in Java (IIRC).

Let's see, that makes one whole paragraph of 59 words to say "it's a
local variable".

That leaves the performance concern.
Thus, different iterations of the macro within a loop would be blind
to eachother, and although I'm no concurrent programming whiz, I'd be
quite surprised if concurrent scopes collide with eachother -- any
Lisper with threading expertise know about this one?

I should certainly hope that local variables in different threads don't
collide. My remarks about thread-safety were relative to the alternative
of it being a global variable.
Just because something isn't in the ANSI CL standard doesn't mean it's
in use by the CL community. Some of the commercial implementations
have their own graphics libraries, and there are several cross-
platform graphics libraries as well. Just google common lisp graphics
to see a sample of these.

The same state of affairs as obtains with C. I have several problems
with that state of affairs:

1. So far as I know, ANSI standards are not freely available -- a
frankly ludicrous state of affairs; all standards, especially ones
ratified by a national institute of any kind, should be public
knowledge and therefore public domain. The irony is all the bigger
when you note that the JLS is freely available (though not, so far
as I know, public domain) even though Java is the brainchild of,
and the standard is maintained by, a private, profit-motivated
business! This seems backward to what you'd expect, but maybe the
profit motive of Sun leads to their doing the smart thing and making
freely available what is cheap to provide, so as to grow their user
base and drive sales of what they can make *real* money on.
2. The lack of an official graphics library, combined with presence of
many third-party libraries of varying degrees of portability and
compatibility, makes using graphics difficult in portable code, and
graphics-using code from different sources prone to not be combinable
(at least, not easily).
3. Some of those libraries being proprietary adds a whole new headache
dimension to the code-interoperability equation, this time legal and
licensing crap and the inevitable associated red tape and monetary
costs.
 
S

Seamus MacRae

Lew said:
"Seamus"'s point is especially weak

I beg to differ. And I consider calling me "Seamus" instead of just
Seamus to be rude.
considering he's been a proponent of Java in this thread, a language
which in and of itself doesn't "assume" any graphics at all, but
depends entirely on an API library to provide graphics features.

C, Common Lisp, and Java all do; the difference is that Java includes
graphics features in its *standard* library, unlike the other two. This
makes it much more attractive for developers of desktop applications and
other software requiring graphics than Common Lisp. The only reason C
beats Java there, market share wise, is that the lion's share of the
desktop OS market is Windows, Microsoft provides a Windows-specific C
library for Windows GUI and graphics that is a defacto standard among
Windows-only-application developers, and C is perceived as being faster
than Java and actually does consume less memory than Java (at least for
smaller apps -- a Windows-GUI C "Hello, World" dialog box popper-upper
has a process size measured in KB; a Java one takes 64 megs -- and, more
generally, any garbage collected system works best with at least some
internally-unused but allocated-to-it memory, typically 25-33%).
Seems like "Seamus" is the one being "cute, all things considered".

I disagree.
 
S

Seamus MacRae

Spiros said:
"Mr. Spock is a Lisp hacker". Yes , I like this.

Mr. Spock does not work in engineering. He works on the bridge.
An interesting thing to ponder.

Ponder it too much and suffer Georg Cantor's fate you will.
Nahhh , certainly not half of mathematics , just some techical
details in set theory.

They basically rebuilt the entire foundation. That ripples into
everything. A lot of other theorems had to be checked for assuming or
relying on something called the "axiom of choice", for instance. Some of
them could still be proven without it. Not others.
 
S

Seamus MacRae

Lew said:
"Seamus" has his facts wrong.

I see no call for this rudeness. Behave yourself or you'll wind up mired
in my kill filter like a fly caught in a pitcher plant.
It didn't drive Georg Cantor mad, and there is no such repute.

Lies.

And it did not take me long to find a citation to support what I wrote.

http://mathforum.org/library/drmath/view/52393.html

"It's worth realizing that the rigorous mathematical definitions of
things like "the real numbers between 0 and 1" weren't well-developed
until roughly 1900, and so it was very hard to also talk about things
like "this infinite set is bigger than that one" until about that same
time. (As a side note, it may be for the best that they're hard to
identify; Georg Cantor, who's responsible for much of the formal set
theory that underlies these questions, went mad late in life and died in
an asylum, as have some other people who have looked at them!)"
The "reformation" of mathematics didn't in any way avoid
"inconsistencies like that";

Sure it did. They replaced a definition of set that allowed for any "x,
such that y" condition to define a set with a constructive definition
that starts with an empty set and works its way upwards, providing only
certain ways to build sets from existing sets.

This is well known, at least among those who have taken the optional
bits of high school math.

Bertrand Russell was the one whose "this statement is false" style
paradox kick-started things, though. Cantor worked later on trying to
fix things to avoid such paradoxes, and some more obscure ones (allowing
a "set of all sets" required a certain transfinite number be unequal to
itself, for instance).
"Seamus" needs to research his facts.

I have. On the other hand, you need to take some lessons in politeness!
 
S

Seamus MacRae

gugamilare said:
Adlai said:
On May 16, 7:46 am, Series Expansion <[email protected]> wrote:
[Some attributions are missing. Sorry.]
But that has nothing to do with dynamic typing...(Aside from the fact
that it is very hard (most likely impossible) to do this sort of stuff
in a statically typed language).
Do what sort of stuff? Accidentally wind up with a Float in a pack of
Strings? Why would you want to? :)
Do things like have a pack of THINGS, rather than a pack of strings.
Paul Graham repeats often, for good reason, that one of Lisp's great
strengths is its flexibility. You can have a heterogenous list and
Lisp won't blink.
Series mentioned some Java myths being perpetuated in this thread: Java
is slow, Java lacks reflection, Java isn't Turing complete. Well, this
seems to be another one: Java doesn't have heterogeneous lists.

Heck, prior to version 5 it didn't have NONheterogeneous lists.

Sheesh!

Are you stupid or what?

Or what.
He didn't even mention the word Java. He is saying what neat features
Lisp has.

He was implying that they were "features Lisp has and Java lacks". I'm
pointing out that not only were heterogeneous lists in both from the
outset, but that only Java (and only recent Java) has NONheterogeneous
lists.

The original context of Adlai's remarks was:
Do things like have a pack of THINGS, rather than a pack of strings.
Paul Graham repeats often, for good reason, that one of Lisp's great
strengths is its flexibility. You can have a heterogenous list and
Lisp won't blink. You can have a function that returns some data, or
NIL if the data is unavailable. You can bind the result of that
function to a variable without worrying about types.

Even though the word "Java" itself is indeed not mentioned, "wind up
with a Float in a pack of Strings", given the general context of this
whole discussion, clearly refers to Java.
This discussion is about LISP.

This discussion is about both. The above quotation, and the Newsgroups:
line, furnish ample evidence that it's about both.
 
S

Seamus MacRae

Thomas said:
Um, how does this work if you want the Java method to return a literal
such as int or double? I guess you are then forced to wrap the return
type in the corresponding Integer or Double, so that you have a safe
null value you can return?

Not since version 5.

But this is rarely done. The most usual reason to wrap primitives is to
put them in collections, not to have "a number or null" types. Null is
usually an unwanted complication and we'd rather have "a number or throw
an exception". One exception is with a map of numbers; map lookup
failure is common enough that using a sentinel value is generally
preferred to using try-catch.
 
S

Seamus MacRae

Paul said:
Whatever you think you see, I can assure you it's a hallucination.

Accusing your debate opponent of being mentally ill is a deplorable and
dishonest tactic, the more so when you do it obliquely to try to hide
the fact that your argument is an ad hominem one.
Methods don't need to be placed in a DEFGENERIC form.

But you guys said earlier that "we don't put methods in classes, we put
them in generic functions".

And Anonymous C Lisper just said, where I quoted it above, that generic
functions take the form of these "defgeneric" constructs.

I then simply pointed out what happens if that construct happens to be
in code you can't change.

Even supposing there's two ways to make generic functions, using a
centrally-controlled "defgeneric" and using some hypothetical
distributed construct, if an author chose to use the centralized
"defgeneric" method for a particular generic function, and you need to
modify that particular generic function, and you don't have write rights
to the code containing that particular generic function ...
 
P

Pascal J. Bourguignon

Seamus MacRae said:
For anything with complex formatting, WYSIWYG is far better than an
edit-compile-view cycle (TeX) or worse, an edit-print-view cycle
(WordStar). The latter consumes paper and toner, the former lets you
see what you're doing as you're doing it, and the middle road lacks
both traits. (Frankly, I would like the best of both worlds: a logical
markup language in a left hand pane and a right hand pane showing a
near-real-time WYSIWYG view, possibly supporting at least a subset of
editing commands. I know of nothing that provides such. Certainly it
would have to be a modern GUI application though.)

We definitely DO NOT WANT wysiwyg. We DO NOT WANT to do anything. We
want the computer to do things like formating documents for us!
 
P

Pascal J. Bourguignon

Seamus MacRae said:
Pascal said:
Seamus MacRae said:
Adlai wrote:
I forgot a few notes:
[1] from page 191 of On Lisp, by Paul Graham
[2] www.gigamonkeys.com
[3] http://www.psg.com/~dlamkins/sl/
By the way, for the (1+ n)th time, SLIME Emacs is a modern IDE. It
has
all the functionality that you've described an IDE should have. The
ONE thing it doesn't have is popping out stuff into neat little help
bubbles, but that's cosmetic, not a functionality.
Being able to see a nicely organized workspace with visible context
for displayed informaton, instead of just one page of text at a time
in one window, is "cosmetic, not functionality"? Pardon me if I
disagree.
No pardon for the ignorant!

Now *this* is a flame.
Here is a typical emacs screenshot: http://collison.ie/code/slime-repl-pics.png
It's as graphic an application as any other.

That's a REPL in a Lisp system of some sort, not emacs.

No pardon for the liars, either.

The innoncent bystanders will have noted the typical emacs status bar
at the bottom of the screen-shot.
 
S

Seamus MacRae

Thomas said:
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.

Except the hypothetical situation at issue was when you wanted to add a
new dispatch for a method and the "defgeneric" dispatch-table thingie
was not in the same namespace you want your own code to be in.

Which means that Anonymous C Lisper dodged the issue instead of
addressing it.

Um, yes.

(defgeneric frobnobdicate (a b)
:)method ((foo foo) (bar bar)) ;;arguments
.. body)
:)method ((foo foo) (baz baz))
..body))

has to become something else, I'm guessing

(defgeneric frobnobdicate (a b)
:)method ((foo foo) (bar bar)) ;;arguments
.. body)
:)method ((foo foo) (baz baz))
.. body)
:)method ((foo foo) (quux quux))
..body))

or something close to that, to add quux to the set of classes it
dispatches on.
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.

That is in contradiction with how Anonymous C Lisper said it was done.
Furthermore, the generic function frobnicate exists in *some* namespace.
Whose? If it's not yours, you'll either be intruding, or you'll be
creating a parallel generic function with the same name in a different
namespace. In the latter case, the two generic functions won't be
compatible anymore than java.util.Date and javax.sql.Date are. You
couldn't have x.frobnicate() (or rather, Lisp's equivalent syntax)
dispatch to foo's frobnicate if x was a foo and to quux's if x was a
quux; if you had imported Anonymous C Lisper's frobnicate x.frobnicate()
would not know about quux (only foo, bar, and baz) and if you had
imported your frobnicate x.frobnicate() would not know about foo (or bar
or baz), only quux. In either case, it would do what you wanted for one
type of value in x and give some sort of runtime error for the other.
It's the same problem, except swapping nouns and verbs, as trying in
Java to have a method whose return type was simply "Date" and then
sometimes return a java.util.Date and sometimes a javax.sql.Date from
it. (The best you can do is return a common supertype, in this case
likely having to be Object.)
Perhaps you were confused because ...

I will not entertain public speculation regarding my mental functioning.
Please refrain from such. I will not respond to that kind of nonsense
except to trim most of it when replying and make a note similar to this
one that it is not polite behavior.
That is ONE way to do it, but in Lisp there are often multiple ways to
accomplish the same thing.

And therefore a high likelihood of confusion being created, particularly
as to where something is getting its value or definition from.

What I've seen so far of Lisp in your posts looks like an excellent
recipe for creating tightly-coupled code that will end up being a
nightmare to debug and maintain in any seriously large real-world
project. Localizing generic functions in one spot in the code causes
code-ownership-respecting change-request bottlenecks or else people
stepping on one another's toes. Disseminating them throughout the code
base, on the other hand, causes the code that's affecting *your* code to
be widely dispersed and hard to locate.

Haven't you guys ever heard of encapsulation?
Having a lot of flexibility in a language takes some getting used to

This is also one of the touted "strengths" of perl. Everyone knows what
the result was: a messy hodgepodge with so many ways to do anything that
code reads like line noise and understanding other peoples' code
requires an encyclopedic knowledge of ALL of the ten zillion ways to do
everything.

Not a problem for small, single-developer projects.

HUGE problem for huge, multi-developer projects.

Hence the recent large scale exodus from perl to ruby and (to a lesser
extent) Python. The recent explosive growth in ruby (and especially
rails) has to a significant degree been fueled by perl users jumping ship.
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.

Fine for single-developer projects.

In multi-developer projects, you have to also rely upon programmers
knowing ALL of the tools, every single last one of them.

Java only barely dodged this bullet, due to the literate-programming
influences on it. Java code contains all kinds of library calls into the
vast, almost incomprehensibly complex standard library, and often into
third-party libraries too. Fortunately, decent Java IDEs let you get
from some code using an unfamiliar class or method to the documentation
for that method almost instantly.

This doesn't work for perl (or, I expect, Lisp) because a) perl at least
lacks this bundle-the-docs-with-the-code-in-a-tool-recognized-format
aspect of Java, and b) even were it otherwise, stuff built into the
language itself lacks this sort of "JIT documentation" anyway. In Java
it's not a problem; although your IDE won't let you point at "int" and
get a primer on the built-in "int" type or point at "class" and get an
explanation of that, there's only a small amount to understand, and it
easily fits within the head of a single programmer. Not so with perl
and, apparently, Lisp; the former has, and the latter apparently has,
TONS of built-in operators and other things that are not going to have
"JIT docs" and that ARE all going to appear in code written by a large
enough team of developers, you can betcher aspidistras they will.
Well, that is one of the nice things about CLOS

Much the reverse, as I have just explained. CLOS is an inside-out object
system; instead of providing powerful tools to create encapsulation to
insulate some code from changes to other code, it seems to provide
powerful tools to destroy encapsulation and change the behavior of
arbitrary other code. In a single-developer or serial-developer
environment, that might be powerful, but in a team-development
environment, it's a train wreck waiting to happen.
There have been lots of large systems built with lisp, and these
things have been given a fair amount of thought.

The problem is that developing a large system without teamwork, with
only one coder at a time, takes eons.

It's no wonder Lisp hackers enjoy good job security at the few job
positions they hold; they're going to be working on whatever they're
building until retirement, if not until doomsday.
Just because the solution is different from Java's solution doesn't
make it ineffective.

No, of course not. It's the solution not scaling to large devteams that
makes 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.

I think that analogy was already torpedoed in another post.
Suppose you wanted to graph a tree of objects. java.lang.Class
doesn't have a graph() method, and you can't add one.

Fortunately for those of your coworkers who rely on its behavior.

A Java programmer create an external iterator that traverses classes
somehow.
In CLOS you just define a graph method specializing as necessary

So a Lisp programmer has the option: create an external iterator that
traverses classes somehow, or muck with a system class and thereby break
everyone else's code in the project, thus getting the entire rest of the
team mad at them and probably winding up fired.

Oh, yeah, except that Lisp programmers work alone, or at best in pairs.
They more or less have to.
I doubt the scientific validity of this, but we'll let that pass.

It's quite valid. It's not a whole-web search, it's a search of just the
definitions at dictionary.com, where nearly all occurrences of "noun"
are in the form of word (noun) definition, and nearly all occurrences of
"verb" are in the form of word (verb) definition. I'd say the figures
are within 5% of the actual numbers of nouns and verbs on the site. (It
would have been nice, though, if they'd had a page with such statistics
that I could find.)
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.

But you can't have such a methodology. There are only three possibilities:

One does package.Noun.verb;
One does package.verb(Noun);
One does package1.verb(package2.Noun) or package1.Noun.package2.verb.

The third is clearly cumbersome and difficult. Eliminate it. The first
makes it easy to add new nouns, and new verbs to new nouns, only. The
second makes it easy to add new verbs, and new nouns to existing verbs,
only. So the first makes it hard to add new verbs to existing nouns and
the second makes it hard to add new nouns to existing verbs, while the
third makes it easy to do both but hard to USE the darn things after.

The choice between the first two is then made by which one does more
often, add new nouns or add new verbs.

Apparently one adds new nouns about 6x as often as one adds new verbs.
The statistics on overall language size suggest it, and my own personal
experience bears it out.
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?

No. I advocate choosing to make 16% harder (package.Noun.verb) over
making 84% harder (package.verb(Noun)) or 100% harder
(package1.verb(package2.Noun) or package1.Noun.package2.verb).
Um. You are making unwarranted assumptions again.

No, I am not, and you will kindly refrain from using accusatory
1) You are expected to use pre-existing generic functions. That's how
you extend the existing library code base.

The problem is that doing so leads to problems in large-team shops when
conflicting modifications get made to basic code used systemwide. This
is why most programming languages don't let you make any modifications
to basic code used systemwide whatsoever. Lisp permitting such
modifications will cause team-size scaling problems.
2) You are NOT expected to even have access to the source code. You
don't need it. You shouldn't mess with it.

So, the spirit of closed-source no-serviceable-parts-inside is still
alive and well in at least one place besides Redmond, WA.
All you need to know is what the API for the generic function is.

That lets you call it but not add to it. To add to the generic function
in Anonymous C Lisper's post (the thing with the "(foo foo) (bar bar)"
stuff in it) obviously requires its source code.
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).

Works for generic functions. Doesn't work for macros, since little
implementation details like the names of internally used variables in
the macros and how many times it references one of its parameters will
change its behavior. Without the source code, trying to debug problems
caused by extra side effects or by collisions between your variables and
variables inside the macro will be a nightmare.

Someone else in this thread has gone into a lot more detail about this,
posting a detailed and fairly convincing argument that some kinds of
macros could not be implemented without the macro having at least one of
three undesirable traits: non-reentrant and either not thread-safe or a
concurrency bottleneck; may cause local variable name collisions; and
may cause multiple occurrence of argument side effects.

Of these, the former is a pretty big deal, and the latter two mean
subtle bugs could arise where the macro got used that would be hard to
figure out without access to its source code.
3) The name already exists in the namespace, so you aren't changing the
namespace at all.

That's sophistry. You could use the same statement to argue that
altering the behavior of java.lang.String was not "changing" the
java.lang 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)

Java packages don't, either, save that they get their own documentation
blurb and there's a "within this namespace only" level of access control
between protected ("same-namespace and subclasses") and private ("this
class and nested classes only", roughly).

Of course, the latter probably mystifies you, like everything else to do
with encapsulation.
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.

Subclassing a library class doesn't change the base class's behavior.
Whereas letting anyone edit

(foo foo) (bar bar)
(foo foo) (baz baz)

to

(foo foo) (bar bar)
(foo foo) (baz baz)
(foo foo) (quux quux)

necessarily also allows editing it to

(foo foo) (mumble mumble)
(foo foo) (baz baz)

and people frobnobdicating bars elsewhere in the project getting a nasty
surprise next time integration tests are run.
So far so code.

This does not make sense.
That doesn't stop you from either creating a subclass of that library
class or extending the generic function by adding methods.

Except that the latter is done by modifying the piece of code with the
defgeneric thingy, at least for a nonempty subset of generic functions
if not for all of them.
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's not the concept that concerns me. It's the actual mechanics.
Altering the dispatch table to add something means having write access,
which means having the ability to also alter or remove something,
perhaps unintentionally while trying to add something. It's a fruitful
source of breakage, it encourages tight coupling, and in some projects,
it might even be considered a security risk.
It is, in essence, adding a dynamically dispatched "subclass" to the
generic function.

Assuming no slips of the finger while editing the defgeneric thing, in
cases where that's how the particular generic function is defined
instead of that other way.
Methods are not in packages.

This contradicts what you guys said earlier. Earlier you intimated that
verbs (and maybe nouns AS WELL) were in namespaces.

If methods really are not in packages, there goes the neighborhood. Name
collisions are going to be causing an unbelievable amount of headaches
in any sufficiently large project.
A Common Lisp package is simply a namespace.

So is a Java package, for the most part.
It controls the mapping from surface strings to symbols.

Ditto, if by that you mean "resolving non-fully-qualified names in the
source code at compile time".

(Computer science really ought to adopt a more uniform terminology for
such common concepts.)
the package system affects only the mapping of strings to names when
lisp code (or data) is read.

Seems to confirm the above.
Only symbols are in packages.

I don't see that this is a useful distinction, between "the method is in
the package" and "the method's name is in the package". It amounts to
the same thing. Using Java-like syntax, as I'm more familiar with it:

import package3.verb;

package1.verb
package2.verb
verb

will mean package1's version, package2's version, and package3's
version, in order. Whether you say "verb" is in the package or the
particular method is in the package, this isn't changed. In fact, it
doesn't seem to me to make much sense to say that "verb" itself is in a
particular package.

If by "symbol" you mean the equivalent of the fully-qualified name, then
yes, "package1.verb" is in package1 and so forth, but the important
thing to the programmer is that the different "verb"s avoid colliding,
and the choice of package to import affects how occurrences of
unqualified "verb" are resolved.

Then the distinction is entirely useless; whether the verb itself, as in
the code that does something, or simply the (fully-qualified) name used
to access it, is in package3 seems to be a meaningless quibble.
Especially given Lisp's lack of Java's default-access and protected
modifiers, which might be argued to make the distinction more meaningful
(but with nouns replacing verbs).
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.

I would consider changing the code associated with those names to be
making changes in the namespace.

I would consider altering java.lang.String to add a new verb quux to it
to enable aString.quux() to be making an alteration in java.lang.

Likewise I would consider altering a Lisp verb lisp-verb in
some-namespace to add a new noun quux to it to enable (lisp-verb
some-quux) to be making an alteration in some-namespace.
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.

I'm sorry, but it does. Contrast:

package foo;

public class FooException extends Exception { }

which extends Exception (in java.lang) with FooException (in foo) and a
hypothetical addition of a Lisp class quux to a foo package with a
dispatch added for quuxes to a generic function in a bar package. You
aren't just subclassing something in the bar package, you're actually
changing the behavior of something in the bar package.

In the Java version you don't have to touch anything in java.lang. The
JVM figures out on the fly during class-loading what dispatch tables to
use. Maybe if the generic function in the bar package was defined the
"defmethod" way the same holds for the Lisp compiler or VM. However, if
the generic function was defined the "defgeneric" way, the way Anonymous
C Lisper did his, then there's a problem, because there's an explicit
dispatch table in the code instead of the compiler making one. To
frobnobdicate a quux, code belonging to the bar package would have to be
edited, and not just code belonging to the foo package (where quux
itself is).
It merely extends the generic function, much as sublasses extend
their parents.

In the above example, the addition of FooException does not prevent
people using the original Exception.

Extending a generic function doesn't seem to me to create two versions,
keeping the original version under the original name and adding a new
version under a different name (ala Exception and FooException).
Instead, it *changes* the generic function (frobnobdicate and
frobnobdicate). This means nobody can use the original frobnobdicate --
and every bit of code referring to it refers to the new frobnobdicate now.

Obviously, havoc would ensue if subclassing Exception caused every bit
of code using Exception to suddenly be using FooException instead.

In fact, though you repeatedly analogize extending a generic function to
subclassing, it seems to be more like editing Exception itself and
adding a new method to it. Maybe it doesn't disturb the existing code
that uses Exception (except for breaking subclasses that added a
same-named method that couldn't be either an overload or an override of
the new base-class method), but it does change something in java.lang,
and it also breaks encapsulation, big-time.

Your generic functions sound to me somewhat like data-less classes, more
like a Java interface with one method specified than like a function.
Only where Java interfaces are implemented by adding "implements Foo" to
other classes, only some Lisp generic functions are analogously
"implemented"; others, the ones defined using "defgeneric" as in
Anonymous C Lisper's post, are more like a hypothetical alternative kind
of interface that lists a method name and a list of the implementing
classes and is implemented by adding an entry to that list. It therefore
cannot be implemented without changing code used by other parts of the
project, potentially breaking things.
 
S

Seamus MacRae

Pillsy said:
Pillsy wrote:
Pillsy wrote: [...]
This, at least, is a potential problem, but in practice it's never
caused me any difficulty.
*deep sigh*
What?
Every time a serious problem is mentioned, you tend to dismiss it with
little more than a hand-wave.

One thing I've discovered is that the things I think are going to be
problems when I start learning a language (or don't know it at all
yet) end up being pretty different from the things that I actually
learn are problems after working with it for a while.

This statement is also little more than a hand-wave. In a way it's even
less convincing than many of the other non-evidence-based arguments
against what I've said, in that it's entirely subjective.
No, I mean, by 2009 standards. It just looks a little crufty.

"A little" crufty? Nevermind looks -- it also feels (more than) a little
crufty, like trying to drive a real full-size automobile using one of
those little gadgets for commanding radio-controlled toy cars*.

Well, emacs does, and I doubt there's anything that adding SLIME to
emacs can do to change that.

* James Bond did this in at least one movie. I wouldn't recommend that
any lesser man ever attempt it.
I might, but if I wanted it to inherit from Number, I could certainly
choose to have it inherit from Number. I'm just not sure that's the
way to go from a design standpoint, though admittedly I haven't
thought about the question a whole lot..

Taking it as a given that Complex should be a subtype of Number, how
else would you go about doing it?

Well, actually, I don't suppose that even makes sense. CLOS apparently
has a notion of subclass, but to have a notion of subTYPE you kind of
need, well, types. Subclassing Number lets you have Complex values
assignable to Number variables in Java. Since everything is assignable
to every variable in Lisp, this consideration goes away, and just having
both implement plus methods will let you use them interchangeably in
code using plus on variables.

So the lack of static typing saves you a little bit of work coding your
type system. You still ought to think through your type system, even if
your type system will be completely invisible to the compiler, or your
program won't work. And penny you saved writing "extends Number;" or its
equivalent up front is owed with interest down the line, as a dollar
spent debugging run-time errors to the effect "String does not
understand the method: plus".
In truth of fact, in Common Lisp, the built-in COMPLEX class actually
does inherit from the built-in NUMBER class.

I hate all-caps names, except on final static fields where they belong.
Well, I guess that's one way of describing compilation...?

This wasn't compilation; this was "defgeneric" forms generated by
something. (Macros?)

Anyway, if you "never see any of it" why did we all see that

(foo foo) (bar bar)
(foo foo) (baz baz)

stuff from Anonymous C Lisper's post a while back? Were we all
hallucinating, or is it not actually true that we NEVER see any of it?
Do you version-control object files and executables? That seems like
strange behavior to me.

Bison generates C source files.
The tool I was describing in that paragraph is called... Emacs.

You mean, there are two programs with the same name that are otherwise
as different as night and day? That's going to cause a lot of confusion.
Who thought this was a great idea? Bayer?
Oh, no, most of the time, you can just use both packages (i.e.,
namespaces) in the package you're working in without having to fully
qualify anything. If there are clashes,

and there will be,
you can specify which package you want to use for a given unqualified
name, and qualify the other one.

What a nightmare. With Java, you just import java.util.List; and then
use List, List.add(), List.remove(), and so on. You would have us
separately import List, add, remove, and so on and then when we had List
and Set to use together, fully qualify one of List.add() and Set.add()
(since your Lisp add wouldn't "belong" to either List or Set, but to its
own top-level namespace).

It's as if instead of:

import java.util.List;
import java.util.Set;

List var1 = getList();
var1.add(x);
var1.remove(y);
Set var2 = getSet();
var2.add(x);
var2.remove(y);

we had to write:

import java.util.List;
import java.util.List.add;
import java.util.List.remove;
import java.util.Set;

List var1 = getList();
var1.add(x);
var1.remove(y);
Set var2 = getSet();
var2.java.util.Set.add(x);
var2.java.util.Set.remove(y);

Oh my fucking God I think I'm going to throw up.

Java's compiler is smart enough to know which add you mean by the type
of the expression to the left. Lisp's compiler obviously wouldn't have a
fucking clue what type either var1 or var2 will be at runtime -- they
could be Lists, Sets, cons cells, integers, or Christ alone knows what
else. So it doesn't know what add to use on var1, the one for lists, the
one for sets, or some other.

Option 1: generic "add" function. Now who owns the

(list list) (list list)
(set set) (set set)

stuff that dispatches it? Who gets read/write access to it? What happens
if someone fucks it up while trying to add another collection type?

Option 2: create separate "add" functions, necessarily in separate
namespaces.

Then we get the horror of the code up above with all of the extra
imports and qualifications, or rather their Lisp analogues.
Well, like I said, in Lisp we have this thing called a compiler.
Perhaps you've heard of them...?

The compiler compiles the

(foo foo) (bar bar)
(foo foo) (baz baz)

stuff, but what generates it? Apparently sometimes it's done manually.
Other times you've suggested it's auto-generated somehow, perhaps by
Lisp macros. Regardless, it gets modified to add a dispatch for
print-object. If it is modified manually, someone with write access to
that part of the code has to do the modification. Either everyone gets
this (and we get a train wreck) or one person does (and we get a
bottleneck). On the other hand, if it is macro-generated, anyone can
invoke macros that modify it (to add their own print-object dispatches,
say), and anyone can therefore invoke macros that potentially screw it
up, which puts us squarely back in train-wreck territory.
And I could just slap

(defpackage #:foo :)use #:cl))

at the top of mine.

Which will do what? Put your print-object there? But print-object is in
a system namespace of some sort. If this makes your print-object and its
dispatch in foo, you can't call (print-object x) and get your
print-object for x a my-whatsit and the standard print-object for x an
integer, say. You need to call either foo's print-object or the system
print-object on x, so you need x to be only ever a my-whatsit or else
only ever something else. And without static types, it will be difficult
to see if the code is correct, and impossible for the compiler to check
it for you, regarding the type of x.

If, instead, it makes your print-object or its dispatch in the system
package, you've just monkeyed with the system package.

If, instead, it MOVES print-object to foo from the system package, an
awful lot of code is about to break spectacularly.
I know what potential risks. The potential risks are that something
could go wrong when you try to print an instance of MY-WHATSIT.

Changing the generic function, whether by hand or macro, means the
potential to make changes other than simple additions, either
intentionally or by accident.
Yes, it was. Whether you decide to inherit or not is a matter of
choice.

What use is inheritance then? You have no encapsulation. You have no
type system to speak of, as far as what can be in what variables and
what can be invoked on what. Just add Complex without a superclass, add
a dispatch to the plus generic function for Complexes, and call (plus x
y) with Complexes or with Numbers. Apparently saying that Complex
inherits from Number buys you nothing, except that maybe the edit to the
dispatch table is done by some macro instead of by hand, a very-arguable
slight reduction in the risk of mangling said dispatch table.
Well, no.

Well, yes. Returning to Anonymous C Lisper's frobnobdicate, if I can add
a dispatch to it, then I can screw with it. If I can add a dispatch to
print-object I can screw with print-object. And so forth.
I could muck with the dispatch tables for the generic
functions in the standard library, but unless we're using a bizarrely
crappy and bug-ridded implementation, that won't hurt you any.

Impossible. If you can manually add (foo foo) (bar bar) to the thing you
can delete from it or otherwise edit it. If you can invoke a macro that
adds to it you can (define and then) invoke a macro that deletes from it
or otherwise edits it. (The deleting or other editing may be
unintentional, perhaps when trying to add something.)
The methods you've defined on YOUR-WHATSIT will be invoked on YOUR-
WHATSIT, the methods I've defined on MY-WHATSIT will be invoked on MY-
WHATSIT, and there won't be any interference between the too.

Unless an error is made in your or my code.

But what are the odds of that, right?
 
S

Seamus MacRae

Lew said:
Well, "Seamus" invoked Godwin's Law here. This post got through before
my plonk, but it sure makes me glad I've started "mass kill-filing" him
already.


And now "Seamus" goes all potty-mouth on us. He must really have some
logic behind his points for him to do that, eh?

Does this outpouring of nastiness serve any purpose in this debate, or
are you just being a lout and spoiling everyone else's fun in a bid for
attention or some such stupidity?
 
S

Seamus MacRae

gugamilare said:
Guess what? This IS a feature of Emacs + Slime

What, a decent interface? Impossible. Trying to graft a decent interface
onto emacs would be like trying to graft an oak tree branch onto a
petunia for God's sake, and trying to do it from inside the editor's
internal scripting language would be like trying to create a "petunia
tree" by adding the gene for lignifying cellulose to the poor plant.
More likely you'd get a dead petunia, or one that tried to eat
Manhattan, rather than a nice new patch of shade in the summer heat.
Emacs + Slime IS the "standard" way to program in CL - not the only one,
but the most used one.

If you're trying to sell Java programmers on Lisp, you're doing a
terrible job of it by making statements like this one. We Java
programmers mostly prefer to use things like Eclipse and NetBeans; these
are to emacs as day is to night. (And, having used all three at various
times within the past four years, I can say this with some confidence.
NetBeans maybe has the slight edge on Eclipse, too.)
Such a shame what a strange reaction people who never learned CL have
when they hear about what it is possible to do with it.

Possible isn't the issue. Easy is. Lots of slapping scope operators and
fully-qualifying things everywhere was one of the things that put me off
C++ and inspired me to be rather creative in "extract class" refactoring
of some JEE projects just so I could avoid ever using java.util.Date and
javax.sql.Date in the same source file.
You really NEVER have to do that

Inconsistent with the previous batch of quoted text.
and, even when you do have to, it is
using much letters than you might be thinking about now.

"Using much letters" is exactly what I'd prefer to avoid. AND NOT BY
"USING MUCH PUNCTUATION" INSTEAD!!

Nevermind the extra typing, *readability* is impacted. Especially by too
much cryptic punctuation. C++ got pretty bad for that, toward the end.
Java has so far managed to mostly avoid it. So far.

I guess we're done here then.
You insist in this thing of screwing everything up.

Yep. Definitely done here.
With manual pointer manipulation
(and, not the case of Java, but handling allocation and dis-allocation
of memory) is MUCH more dangerous than ANYTHING in Lisp. Believe it or
not.

Congratulations. You've just convinced me that Lisp is better than C.
But Java still rules the roost.
 
S

Seamus MacRae

Thomas said:
Well, if you were to actually LEARN something about Common Lisp first

There's no call for this rudeness.
perhaps you wouldn't raise so-called "problems" that don't really
exist.

But they do exist.
I mean, what would your response be if someone were to say:
"Java method overrides cause all sorts of problems. If you want
to override an inherited method, first you have to go in and
manually modify the dispatch table, so that your the right
method will be found."

The thing is, you DON'T have to manually modify Java dispatch tables. In
fact a dynamic linker makes them at runtime. Lisp, on the other hand,
has this

(foo foo) (bar bar)
(foo foo) (baz baz)

stuff explicitly in the source code. It's like faking C++ virtual
methods in C all over again! Everything old is new again! Amaze your
friends!
Well, it turns out that the inheritance specification is optional.

And, to judge by other recent posts, useless.
You only need to specify that inheritance if you actuallly need to
inherit anything. If you are going to implement ALL of the methods,
then it doesn't matter if you inherit from number of not. You
would get the same dispatch.

OK, maybe one use, inheriting un-overridden methods. One very weak use.
All the really good stuff (encapsulation, is-a relationships with type
safety, etc.) apparently goes right out the window with Lisp.
Flexibility. It's all about flexibility.

Flexibility at the expense of type-safety and encapsulation.

Wonderful for the lone hacker. Terrible for the team effort.
So I assume that you are in the habit of examining the Java method
dispatch tables?

Not the same thing. As Anonymous C Lisper told us earlier in the thread,
Lisp's are part of the *source code*, like tables of function pointers
in C. Remember the post with

(foo foo) (bar bar)
(foo foo) (baz baz)

?

Sure, they exist somewhere in the code.

Not in Java. Java has run-time loading, which creates them on the fly.
Even C++ doesn't have them in the *source* code.
I think you're being deliberately obtuse.

And I think you're being deliberately rude.
Yet, amazinginly enough, Common Lisp compilers do it all the time.

The fuckin' foo-foo shit was in SOURCE CODE, remember??? Sheesh!

Besides I'm more worried about the programmers finding it rather than
the tool-chain; if a bug creeps in it will be a real pain to track down.
This is one reason why very few languages put dispatch tables in the
freaking source code, either putting them in the executable (C++ linker)
or generating them on the fly (Java classloader and JVM "magic").
Well, the Emacs-based tools do that.

Pull the other one.
So do other IDEs, such as Allegro's and LispWorks.

The phrase "other IDEs" is incongruous here, when no previous IDE had
been mentioned. It would be like saying TextPad did something, and so
did "other IDEs" such as Eclipse and NetBeans.
But it really doesn't matter what tool it is, because you seem to be
quite able to imagine defects and malign technologies that you've never
bothered to understand, so what difference would it make if you had
heard of the particular systems?

Back to personal attacks and accusations, then, is it? Or hadn't you
noticed that I am arguing largely based on the things that YOU
(collective) have said are true of Lisp? Either my arguments are valid,
then, or you (collective) have been mistaken quite a lot. Take your
(collective) pick.
But true, very true.
You just invoke the function the same way as any other lisp function.

The devil is in the details.

No, please don't. Seeing the syntax for scoping all this stuff at once
will probably cause me to herniate something throwing up, and I'm all
out of sick days this month after a nasty bout of diarrhoea much of last
week (why do you think I disappeared from this thread for days?) that I
now suspect was induced by the horrible abuse of variable capture
graphically described in post #371. There should be mandatory viewer
discretion warnings on that sort of shit!
You don't have to do it.

Of course you can.
You seem to be getting frustrated that all of your putative objects are
really just whisps of smoke that don't exist in real usage.

If this is what CLOS use does to your objects, then I want no part of
it, y'hear? No part of it!

("Whisps of smoke that don't exist in real usage" is a very eloquent way
of saying nil, though -- gotta remember that to use that someday.)
The standard answer to your so-called problems really is that it isn't
a problem, because, frankly, it isn't.

Fully qualified names are no more of a problem in Common Lisp than they
are in Java.

Given that you need to qualify twice as much stuff, I find this
unsupported assertion difficult to believe.
You occassionally need them if there is a specific
potential naming conflict, but otherwise various importing mechanisms
eliminate the need for it.

"Occasionally", here, meaning every three lines of code on average, or
only every four?
Well, the only manual code generation is writing the specific part that
applies to the method you want.

For instance, (foo foo) (quux quux) (body), or whatever it was?
The linkage to the rest of the system is handled by the compiler. The
same way that you don't have to manually link up your Java class
hierarchy, or figure out the details of the method dispatch. The
language infrastructure does that.

Except that with multiple dispatch, it's going to have some very hairy
rules for any auto-generated dispatches. No wonder Anonymous C Lisper
prefers his generic functions to use manual dispatch then.

Figuring out what does what to what and scoping everything correctly was
a nightmare with C++ multiple inheritance. I'm guessing that was nothing
compared to the mess created by multiple dispatch without manual
dispatch table creation. (And manual dispatch table creation, meanwhile,
has colossal scaling problems. Then again so does understanding what's
going on in a big enough class hierarchy with multiple inheritance or
multiple dispatch!)
There are no more risks doing that than doing any other programming
task. You are just adding a method to the name. It's just like adding
a subclass, in many ways.

Except for the "another piece of code halfway across the repository is
affected by the change" bit, of course. (The bit with (foo foo) or
similar in it.)
Not any more than in any other programming language.

It's the magnitude of the consequences of the screwups that concerns me,
and the amount of work it will take to track down and fix things.

Yes, according to the previous description given.
But you can't screw them up any more than you can screw up the method
dispatch tables that Java generates internally.

Sure you can, unless the file containing the (foo foo) (baz baz) stuff
is made read-only by the sysadmin, and then how do you add a new
dispatch when you need one?
 
S

Seamus MacRae

Larry said:
Seamus MacRae and Series Expansion are proving themselves to be
grandmasters of trolling. The Troll-o-Matic will have to be updated to
reflect their expert techniques.

This looks suspiciously like a personal attack. It certainly seems to be
irrelevant to the debate at hand, as does its parent post.
And has anyone else noticed that they are never both present at the
same time? Just a thought.

Is that supposed to be some sort of insinuation? Most likely we just
live in different timezones or something. There are after all 24 of them
in the world, so the odds have to be pretty good.
 
S

Seamus MacRae

Lew said:
Both are absent at the same time through the magic of killfiles.

That, definitely, is a personal attack.

Keep your opinions of other people to yourself. Didn't your mother teach
you any manners?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,436
Messages
2,571,696
Members
48,796
Latest member
Greg L.
Top