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

P

Pascal J. Bourguignon

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


And you don't HAVE to use implementation-standard names.

(defpackage "MY-LISP-WITHOUT-CAR"
:)nickname "MY-LISP")
:)use "CL")
:)export "CONTENT-OF-ADDRESS-PART-OF-REGISTER"
"CONTENT-OF-DECREMENT-PART-OF-REGISTER"))
(do-external-symbols (sym "CL")
(unless (member sym '(car cdr #|...|#))
(export sym "MY-LISP-WITHOUT-CAR")))
(setf (symbol-function 'my-lisp:content-of-address-part-of-register) (symbol-function 'car))
(setf (symbol-function 'my-lisp:content-of-decrement-part-of-register) (symbol-function 'cdr))

and now, in your programs instead of writing:

(defpackage "MY-PROGRAM" :)use "CL"))

you will write:

(defpackage "MY-PROGRAM" :)use "MY-LISP"))
(in-package "MY-PROGRAM")
(content-of-address-part-of-register (cons 1 2)) ; --> 1
(content-of-decrement-part-of-register (cons 1 2)) ; --> 2


What we've done here is to define a new language, one which is almost
like Common Lisp, but where car and cdr are actually named
content-of-address-part-of-register and
content-of-decrement-part-of-register.
 
S

Seamus MacRae

Pascal said:
You are so confused! The macros are not expanded by the editor!

Eh. That wasn't my interpretation of the OP's post. He was responding to
this:

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

where someone said if he suspected a macro was buggy he'd type something
in his IDE that would cause the macro to be expanded in-place.

Series is pointing out that if he then went off to fix the bug in the
macro, but forgot to return to that other part of the code to change the
expanded code back into a macro call, then there's two copies of the
macro code -- the macro, and the one particular application of it that
was replaced in the code editor with its expansion pre-compilation.

As I understand it, he's saying the compiler still expands the macro at
all its other usage sites.

The C equivalent (I'm more familiar with C than Lisp) would be:

You have

#define DOIT(x,y) ((x)+(y)+(y))

Later you find a bug at

DOIT(a,b++)

where b is getting incremented twice instead of once.

You do whatever it is and the code there changes to

((a) + (b++) + (b++))

and realize why b is being incremented twice. You remove the "++" from
the first "b" and then zip back up to the top of the file to change the
macro definition to:

#define DOIT(x,y) ((x)+2*(y))

feeling secure in the knowledge that everything used with DOIT can be
multiplied by two (there's no string "+" concatenation operator in C).

Later, there's a decision made to change it to ((x)+3*(y)). In most
locations in the code where it "does it", the compiler dutifully expands
DOIT(foo,bar) into ((foo)+3*(bar)).

But in one lonely spot the code still reads ((a) + (b) + (b++)).

So b is still multiplied by two, instead of three, there.

Bit of a contrived example? Maybe. But I think this is what Series was
getting at. Maybe he's misunderstanding something somewhere, but I think
you definitely are.
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.

In the practical software development world, we have long since adopted
tools that track dependencies for us more or less automatically (Java
has the niggling "public static final field problem" though). Your
manual tracking of dependencies would not scale to a real-world
productive code shop in a major company or major open source project.
"Go to definition" can be implemented using classical tags, like for any
other programming language.

We NetBeans users don't have to implement it at all, nor worry our heads
about editor internals like "classical tags" (whatever those are). We
just right click and away we go, without any mess or fuss.
Getting the documentation and seeing the expansions are primitive
feature of the Common Lisp language. Trivial.

There are two problems with this statement. First, getting the
documentation seems to presuppose there is some. I've seen a fair bit of
Lisp code in my time, but never has any piece of it had anything
recognizable as some kind of doc comment attached to it. If there is any
documentation, it apparently has to be searched manually, and being
maintained separately from the source code, is liable to be out of synch
with the codebase at any given time.

Second, as Series was trying to point out (but you misunderstood), the
command to expand the macro in-place, when used to simply see how it
expands in a particular place, has the side effect of actually modifying
the source code in the editor. If that modification is saved, the macro
expansion is now "baked in" at that one location, and won't reflect
future changes to the macro's definition. So things once again drift out
of synch.

Series noted that a hypothetical NetBeans-like IDE for Lisp would have
the capability, unlike a text editor, to show the results of the
expansion in some sort of pop-over or tooltip or balloon help instead of
having only one place to put it, in the source code itself. As a result,
one could have a "view what this looks like expanded" command that was
actually a non-modifying operation, instead of having to (ab)use the
modifying operation "replace this macro call with its expansion"
(preferably immediately followed by "undo"!) to achieve the desired effect.

I'll note though that the implied lack of such an IDE is not inherently
a problem with the Lisp language itself; one could be written. A
NetBeans plugin could probably even be written. Or an Eclipse one for
people that swing that way. :)
There's no need for an IDE.

Spoken like someone who's never had to do any REAL programming. :)
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.

"Rather trivial" if you like to spend as much time or more programming
the editor as you do actually programming what you're being paid to
program -- and your boss likes you dividing your time that way, too.

Oh, and making mistakes by using "replace this macro call with its
expansion" but forgetting the subsequent "undo", which mistake silently
cause no symptoms until days, weeks, or even years in the future when
the macro definition is changed and something suddenly doesn't quite
work right, and after tearing your hair out for hours you still can't
find any error in the new macro definition, never suspecting that the
error lies somewhere else entirely because the macro definition is the
only recent change.
Why would we do that? That would mean shooting in one's foot. Nobody
would do that.

Apparently, the person Series was responding to would do that.

That person seems to go by the name "gugamilare". If you'd like to tell
him what a horrible kludge it is to use "replace macro with expansion"
as a poor-man's "view this macro call's expansion" due to lack of a
graphical IDE, well, go right on ahead. I wholeheartedly agree with that
sentiment.
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

Somehow, I doubt Yahoo abandoned all their change-management and
version-control practises and just started hacking on their servers
while they were live. If they'd done that, Series is right about the
likely outcome: some sort of at least downtime, if not a big data loss
or other disaster.
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.

That's a rather unusual, special case. Also, I expect they did this
while it was coasting in the vastness of space, so nothing could go too
horribly wrong too quickly so long as they didn't render it unable to
receive and execute commands or become unbootable.

They were also probably very careful indeed; I expect they tested their
changes in a simulator of some sort groundside before beaming any code
modifications to the probe. NASA doesn't take the preservation of
multi-billion-dollar machinery lightly, I expect.
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?

Well, now you're making changes in two places at once. Better not forget
one, or make slightly different changes to both.
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.

Who are you calling slime, ooze? :)

