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

K

Kaz Kylheku

- you could blow things up in completely new and exotic ways

The ability to define types or overload operators is also on on-the-fly
modification to the compiler.
- you could generate bugs it would take a crack team of comp.sci
Ph.D.s to track down

- you could find previous/other programs no longer compiling, or
worse, compiling but no longer working correctly once recompiled

That's a retarded statement which shows ignorance of what is going on.
The potential here is for foot-bullets express-delivered by a fully-

The potential here is for you to do some RTFM before looking like a moron.
 
T

Thomas A. Russ

Series Expansion said:
That doesn't help you much when you have to use pre-existing code, or
implementation-standard names. ("car", anyone?)

"first"?

Are you being deliberately provocative, or just obtuse?
 
S

Series Expansion

Ahh, the good old Turing argument! By the same line of reasoning,
since Common Lisp is Turing-complete too, you can do in it everything
you do in a statically typed language, and the two are just
equivalent :)

The point here is not what is theoretically possible, but what is
doable reasonably with the language by a human being.

True enough.

With Lisp: blowing your foot off, and metaprogramming most people
apparently don't need.
With Java: getting the job done, and having the compiler catch a
lot of bugs and locate them for you, saving hours of
work tracking down how that Rabbit got into what was
supposed to be a list of Collaborators. (Caveat: Java
still causes headaches when a null gets into a list of
Collaborators, but Java 7 might address that soon.)
 
T

Tamas K Papp

If _I_ can add constructs like that, my coworker can too, probably ones
that are incompatible with mine, making our attempts to collaborate blow
up in our faces. Then our boss wonders why we're stuck, and whether the
money the company is spending on our salaries and benefits would be
better spent elsewhere...

Or maybe you could just talk about it and sort it out with your
coworker. Ever tried things like that? :)

Tamas
 
S

Spiros Bousbouras

If _I_ can add constructs like that, my coworker can too, probably
ones that are incompatible with mine, making our attempts to
collaborate blow up in our faces.

I don't see how it follows that you cannot collaborate but in
any case it's the same with functions: you and a coworker might
write functions with the same name but doing different things.
Any solution you have for this problem will work with macros.
 
S

Spiros Bousbouras

If _I_ can add constructs like that, my coworker can too, probably
ones that are incompatible with mine, making our attempts to
collaborate blow up in our faces.

I don't see how it follows that you cannot collaborate but in
any case it's the same with functions: you and a coworker might
write functions with the same name but doing different things.
Any solution you have for this problem will work with macros.
 
A

Alessio Stalla

True enough.

With Lisp: blowing your foot off, and metaprogramming most people
           apparently don't need.
With Java: getting the job done, and having the compiler catch a
           lot of bugs and locate them for you, saving hours of
           work tracking down how that Rabbit got into what was
           supposed to be a list of Collaborators. (Caveat: Java
           still causes headaches when a null gets into a list of
           Collaborators, but Java 7 might address that soon.)

I know Java. In fact, I use it every day at work. I don't think it's a
bad language; it has some features (some not well-known) that you
could only dream of in mainstream languages prior to it. And it has a
huge standard library, and many widely used open source libraries for
all sorts of things.

But. Especially in big applications, static typing really shows its
limits. To do some of the things a dynamic language like Lisp allows
easily, Java (and C# and C++ and...) programmers are forced to use
lots of XML and other similar mechanisms. XML is NOT type safe with
respect to Java: if you write an XML configuration for your
application that specifies an object of type X as the dependency of
another one that requires type Y instead, you won't notice until
runtime - exactly like it happens in Lisp. But Lisp is built to deal
with this: for example, you can test functions one by one in Lisp, and
with some compilers statically check declared or derived types; you
can't check for correctness pieces of XML configuration (*) - you must
wait for it to crash at runtime. Believe me, XML configuration is
really a big, important part in the kind of applications I work on.
Another common example are all the kind of non-type-safe "expression
languages" that are used in Java, especially with Web frameworks.
Again, you mistype a dot-notation expression pointing to some deeply
nested property of an object, and you can only detect the error at
runtime. What if it is in a rarely executed code path? Again, with
Lisp if you make a typo when writing a call to a slot accessor, you'll
likely get an undefined function warning at compile time. Who is
safer? ;)
These things and many others derive from an abuse of reflection in
Java. Unfortunately, indiscriminate use of reflection is the only tool
Java programmers (and especially library writers) have for writing
more dynamic code.