But if you are editing the source file and then copying the changes to
the running image, that's a bit better since they shouldn't get out of
synch nor any changes be lost. Gugamilare apparently told Series he just
edits the running image and where it stops, no-one knows.

The stuff Series said about keeping separate testing and production
systems, only hacking on the former, and having some sort of version
control seems to stand though. Editing text files on disk does not scale
up to a major software project's development practises; you'll spend
more time using the command line to check in and check out than you
spend editing, testing, or compiling anything. NetBeans provides
integration with multiple widely-used version control systems, by
contrast -- you can edit the file and save it and it can more or less
transparently commit the changes to the repository, maybe prompting you
for a change summary, as well as check out files you browse to.
Meanwhile browsing a manually-maintained mirror on your hard drive means
sometimes seeing code that's out of date, if you forget to re-checkin a
file you haven't viewed in a while.

NetBeans also provides an internal, lightweight version control system
that can recall or undo the changes to a local codebase over the past
week or so. It also can show you diffs of your recent changes in an
easy-to-read way. Quite handy, actually, and way beyond the capabilities
of a mere text editor. Particularly, the NetBeans diff-viewer could
never be even approximated in a text console no matter how fancy you got
with ncurses. You can see at a glance corresponding parts of both
versions, highlighted to indicate what corresponds, what's inserted,
what's removed, and everything, even around parts that have gotten a
fair bit longer or shorter. Lines marking corresponding bits may be
diagonal, at angles you could never manage using /-\|. And it's
*stretchy* in a way that no rigid grid of letters and numbers could ever
be. :)
 
K

Kenneth Tilton

Series said:
What are you using, Java 1.1? We're at Java 6 now and have had JIT and
near-C-speed performance for quite some time now.

I was referring to development time, not runtime. You *have* programmed
a Turing machine, haven't you?

HLLs exist because we do not want to program in assembler, let alone the
Turing instruction set. Thus when comparing HLLs, citing Turing
equivalence is... oh, wait, you did that, I better not say what I think.