I'm not saying Java is unusable and should be dropped tomorrow. Just
that maybe it's not the be-all, end-all of programming languages ;)

Alessio

(*) I'm not speaking of checking the XML itself - I know of XSD
schemas, DTDs and the likes. I mean checking it *with respect to the
Java code* it will execute when interpreted.
 
S

Spiros Bousbouras

True enough.

With Lisp: blowing your foot off, and metaprogramming most people
apparently don't need.

You can blow your foot off with pretty much every language. You
seem convinced that macros make things much more dangerous
but this hasn't been the experience of Lisp programmers or they
would have abandoned macros. Note that core parts of Lisp
are implemented with macros and it hasn't caused anyone's foot
to blow off.

Regarding whether metaprogramming is needed then strictly
speaking it is not. Strictly speaking one doesn't even need a
high level language , people have written useful programmes
in assembly. But metaprogramming offers great power and
convenience without any great dangers in *** languages which
have good support for it ***. Most languages do not and that's
the reason most programmers do not use it.

--
If there really exist any apostate ex-Randroids, god damn I'd
love to meet them. Apparently, though, it's like a black hole,
i.e., once you go there, you don't come back - ever.

http://www.iidb.org/vbb/showthread.php?p=2704978#post2704978
 
S

Series Expansion

Just like a function can have bugs. Or do you write bugless functions?
Tell me the secret then.

Did you miss the bit about tight coupling making it harder to find the
bugs?
By using macros the bug will be in one single place, so you can easily
change it. If you write the same code a hundred times and realize that
it is wrong, you will have to change the one hundred places where you
wrote that same thing.

If your editor doesn't support search and replace, I suggest you
search for a new one to replace it. :)
Macros are not a source of headaches in CL because they are most times
as simple as a normal function. And you can always expand the code
directly from the source (by hitting a small sequence of keystrokes)
if you thing it has a bug somewhere.

And now you've replaced a bit of your code with the expanded version.
Later you'll change the macro for whatever reason, but at this one
spot the change won't be applied since the macro call was replaced
with its expansion in your editor at that spot. That copy now gets out
of synch with the rest of the code.

Of course, a proper IDE should let you right click on the macro call
and get a menu with options like "go to definition", "view
documentation", and "see expansion in a pop-over window WITHOUT
altering the code in your source file". For that you need something
obviously way more sophisticated than what you're describing, which
("small sequence of keystrokes") sounds suspiciously like emacs.

My Java IDE (NetBeans) has features like these (for class and function
identifiers, rather than macros). I can jump to the code for the
function or class, or view the documentation for it if it has any, and
a bunch of other things too. Even bulk-rename without affecting same-
name ones in different scopes (same-name classes in different
packages, same-name methods in different classes, etc.).

Having a fancier user-interface than a box of letters can come in
handy that way sometimes. Though I'm sad to hear than in your case,
your relatively crude development tools actually encourage you to do
things that will eventually result on parts of your code getting out
of synch with one another.

The irony being that that was basically the criticism you leveled at
Java and its frequent need for boilerplate code: if I make 100 copies
and later need to change something I have to track them all down. You
may actually have it worse:
1. You write a macro.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
2. At one point, something goes wrong so you hit a "small sequence of
keystrokes" to do an in-place replacement of a call to that macro
with its expansion.
3. You fix the bug in the macro, whatever it was, but don't change
that other code back into a macro call.
4. Later, you make a change to the macro.
5. Because you didn't copy-paste that code all over the place, you
think you DON'T have to go track down copies and make sure
they're all in synch. As a result, the expanded copy produced
in step 2 doesn't end up reflecting the change.
6. Now you've got code that's getting out of synch with other code.

Congratulations, gugamilare, it's a bug!
I really don't think this is the case with CL macros.