hth,kzo
 
K

Kenneth Tilton

Stefan said:
gugamilare said:
Oh, I forgot this question. Because in Lisp you can create functions
like objects. The canonical example:
(defun make-adder (n)
(lambda (x) (+ x n)))

class Adder
{ final int n;
public Adder( final int n ){ this.n = n; }
public int add( final int x ){ return x + this.n; }}

public class Main
{ public static void main( final java.lang.String[] args )
{ final Adder add0 = new Adder( 0 );
final Adder add1 = new Adder( 1 );
java.lang.System.out.println( add0.add( 0 ));
java.lang.System.out.println( add1.add( 0 )); }}

0
1


Aside from the fact that you just beautifully illustrated that Java at
its cleanest would do well in a code obfuscation contest (obfuscation
via bloat), I think you also screwed up the Java: the closest thing to
lambda is an anonymous class.

hth, kzo
 
A

anonymous.c.lisper

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.

Depending on your culture this may or may not be a natural way of
thinking.
1 + 1 = 2. And so on.

Woah! hang on there..
This is a /very/ bad example of subject does verb to object.
Lisp is verb-oriented. It goes (verb subject object1 object2) or (+ 1 1).
Right, Add one and one.
(although actually '+' in lisp is more like a summation than a '+')
Right off, Lisp seems less intuitive. But that doesn't necessarily mean
anything.

Not obviously less intuitive here...
However, it will also affect namespacing.

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

MMM. no.
To continue the anaolgy:
You have packages with verbs /and/ nouns (at the same level).
Then your verbs are specified based on the noun that they apply to.
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!
No. You tack on another specification to the verb.
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.
Not really.
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.

Neither of these is really a problem in lisp.
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.

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

(defclass foo () ;; no inheritance
(AttributesHere))

(defclass bar ()
(AttributesHere))

(defclass baz ()
(AttributesHere))

(defclass bat (baz) ;inherits from baz
())

Then I can do:
(frobnobdicate InstanceOfFoo InstanceOfBar)
(frobnobdicate InstanceOfFoo InstanceOfBaz)
(frobnobdicate InstanceOfFoo InstanceOfBat)
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.
Of course, this is programming in Java (I assume?), where everything
is (somewhat arbitrarily) 'noun based'.
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

polymorphic dispatch == generic function
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.
Not really. You could put all of your methods for a given generic
function with the generic function, or you could put all of your
methods for a given object with the object.
(using defmethod).

If you want to use the exact same existing method, you could just
inherit it.
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.

No. Use inheritance.
You'd have a metaclass addable and everything addable that would
inherit it.
 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.

You really don't seem to have a clue about lisp or clos.
That's the same thing isn't it? He says "private", you say "won't be
exported"; it looks the same to me.
Packages and methods are very different things.
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.

Ok. I agree. Based on this thread alone CL is too difficult for the
masses.
This is not a reflection on Lisp, it is a reflection on the masses.

Next time I suggest knowing a little bit about lisp and clos before
arguing about lisp and clos.
 
L

Lew

Why don't you believe it when you're told you don't understand something?

He probably doesn't believe it because, a), he does understand it, and b),
telling someone off in that manner is incredibly annoying, arrogant and
common. Flame wars are introduced and fanned with comments like, "Why don't
you believe it when you're told you don't understand something?" Questions
and comments like that make the poster sound like an arrogant pr*ck.

The main difference between Lisp adherents and Java adherents is that Lisp
adherents spend their arrogance making a religion out of defending Lisp
against all comers, and Java adherents religiously criticize Java for its
shortcomings.
 
A

anonymous.c.lisper

Eh. That wasn't my interpretation of the OP's post. He was responding to
this:

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

where someone said if he suspected a macro was buggy he'd type something
in his IDE that would cause the macro to be expanded in-place.
It probably doesn't work like that.
Cue benny hill music if it does..
Series is pointing out that if he then went off to fix the bug in the
macro, but forgot to return to that other part of the code to change the
expanded code back into a macro call, then there's two copies of the
macro code -- the macro, and the one particular application of it that
was replaced in the code editor with its expansion pre-compilation.

As I understand it, he's saying the compiler still expands the macro at
all its other usage sites.