I don't see how it can fail to be. Obviously the code at the macro
call site intimately depends on the macro's innards -- for example, if
one input to the macro is an expression with side-effects, the number
of times the side-effects happen and the order in which side-effects
of different inputs happen will depend heavily on the exact macro
code. So certainly code that calls the macro will break if the macro
implementation (not just its signature) changes. The reverse is also
true: if the macro takes the inputs apart with car and cdr to
transform them in some way, its correctness will depend on the inputs
having the correct structure.

So, the macro definition and every call site of the macro will be
tightly coupled.

A Java method or C function definition is more loosely coupled. Since
it's just values of some sort passed as parameters, rather than code,
the order of side-effects of the arguments is well-defined: each
happens once, in left-to-right-order, at the call site and just before
the call itself. With pass-by-value (Java primitives and non-pointer C
parameters) the function also won't alter the passed-in data. With
pass-by-reference (Java objects with mutable state, pointers, C++
references) the function can alter the passed-in data but its
implementation still won't influence side effects and order of
evaluation of the argument expressions.

Macros may be able to do powerful things, but with that power comes
the greater potential for problems. (Others have mentioned variable
capture, so I won't go into detail about that here.)
Listen, I didn't design the system, so I don't know about how things
worked. This is just an example of how stable and modifiable a CL
system can be.

A made-up example. You haven't named a real, running mission-critical
system that is routinely modified on the fly while in production use
and has no back-ups.

Show me one of those, and I'll show you a headline from the future:
"Over sixty thousand customers in the dark after catastrophic computer
failure at power distribution center", "Over three hundred million
awarded in class-action suit over defective products caused by process
control computer error", "One person dead after ill-timed heart attack
during last night's six-hour 911 outage", "E-commerce giant courting
bankruptcy after catastrophic three-week Web site downtime", or
something along those lines.
How about saving your changes in a file before you load them???

These were changes being made to the copy of the program running in
RAM using the debugging tools, remember? Not to the source code on
disk.
And using a persistent database as well. This is the programmer's problem..

Problems like those are why I prefer NetBeans to Eclipse. Having the
code base reside solely in a database in the guts of the IDE leads to
headaches with migration, headaches with versioning-system
integration, migraine headaches with using a versioning system
externally INSTEAD of integratedly, and potential loss of data that
you can't even get at with normal tools and maybe can't even easily
find to back up.
 
S

Seamus MacRae

Thomas said:
Hmmm. A curious algebra, this one.

Each time a language adopts a featuer from Lisp, it becomes better than
Lisp. As Alice would say, "curiouser and curiouser"

Considering only syntactic features? "He is intelligent, but not
experienced. His pattern suggests one-dimensional thinking." With
apologies to Mr. Nimoy. :)

Series Expansion and the other cljp'ers here have been mentioning such
features as ability to keep the code, the IDE/toolchain, and the runtime
environment separate and know what is where and where everything is, use
external version control tools (a biggie in most real-world commercial
development projects, and I include big and widely-used open source
projects in that category as they usually have commercial involvement
and funding somewhere), and have the compiler catch more bugs earlier in
the code-compile-correct-test-debug cycle.
 
S

Seamus MacRae

Spiros said:
If someone decided to use short names in their code that may be
considered a problem with that particular piece of code but it's
certainly not a problem with Lisp. Lisp doesn't force anyone to
use short names.

This really says it all, doesn't it? :)
 
P

Paul Donnelly

Series Expansion said:
I just explained why the package system won't. Adding new classes in
their own packages? No problem, the package system can distinguish
foo.String from bar.String. Adding new methods to an existing class,
say foo.String? Uh-oh. Is that baz's foo.String.doIt() or quux's
foo.String.doIt()?

I guess that's one of the downsides of an inside-out object
system.
Java can do this too.

So, basically, you're saying that the way you avoid the name clash is
to make baz's String.doIt() and quux's String.doIt() private. Of
course, this now means that anyone who wants their own code to call a
String.doIt() has to roll their own and can't get a canned one from a
library. Because if they do, and there's multiple incompatible
libraries that provide this, then we're back to square one and name
clashes.