The C equivalent (I'm more familiar with C than Lisp) would be:
This is where you are going wrong.
Lisp macros and C macros are not equivalent.
You have

#define DOIT(x,y) ((x)+(y)+(y))

Later you find a bug at

DOIT(a,b++)

where b is getting incremented twice instead of once.

You do whatever it is and the code there changes to

((a) + (b++) + (b++))

and realize why b is being incremented twice. You remove the "++" from
the first "b" and then zip back up to the top of the file to change the
macro definition to:

#define DOIT(x,y) ((x)+2*(y))

feeling secure in the knowledge that everything used with DOIT can be
multiplied by two (there's no string "+" concatenation operator in C).

Later, there's a decision made to change it to ((x)+3*(y)). In most
locations in the code where it "does it", the compiler dutifully expands
DOIT(foo,bar) into ((foo)+3*(bar)).

But in one lonely spot the code still reads ((a) + (b) + (b++)).

So b is still multiplied by two, instead of three, there.

Bit of a contrived example? Maybe. But I think this is what Series was
getting at. Maybe he's misunderstanding something somewhere, but I think
you definitely are.


In the practical software development world, we have long since adopted
tools that track dependencies for us more or less automatically (Java
has the niggling "public static final field problem" though). Your
manual tracking of dependencies would not scale to a real-world
productive code shop in a major company or major open source project.



We NetBeans users don't have to implement it at all, nor worry our heads
about editor internals like "classical tags" (whatever those are). We
just right click and away we go, without any mess or fuss.


There are two problems with this statement. First, getting the
documentation seems to presuppose there is some. I've seen a fair bit of
Lisp code in my time, but never has any piece of it had anything
recognizable as some kind of doc comment attached to it. If there is any
documentation, it apparently has to be searched manually, and being
maintained separately from the source code, is liable to be out of synch
with the codebase at any given time.

Second, as Series was trying to point out (but you misunderstood), the
command to expand the macro in-place, when used to simply see how it
expands in a particular place, has the side effect of actually modifying
the source code in the editor. If that modification is saved, the macro
expansion is now "baked in" at that one location, and won't reflect
future changes to the macro's definition. So things once again drift out
of synch.

Series noted that a hypothetical NetBeans-like IDE for Lisp would have
the capability, unlike a text editor, to show the results of the
expansion in some sort of pop-over or tooltip or balloon help instead of
having only one place to put it, in the source code itself. As a result,
one could have a "view what this looks like expanded" command that was
actually a non-modifying operation, instead of having to (ab)use the
modifying operation "replace this macro call with its expansion"
(preferably immediately followed by "undo"!) to achieve the desired effect.

I'll note though that the implied lack of such an IDE is not inherently
a problem with the Lisp language itself; one could be written. A
NetBeans plugin could probably even be written. Or an Eclipse one for
people that swing that way. :)


Spoken like someone who's never had to do any REAL programming. :)


"Rather trivial" if you like to spend as much time or more programming
the editor as you do actually programming what you're being paid to
program -- and your boss likes you dividing your time that way, too.

Oh, and making mistakes by using "replace this macro call with its
expansion" but forgetting the subsequent "undo", which mistake silently
cause no symptoms until days, weeks, or even years in the future when
the macro definition is changed and something suddenly doesn't quite
work right, and after tearing your hair out for hours you still can't
find any error in the new macro definition, never suspecting that the
error lies somewhere else entirely because the macro definition is the
only recent change.



Apparently, the person Series was responding to would do that.

That person seems to go by the name "gugamilare". If you'd like to tell
him what a horrible kludge it is to use "replace macro with expansion"
as a poor-man's "view this macro call's expansion" due to lack of a
graphical IDE, well, go right on ahead. I wholeheartedly agree with that
sentiment.



Somehow, I doubt Yahoo abandoned all their change-management and
version-control practises and just started hacking on their servers
while they were live. If they'd done that, Series is right about the
likely outcome: some sort of at least downtime, if not a big data loss
or other disaster.


That's a rather unusual, special case. Also, I expect they did this
while it was coasting in the vastness of space, so nothing could go too
horribly wrong too quickly so long as they didn't render it unable to
receive and execute commands or become unbootable.

They were also probably very careful indeed; I expect they tested their
changes in a simulator of some sort groundside before beaming any code
modifications to the probe. NASA doesn't take the preservation of
multi-billion-dollar machinery lightly, I expect.



Well, now you're making changes in two places at once. Better not forget
one, or make slightly different changes to both.


Who are you calling slime, ooze? :)

But if you are editing the source file and then copying the changes to
the running image, that's a bit better since they shouldn't get out of...

read more »

Its nice out so I didn't read the rest of this, sorry. :)

You all have a nice flame war.
 
L

Lew

gugamilare said:
1) Java does not have dynamically created functions (or am I wrong?)

That depends on what you mean by "dynamically created". If you mean by the
program at run time, no, not without considerable effort. If you mean at need
at a point in the source code, yes, it does, although the signature must be
known beforehand.
2) Java Code is not an easy manipulable data

That's a design feature of Java, not a problem.
3) Java doesn't have macros.

That's a design feature of Java, not a problem.
As you can see, macros not only provide a way to make your
applications shorter or more readable, but they also make it possible
to do somethings that otherwise couldn't be done.

I have yet to find any program requirement that couldn't be done in Java
without too much effort. As to readability, that's in the eye of the
beholder. Some Java adherents believe shorter is necessarily more readable
also, but sometimes verbosity increases readability.

Hemingway and Dickens were both powerful writers.
 
S

Stefan Ram

Kenneth Tilton said:
Aside from the fact that you just beautifully illustrated that Java at
its cleanest would do well in a code obfuscation contest (obfuscation
via bloat), I think you also screwed up the Java: the closest thing to
lambda is an anonymous class.

An /inner/ class can close over certain variables of
its outer scopes (it does not matter, whether it is
/anonymous/), but I deliberately did not choose this
approach as it would only add notational overhead here.
(Try to write a SSCCE for it yourself, to see why.)
 
K

Kenneth Tilton

Lew said:
He probably doesn't believe it because, a), he does understand it, and
b), telling someone off in that manner is incredibly annoying, arrogant
and common. Flame wars are introduced and fanned with comments like,
"Why don't you believe it when you're told you don't understand
something?" Questions and comments like that make the poster sound like
an arrogant pr*ck.

The main difference between Lisp adherents and Java adherents is that
Lisp adherents spend their arrogance making a religion out of defending
Lisp against all comers, and Java adherents religiously criticize Java
for its shortcomings.

Suggesting that the main difference between Lisp and Java is that Lisp
is unassailably great and Java is full of shortcomings.

I have long thought that Java might be the only language no one ever
loved, including even its creators. In case you are wondering, that is
not a good sign.

kt

ps. I thought you were going to *watch*. Won't you keep knocking over
that bowl of popcorn? kt
 
L

Lew

Kenneth said:
Suggesting that the main difference between Lisp and Java is that Lisp
is unassailably great and Java is full of shortcomings.


Say rather that Lisp programmers drink the Kool-Aid and Java programmers are
pragmatic and thoughtful.
I have long thought that Java might be the only language no one ever
loved, including even its creators. In case you are wondering, that is
not a good sign.

I was not wondering, and you have not established that goggle-eyed adoration
is superior. I think it's a good sign that Java adherents are committed to
improvement and constant examination. I also find it telling that far more
commercial projects are programmed in Java than Lisp. So it's a good and
healthy sign that competent Java programmers, of whom I'm one, continue to
examine the language.
ps. [sic] I thought you were going to *watch*. Won't you keep knocking over
that bowl of popcorn? kt

Interesting that you feel the need to resort to personal attack. What fun!

Perhaps Java programmers are more secure in their knowledge of the language
and see it merely as a tool, and not some cult that requires snarky remarks
and blind devotion in lieu of reasoned and dispassionate utility. Or perhaps
not. I just notice that the tone in this thread from the Lisp programmers
tends to the nasty and personal compared to those who are trying to explain
why they find Java useful.

I am suspicious of anyone who claims any programming language is the be-all
and end-all for all purposes world without end amen.
 
D

Dangling Pointer

Spoken like someone who's never had to do any REAL programming. :)

Oh, here we go. Flamewar. FLAMEWAR!

I suppose it was inevitable. We have all the ingredients of the Usenet
Fire Triangle together here don't we? Lisp vs. Java. Netbeans vs.
Eclipse vs. emacs, no doubt with a vi-lover about to jump in and offer
to show us what's behind door number four. Dynamic vs. static typing,
too. Now all we need is for someone to mention "gun control", or
"abortion", or 9/11, and ...