No, he's saying that support methods that don't make up a library's API
won't be exported from packages, so there's no hazard of name clashes
between them when one chooses to import all symbols from a package. That
leaves a smaller number of potential name clashes to resolve manually.
Ah, I love the smell of boilerplate code in the morning!

Not boilerplate. Just resolving a couple of conflicts if they arise. You
could skip it entirely and use package prefixes if you liked, which
isn't always a bad thing to do.
 
A

anonymous.c.lisper

Your code base has one bug.

Good sir I take offense!
My code base is immaculate!
:)
Of course the compiler can't see it
(dynamic typing). So you run it.

Compiler actually can see it, if I declare my types, and it happens to
be a type error.

However, if I am writing a function that at runtime writes and
compiles another function;
I won't know that the secondary function has an error in it until I
generate and compile it.
But this really demonstrates to me the importance of testing your code
*before* you ship it, rather than the evils of meta-programming.

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).

All of this is actually orthogonal to compiler checks.

(Aside: I don't understand everyone's obsession with type errors! I
rarely make them!)
Whoops. Now your code base has fifty
bugs, because the one bug was in code that modified it!

No, *YOUR* code base has 50 bugs.
This is a good example of what would happen if I were using Java (or
any statically typed language; I believe) to do meta-programming.
(Also a good example of why I wouldn't do that).
--
However, *MY* code base *still* has one bug.
Because I'm generating code and evaluating it.

I fix the one bug and go on my merry way,
living my life of decadence and excess,
lucky should I live to see the year 2040!
 
T

Tobias C. Rittweiler

Series Expansion said:
And now you've replaced a bit of your code with the expanded version.
Later you'll change the macro for whatever reason, but at this one
spot the change won't be applied since the macro call was replaced
with its expansion in your editor at that spot. That copy now gets out
of synch with the rest of the code.

Of course, a proper IDE should let you right click on the macro call
and get a menu with options like "go to definition", "view
documentation", and "see expansion in a pop-over window WITHOUT
altering the code in your source file". For that you need something
obviously way more sophisticated than what you're describing, which
("small sequence of keystrokes") sounds suspiciously like emacs.

My Lisp IDE can do all this. In combination with my Lisp implementation
of choice, it also shows undefined functions, undefined variables, and
even type errors etc. _at compilation time_. In the debugger I can jump
to the exact _expression_ (not just line) corresponding to a frame in
the backtrace. I can evaluate or inspect arbitrary things in the context
of a frame, and I can also restart the computation from a frame shown in
the debugger after I fixed the bug and reloaded the new function
definition interactively.

Yes, it's Emacs.

-T.
 
P

Pascal J. Bourguignon

Series Expansion said:
Did you miss the bit about tight coupling making it harder to find the
bugs?


If your editor doesn't support search and replace, I suggest you
search for a new one to replace it. :)

Apart for emacs, I know of no editor able to do the syntactic analysis
that is needed to match the boilerplates you have to have in non-lisp
programming language, and do the needed substitutions.

But in practice it's too hard to do, so you end doing the updates
manually or mostly manually anyways.

Check again the example of open/try/close vs. with-open-file.
And now you've replaced a bit of your code with the expanded version.
Later you'll change the macro for whatever reason, but at this one
spot the change won't be applied since the macro call was replaced
with its expansion in your editor at that spot. That copy now gets out
of synch with the rest of the code.

You are so confused! The macros are not expanded by the editor! They
are compiler hooks, they are expanded by the compiler, from the
source. You never see (unless you use MACROEXPAND) the code generated
by macros, it's immediately processed by the compiler.

The only thing you have to do when you change a macro, is to recompile
the functions that use it. This is easily done automatically by
putting macros in a separate source file and defining correctly the
dependencies of the other files.

Of course, a proper IDE should let you right click on the macro call
and get a menu with options like "go to definition", "view
documentation", and "see expansion in a pop-over window WITHOUT
altering the code in your source file". For that you need something
obviously way more sophisticated than what you're describing, which
("small sequence of keystrokes") sounds suspiciously like emacs.

"Go to definition" can be implemented using classical tags, like for any
other programming language.