oops
 
P

Pascal J. Bourguignon

Seamus MacRae said:
Eh. That wasn't my interpretation of the OP's post.

Ok, I was confused then.

He was responding
to this:

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

where someone said if he suspected a macro was buggy he'd type
something in his IDE that would cause the macro to be expanded
in-place.

Ok, but he didn't mean to modify the source. Only that if you have a
doubt about the correct behavior of the macro, you can obtain the
expansion of one of it's invocations to check that the correct code is
generated. (And if not, you go to the source of the macro to modify
it). The generated code doesn't replace the macro invocation in the
source, such results are displayed in the mini buffer of emacs, which
is transient.
[...]
As I understand it, he's saying the compiler still expands the macro
at all its other usage sites.

Yes, that's it.

The C equivalent (I'm more familiar with C than Lisp) would be:

You have

#define DOIT(x,y) ((x)+(y)+(y))

Later you find a bug at

DOIT(a,b++)
[...]

Emacs provides the same feature for cpp: you can select a region
containing macros calls in a C or C++ buffer and use the
c-macro-expand command to have it send the #includes and the selected
text to the C pre-processor, and display the result to another
temporary buffer.

Bit of a contrived example? Maybe. But I think this is what Series was
getting at. Maybe he's misunderstanding something somewhere, but I
think you definitely are.


In the practical software development world, we have long since
adopted tools that track dependencies for us more or less
automatically (Java has the niggling "public static final field
problem" though). Your manual tracking of dependencies would not scale
to a real-world productive code shop in a major company or major open
source project.

Who said it was manual? I didn't mention make or ant because that's
not what would be used on a lisp project, but there are tools with
equivalent features.

And don't worry about real-world productive lisp code shops, they do
perfectly well, thank for them. (Even if there's not a lot of them,
they still develop software as big as any other).

We NetBeans users don't have to implement it at all, nor worry our
heads about editor internals like "classical tags" (whatever those
are). We just right click and away we go, without any mess or fuss.

Neither lisp programmers: these features are provided by any
programmer editor such as emacs. There's nothing to be done.

There are two problems with this statement. First, getting the
documentation seems to presuppose there is some.

I don't presuppose that there is no documentation of your java codes,
so don't presuppose that there's no documentaiton of my lisp codes.
I've seen a fair bit
of Lisp code in my time, but never has any piece of it had anything
recognizable as some kind of doc comment attached to it.

I saw no more documentation of the java code I had the occasion to see.
If there is
any documentation, it apparently has to be searched manually, and
being maintained separately from the source code, is liable to be out
of synch with the codebase at any given time.

You can always do things manually, you seem to like it...

Second, as Series was trying to point out (but you misunderstood), the
command to expand the macro in-place,

It is called in place, but doesn't replace in-place.
when used to simply see how it
expands in a particular place, has the side effect of actually
modifying the source code in the editor.

I know of no lisp IDE having this feature.

[...]
Series noted that a hypothetical NetBeans-like IDE for Lisp would have

Lisp IDEs are not hypothetical.
the capability, unlike a text editor, to show the results of the
expansion in some sort of pop-over or tooltip or balloon help instead
of having only one place to put it, in the source code itself.

Has anybody said it was otherwise?

As a
result, one could have a "view what this looks like expanded" command
that was actually a non-modifying operation, instead of having to
(ab)use the modifying operation "replace this macro call with its
expansion" (preferably immediately followed by "undo"!) to achieve the
desired effect.

Such a feature has never been described.
[...]
There's no need for an IDE.

Spoken like someone who's never had to do any REAL programming. :)

Yes, I've been programming professionnaly for 27 years, that must have
been IMAGINARY. Have you a -i to spare?

"Rather trivial" if you like to spend as much time or more programming
the editor as you do actually programming what you're being paid to
program -- and your boss likes you dividing your time that way, too.

No, as trivial as using the simple features provided with emacs, or as
downloading the slime IDE and using its more sophisticated but simple
to use features. Or as simple as downloading a commercial IDE from
one of the various Common Lisp implementation vendors.

[...]
But if you are editing the source file and then copying the changes to
the running image, that's a bit better since they shouldn't get out of
synch nor any changes be lost. Gugamilare apparently told Series he
just edits the running image and where it stops, no-one knows.

The point is that the tools renders the bookkeeping so oblivious that
it feels like if you are just editing the running image, but you're
working from emacs, so what you are always editing are local files.

The stuff Series said about keeping separate testing and production
systems, only hacking on the former, and having some sort of version
control seems to stand though. Editing text files on disk does not
scale up to a major software project's development practises; you'll
spend more time using the command line to check in and check out than

What CLI?

you spend editing, testing, or compiling anything. NetBeans provides
integration with multiple widely-used version control systems,

Where do you think NetBeans developers got the idea from? Where these
developers even _born_ when emacs was created?
 
S

Seamus MacRae

Pascal said:
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)().

Isn't this exactly the problem Series Expansion foresaw? Lots of extra
namespace qualifiers dangling all over the place and virtually
unreadable code.
Right, non-lisp programming languages are migraine-headache territory.
We never said otherwise.

It was YOUR suggestion, above, to qualify both the nouns and the verbs,
separately.
No, the best way to avoid multiple incompatible libraries is to use
the package system of Lisp.

That means failing to avoid the two-orthogonal-sets-of-namespaces
headache though.
 
S

Seamus MacRae

It probably doesn't work like that.
Cue benny hill music if it does..

Someone -- gugamilare? -- seemed to think it did.
The C equivalent (I'm more familiar with C than Lisp) would be:

This is where you are going wrong.
[flamage]
[tons of untrimmed quoted text]

Its nice out so I didn't read the rest of this, sorry. :)

You all have a nice flame war.

A drive-by! Why, of all the dirty, rotten, low-down ... !
 
P

Pillsy

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.

This, at least, is a potential problem, but in practice it's never
caused me any difficulty. Lisp development environments are quite
helpful when it comes to locating method definitions wherever they
might be.
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.

Same in Common Lisp. Classes can inherit from other classes, and
generic functions dispatch on the run-time class, respecting
inheritance relationships.
[...]
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.

Not at all. The necessary modification of the generic function is
handled automatically (really, CLOS would be remarkably useless if it
weren't) when you define the new method.

And there's no problem defining methods from one namespace on classes
from another namespace. You need to be able to do this to add methods
for user-defined classes to built-in generic functions (like PRINT-
OBJECT or INITIALIZE-INSTANCE).
With Java I'd just have to define the implementations, naming them
correctly, and stick "implements Number" somewhere and away I'd go.

In Common Lisp, you'd just write the four method definitions; you
wouldn't even have to mention the "implements Number" part.
[...]

Cheers,
Pillsy
 
A

anonymous.c.lisper

It probably doesn't work like that.
Cue benny hill music if it does..

Someone -- gugamilare? -- seemed to think it did.
This is where you are going wrong.
[flamage]
[tons of untrimmed quoted text]
Its nice out so I didn't read the rest of this, sorry. :)
You all have a nice flame war.

A drive-by! Why, of all the dirty, rotten, low-down ... !

Just because you insert [flame] or [flammage] somewhere, doesn't make
it so.
I apologise if you mistook my comments.

Have a nice day.
 
G

George Neuner

George Neuner wrote:
...
...

How would you implement malloc, sbrk, or operating system internal
memory management using only C++ references and indexing?

Patricia

Are you serious?

The allocator subdivides an array (the heap) by numeric indices and
returns to the application a fixed pointer (ie. a reference) to the
new subdivision. All that is needed is the ability to index an array
and create a new language level pointer/reference by taking the
address of a particular array element.

This works at all levels - OS, library allocator, etc. The OS just
returns an absolute numeric index into its (possibly virtual) memory
array. The local allocator returns a new block by indexing from the
heap base and creating a new pointer/reference.

WRT the particulars of sbrk, if the call is successful, the local
allocator adjusts the top of its array by adding the size of the sbrk
request (sbrk can return memory to the OS as well).

Turning back to C++, references can be set to any arbitrary value (by
casting from an integer value) and are type castable (ible?) to
references of a different type. Except for arithmetic, their
semantics are nearly identical to pointers so there are no type
problems with using references.

Try it for yourself. The ability to perform arithmetic on pointers is
not needed.

George
 

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,434
Messages
2,571,690
Members
48,796
Latest member
Greg L.

Latest Threads

Top