Getting the documentation and seeing the expansions are primitive
feature of the Common Lisp language. Trivial. There's no need for an
IDE. So it's rather trivial to have a simple editor like emacs (or
even simplier) to get the documentation of lisp operators or to expand
a macro.

2. At one point, something goes wrong so you hit a "small sequence of
keystrokes" to do an in-place replacement of a call to that macro
with its expansion.

Why would we do that? That would mean shooting in one's foot. Nobody
would do that.


Congratulations, gugamilare, it's a bug!

In your dreams only.
A made-up example. You haven't named a real, running mission-critical
system that is routinely modified on the fly while in production use
and has no back-ups.

Show me one of those, and I'll show you a headline from the future:
"Over sixty thousand customers in the dark after catastrophic computer
failure at power distribution center", "Over three hundred million
awarded in class-action suit over defective products caused by process
control computer error", "One person dead after ill-timed heart attack
during last night's six-hour 911 outage", "E-commerce giant courting
bankruptcy after catastrophic three-week Web site downtime", or
something along those lines.

In really, such a mission-critical system was developed by Paul
Graham, and sold to Yahoo for a fortune, which used it without such a
catastrophe. http://lib.store.yahoo.net/lib/paulgraham/bbnexcerpts.txt


Another example, is the debugging of the OS code of the Deep Space 1
code when it was millions of kilometers from the Earth. Again, the
modifications were made on a running program without outage, and even
without physical access to computer.
http://www.flownet.com/gat/jpl-lisp.html


These were changes being made to the copy of the program running in
RAM using the debugging tools, remember? Not to the source code on
disk.

Well probably lisp programmers are smarter. For sure you make us
think so. Is it so hard a concept to make the modifications both in
the running lisp image and in some persistent storage?

This is actually the normal work flow of a lisp programmer: he will
edit the source file in emacs, type C-x C-b which will ask slime to
send the file to the running lisp image, which updates it.
 
P

Pascal J. Bourguignon

Series Expansion said:
Yes, folks, Pascal is seriously suggesting that it might be a PLUS
that we can run fifty-year-old code.

Well not only I'm serriously suggesting that, I proved it.
http://www.informatimago.com/develop/lisp/small-cl-pgms/wang.html
But what's more I'm even expecting from my fellow humans to be able to
do one step of inference during a discussion. But perhaps I
overestimate you.

What do you think, if a system is able to run code that's fifty years
old, will it able to run the previous programs or no?
 
P

Pascal J. Bourguignon

Series Expansion said:
And if code using your library and code using a different library to
do the same job get used together, it's collision time.

Never happens in Common Lisp. We didn't mention it because the
discussion so far only involved macros, but Common Lisp is a full
featured programming language, and there are tools to solve all the
problems that occured to lisp programmer in the last fifty years. You
see, there's a lot of accumulated experience and knowledge, even if
unfortunately it's not spread over a big number of programmer.

So in this case, the notion of PACKAGE, which coarsely correspond to
that of C++ namespace is put to use, and there's never any collision
problem between two CL library because they live in different
namespaces. Of course, there may always be some collision on the
usage of some global resource, but at least names are not such a
global resource.

Heck, just two hunks of code separately using your library, but with
different "small changes". Then there's GUARANTEED to be name clashes
and incompatibility.

And even in this case, it's rather trivial to load one version of the
library, and to _rename_ (at run-time) the packages of that version,
before loading the other version. Thus you can easily work with two
versions of the same libraries at the same time. (Or you can of
course do what you'd do with another programming language, modify the
source of the different versions to be able to work with both at the
same time).



Frankly, I must say that I find your objections rather silly...


Meanwhile, your objection to Java's capabilities in this area (which
are used very sparingly anyway, thus apparently needed very sparingly)
is that they will cause ... incompatibility.

[...]
Why don't you write your own entire compiler instead with the new
feature added?

Why bother with the time and (probably) bugs when you can use the
existing compiler?

Indeed why? When you can use a lisp compiler, and just patch it at a
high level with a few macros.

In other words, when you said "it can't be done" you didn't actually
mean it can't be done. Closer to "nobody wants to do it". Only if
you'd stated it that way to begin with, it wouldn't have seemed to
support your argument. "Lisp lets you more easily do something that
hardly anybody wants to do." Wow! What an endorsement! :)

Indeed. In lisp, it's easy to do things hard to do in other
languages, and it's possible to do things that are impossible in other
programming language. Get used to it, that's the way it is.
 
P

Pascal J. Bourguignon

Series Expansion said:
I'm not the one doing the flaming here at all.


I just explained why the package system won't. Adding new classes in
their own packages? No problem, the package system can distinguish
foo.String from bar.String. Adding new methods to an existing class,
say foo.String? Uh-oh. Is that baz's foo.String.doIt() or quux's
foo.String.doIt()? They have the same method name, are methods of
classes with the same name, and the classes are in the same package.

Why don't you believe it when you're told you don't understand something?
Perhaps it's time you learn serriously Common Lisp.
You may start with this introduction: http://www.gigamonkeys.com/book/

In the Common Lisp Object System (CLOS), methods are not attached to a
class, but to a generic function, and generic functions, like any
other, may be named by any symbol. It could be a symbol interned in
the same package as the symbol naming the class of one of the
parameter of one of the method of the generic function or in another
package or even in no package at all.

Concerning the names, it's like if having a class foo.String, you
could define a java method foo.doIt and another java method bar.doIt.

(new foo.MyString).(foo.doIt)() would no call the same method as
(new foo.MyString).(bar.doIt)().


You could do:

(defpackage "FOO" :)use "CL") :)export "MY-STRING" "DO-IT"))
(defclass foo:my-string () ())
(defgeneric foo:do-it (a b))
(defmethod foo:do-it ((a integer) (b foo:my-string)) '(the do-it in foo))
(defpackage "BAR" :)use "CL") :)export "DO-IT"))
(defgeneric bar:do-it (a b))
(defmethod bar:do-it ((a integer) (b foo:my-string)) '(the do-it in bar))

and then:

(foo:do-it 42 (make-instance 'foo:my-string)) --> (THE DO-IT IN FOO)
(bar:do-it 42 (make-instance 'foo:my-string)) --> (THE DO-IT IN BAR)


As far as the compiler is concerned, they are the same. The package
system cannot distinguish them unless we add another layer of
namespacing, this time INSIDE classes, and have foo.String.baz.doIt()
and foo.String.quux.doIt() instead of just foo.String.doIt() as the
fully-qualified names. And now we're deep in migraine-headache
territory, without oar or compass...

Right, non-lisp programming languages are migraine-headache territory.
We never said otherwise.


Java can do this too.

So, basically, you're saying that the way you avoid the name clash is
to make baz's String.doIt() and quux's String.doIt() private.

Not in CLOS.
[...]

Of course, the best way to avoid multiple incompatible libraries is to
have commonly desired functionality built into the standard library.
And then letting third parties create (non-private, at least) methods
in your classes is unnecessary.

No, the best way to avoid multiple incompatible libraries is to use
the package system of Lisp.
 
S

Seamus MacRae

Paul said:
I guess that's one of the downsides of an inside-out object
system.

Can I jump in here? You see, I have a theory.

It goes something like this. Java and most OO languages are actually
noun-oriented languages. They follow the natural way of thinking:
subject does verb to object. 1 + 1 = 2. And so on.

Lisp is verb-oriented. It goes (verb subject object1 object2) or (+ 1 1).

Right off, Lisp seems less intuitive. But that doesn't necessarily mean
anything.

However, it will also affect namespacing.

With Java, you'd have packages that then contain nouns (classes), in
which you implement verbs (methods). So suppose there's Integer, Float,
and Double and they all have plus verbs that take their own kind. I add
Complex and create a Complex.plus(Complex) verb inside it, and stick it
in my own namespace.

Good, good.

With Lisp, you'd have packages that then contain verbs, in which you
implement versions for different nouns. So you'd have a system package
containing plus, which in turn contains plus(Integer, Integer),
plus(Float, Float), and plus(Double, Double).

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!

It all boils down to which programmers will be doing more often: adding
new nouns which may be used with already-existing verbs, or adding new
verbs which may be used with already-existing nouns.

Adding new nouns which are used only with new verbs is not a problem in
either case.

Adding new nouns which may be used with already-existing verbs is not a
problem if namespaces contain nouns, which contain implementations per
supported verb. But it is a problem if namespaces contain verbs, which
contain implementations per supported noun.

Adding new verbs which may be used with already-existing nouns is not a
problem if namespaces contain verbs, which contain implementations per
supported noun. But it is a problem if namespaces contain nouns, which
contain implementations per supported verb.

So, if new nouns with existing verbs is more common, Java's method is
better. If new verbs with existing nouns is more common, Lisp's method
is better. (Leaving static vs. dynamic typing entirely alone here and
considering only the order of scoping of nouns and verbs within
namespaces.) Doing the "wrong" one in either language will cause
headaches unless there's a way to namespace separately by noun and verb,
which would cause its own inherent variety of headaches instead.

My own experience tells me that new nouns with existing verbs is more
common. I quite often want to define a new Java class that has state. I
much less often wish for an existing Java class to have a method I've
never heard of before.

The workaround also isn't usually that bad: create a utility class with
a static method to do the manipulation. It can't be polymorphic or use
the object's private state directly, but the latter is for the best and
the former, while annoying, isn't usually a show-stopper.

The Lisp way around would present problems. On the rare occasion I
wanted to augment an existing class with new behavior it would be easy:
define my own verb in my own namespace and set up somehow a polymorphic
dispatch on object type. On the much more frequent occasion I wanted to
add a new noun, I'd often be forced to change verbs that lived in
pre-existing namespaces, and maybe even in more than one namespace; the
code for my new noun would be scattered all over the codebase AND the
namespaces within the system, rather than in exactly one place in each.

Ouch.

There's also going to be big differences in polymorphism. With an object
oriented system, nouns can be subtypes of other nouns, and verb behavior
can be inherited, with or without modification. Dispatch is based on the
run-time-type of the noun, and adding a new polymorphic type is easy. In
Java, suppose there was an Addable interface specifying the plus method,
and Integer, Float, and Double implemented it. If I created my Complex
class and implemented Addable, code that did generic sums over Addables
would automatically also work with Complex now. I wouldn't have to make
any changes outside the Complex class.

With Lisp, I'd need to change the system namespace's plus verb's
dispatch table manually so that it knew about my Complex class, on the
other hand. Both problems in one. In fact, every combination of noun and
verb in dynamic dispatch needs to be explicitly specified somewhere.
From the sounds of it, I couldn't just say "Complex is a type of
Number" in Lisp and have the compiler automatically know where to
dispatch plus, minus, times, and dividedBy; I'd have to edit four
separate dispatch tables in four separate places, AND define (hopefully
all in one final, fifth place) my Complex implementations of these that
the new dispatch table entries would point to. With Java I'd just have
to define the implementations, naming them correctly, and stick
"implements Number" somewhere and away I'd go.
No, he's saying that support methods that don't make up a library's API
won't be exported from packages, so there's no hazard of name clashes
between them when one chooses to import all symbols from a package.

That's the same thing isn't it? He says "private", you say "won't be
exported"; it looks the same to me.
Not boilerplate. Just resolving a couple of conflicts if they arise.

At each place where it arises.

This can happen in Java too, if the same piece of code uses two
different classes with the same unqualified name. You can end up with
code littered with "java.util.Date" and "javax.sql.Date" for instance in
some types of enterprise code. It's god-awful. All those repeated
"java.util." and "javax.sql." prefixes add up to quite a lot of boilerplate.

Fortunately, it's rare to get name clashes between different peoples'
nouns and still need to intersperse both in one bit of code. It's much
more common with verbs:

someIOStream.close();
aDoor.close();
aPort.close();
aSocket.close();
aTransaction.close();
if (difference(pointA, pointB).close()) doSomething();

I'd hate to have to fully qualify all my "close"s, or "open"s, or
"free"s, or "release"s, or "next"s, or "remove"s, or "equals"s, instead
of the correct one being inferred from the type of the expression to the
left of it.
 

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

No members online now.

Forum statistics

Threads
474,432
Messages
2,571,682
Members
48,796
Latest member
Greg L.

Latest Threads

Top