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

L

Lew

Adlai said:
It's not called rational when:
- People tell you to spend a few minutes understanding some new
concept, and
- They provide resources, whether by directly explaining, or pointing
you to a free resource (not ONE of the resources recommended herein
wasn't free: PCL, Successful Lisp, and On Lisp are all books available
for free on the internet. Google, or clicking the links provided
earlier, would bring them to you instantly), and
- They redirect you to these efforts after the first few times you
ignore them, but
- You continually ignore these resources, while saying that you only
deal reasonably and requesting us to supply any backing for statements
like "C macros and Lisp macros are two very different beasts."

Open up your eyes, and tell us what you see.

Please take this thread out of the Java newsgroup.
 
A

Adlai

Perhaps it would be more useful to replace the word "attackers" with
"critics". I came to this debate curious about Lisp, rather than
inherently hostile to it, but found myself somewhat alarmed by things
that I realized would inevitably cause serious problems in any
realistic large-scale software-development effort.

Then why don't you try to learn about Lisp? If I told you that both
Lisp and Java had classes and a package system, that would by no means
justify the conclusion that they're the same. It's the differences
between Lisp's OO and Java's OO (and similar corresponding differences
in other programming features) that make the differences between the
languages.
Thus, to understand Lisp macros, packages, and CLOS, you should look
into how they're different from C macros, Java packages, and "noun-
based" object systems.
My criticism in this area was offered with the hope that it might lead to
improvements, but unfortunately it has only led to flaming, much of it
directed at me.

I hope you understand why. You really have ignored many arguments and
links put forth by people, regardless of verbal slips they may have
had. You haven't even said something along the lines of "I read xyz,
but I'm still confused about how generic functions frobnobdicate their
quuxmagogs... clarifications plz?"
At the same time, if those from
comp.lang.java.programmer angered by the "attackers of the Java
language" could see past their anger, they might respond by correcting
certain outdated or simply erroneous beliefs about Java rather than
flaming those who hold them. This would lead to a much more productive
debate than we have witnessed here thus far.

There have been very few erroneous beliefs about Java posted here.
In fact, the only one I can think of is MINE, where I implied
(although didn't explicitly say) that I believed you couldn't have a
heterogenous list in Java. I stand corrected now.

Many of what you've interpreted as erroneous beliefs about Java were
in fact statements about the process of coding in a language that
doesn't have xyz Lisp feature, most often Lisp macros.

Specifically, the comments in response to "Java is turing-complete, so
it can do anything Lisp can" were not to contest that FACT. They were
to point out that between two turing-complete languages, one can still
have more power. It takes much less time to write a working Lisp
program (benchmarks are quite clear here), and yes, I'm talking about
full developement, including debugging. Here's a comparison:
programming in C is turing-complete, and so is writing by hand a state
diagram for a turing machine that does the same things as that C
program. But wouldn't you rather just write in C? To bastardize
Orwell: "All [languages] are [Turing-complete], but some [languages]
are more [Turing-complete] than others."
 
S

Series Expansion

Did you just write two different replies to the same post?

If I did, it would mean that I received two different copies of the
same post, ergo that you posted two different copies of the same post,
given that the post in question was apparently authored by you.
Placing methods inside of objects. It was clever in... 1767? But it's
time to move on. In CLOS, methods, functions, and objects use the same
package system, rather than all methods applicable to an object being
mistakenly associated with a particular class.

So, it is your opinion that object orientation is a mistake?
Fascinating.

Equally interesting is your implication that CLOS is not an object
oriented system; such systems being defined by encapsulating objects'
data *and their behavior*, i.e., among other things by placing methods
inside of objects.
They can do this because methods aren't considered to be inside any
object, and are therefore free to be "top-level" entities in the
package system.

As was noted previously in this thread, this has undesirable
consequences, namely, the need to completely specify *two* namespaces
for every operation involving a method call, rather than just one.
This raises the likelihood of name collisions and the verbosity of
code in equal measure.

That this revelation comes from an avowed critic of Java's "bloat" is
especially noteworthy.
You seemed to be thinking that other methods would be made private as
well.

On what basis did you infer that nonsense? As can be seen in the
quoted material above, I explicitly stated only that the two clashing
support methods would be made private, and made no reference to making
anything else private.
Far from it!

Then you deny that the programmer has to "explicitly tell how the
clashes should be handled" near a clash site? Recall that those were
the exact words used by gugamilare in
<1490d678-60bb-4a4d-978c-94d9b654f39a@e20g2000vbc.googlegroups.com>.

I find it difficult to have a productive debate with a group whose
members frequently contradict one another. Until your "debate team"
can present a more coherent position, you will find it difficult to
sway others towards your beliefs, as your opponents will find it easy
to exploit such contradictions to undermine your credibility.
You might design a system that worked like that, but I
assure you that Lisp's designers would and did not.

You and gugamilare apparently disagree as to precisely what Lisp's
designers would do or did do. It is possible that this stems from
differences among dialects of Lisp; I am aware that there are several.
Perhaps you should confine your remarks, for now, to Common Lisp and
spare both sides further confusion.

If it is your beliefs specifically about Common Lisp that are in
conflict, however, then your best strategy at this time is to
withdraw, regroup, and reformulate your position in what football
players term "the huddle" prior to the next "scrimmage".
It would only work remotely as you imagine if you continually used a set
of awkwardly named libraries together

It is generally the case that code that uses two external libraries
together is likely to "continually" do so, rather than do so at only
one time, or at only a single location within the codebase. Generally,
that they are used together at any point at all indicates that code
belonging to the same layer, working with the same abstractions, uses
them together, and therefore that such points of conflict will crop up
at numerous locations within that layer of the application, rather
than just the once.

One could of course reduce it to one location by wrapping one of the
libraries, with the one remaining location being inside the wrapper.
This merely replaces one headache with another: the need to create the
wrapper, probably a labor-intensive and unrewarding task and a
potential nesting ground for bugs that otherwise would not have
existed.
 
F

Frank GOENNINGER

Lew said:
While this answer tells us that "Series" *will* read the book, I
suspect he won't keep his word.


"Series" is a troll. He doesn't want to learn anything. He just
wants to pepper you with foul-mouthed trash while claiming that you're
the one getting personal.

I got personal with him explicitly and he didn't scold me for it, I
notice. What, don't I deserve a four-letter word?

Of course, I wasn't defending Lisp, either.

I'm going to read the FREE (including shipping and tax) book.

Then I'm going to continue not using Lisp.

First read it. Then do yourself a favor and try the examples in just the
first three chapters. And then decide if you're going to continue to not
using Lisp.

Thanks, Lew.

Cheers
Frank
 
L

Lew

Adlai said:
Specifically, the comments in response to "Java is turing-complete, so
it can do anything Lisp can" were not to contest that FACT. They were
to point out that between two turing-complete languages, one can still
have more power. It takes much less time to write a working Lisp
program (benchmarks are quite clear here), and yes, I'm talking about
full developement, including debugging. Here's a comparison:
programming in C is turing-complete, and so is writing by hand a state
diagram for a turing machine that does the same things as that C
program. But wouldn't you rather just write in C? To bastardize
Orwell: "All [languages] are [Turing-complete], but some [languages]
are more [Turing-complete] than others."

It is likely that answering "Series" is not going to be fruitful.
 
L

Lew

Frank said:
First read it. Then do yourself a favor and try the examples in just the
first three chapters. And then decide if you're going to continue to not
using Lisp.

Please do me a favor and discuss Lisp in the Lisp newsgroup.
 
F

Frank GOENNINGER

Lew said:
Please do me a favor and discuss Lisp in the Lisp newsgroup.

Come on, Lew. You understand perfectly well that this is not relevant to
Lispers - but relevant to all the other threads and their readers in
other groups than c.l.l - I therefore was cross-posting. But enough of
that now. We all should know when enough is just enough. ;-)

Thanks for being patient and honest.

Frank
 
S

Series Expansion

Considering his opinions on Jews

By some standards, the pro-Java side just won the debate right there.
Series Expansion <[email protected]> writes:
[an attribution is missing here, but it was obviously a Lisp partisan]
Then it's a good thing it's not necessary to edit any generic functions
to add methods, isn't it?

This statement contradicts an earlier statement that the means by
which methods are dispatched is through generic functions, which
contain dispatch tables that reference all of the methods that they
can dispatch.

In <[email protected]>
anonymous_c_lisper posted an example of a generic function:

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

It seems quite obvious that adding another method, this one with a new
class quux as a second argument type, would require editing that code
to:

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

The problem arises if it is not your code to edit. Then you cannot add
a frobnobdicate method to your quux class.

There appear to be only three alternatives here:
1. The problem arises;
2. anonymous_c_lisper was wrong about something; or
3. You are wrong about something.

The suggestion floated recently that code like the above be generated
by automation does not materially alter the parameters of this debate.
The above alteration, whether automated or not, poses a problem if the
code is not yours to modify, and an even larger problem if conflicting
modifications are made by different developers whose code will
eventually be combined, granting the assumption that

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

will fail in some manner or another.

This particular corner of the debate is but one of many where evidence
has surfaced that strongly suggests that Lisp is centered around a
lone-wolf development model and, in particular, that in its present
form as described by you it is unsuited to use by a large team. Pair
programming may well be the largest team size up to which it will
scale given the numerous issues that have come to light.

Even supposing that one were to have dispatch tables like the above,
widely-used macros, and similar constructs gate-kept by "owners"
within a larger development team, all requests to for instance add a
new dispatch to a generic function would have to go through the
appropriate gatekeepers. Whereupon the scaling problems described in
__The_Mythical_Man_Month__ come into play full-force; the volume of
such requests will tend to grow as the square of the number of
developers, and the number received by the owner of a particular piece
of such code will tend to grow linearly, soon overwhelming them. The
encapsulation and modularity of code offered by OO languages like Java
reduces this problem enormously, as only defining and changing widely-
used interfaces requires that level of coordination, and everyone can
work within the encapsulation walls of their classes as if alone
without fear that they will tread upon any toes. Even if they wish to
put a frobnobdicate method into a class named quux that they use to
implement their piece of the program, and other frobnobdicate methods
already exist.

Imagine the chaos if there was a master list of all classes that
implemented "Comparable" for example and for anyone to add
comparability to a class in their corner of the codebase had to get it
approved so the owner of the comparable-classes list could add it to
the list, this list being needed by the JVM to dispatch compare()
method invocations. Fortunately Java was not designed this way, but if
we replace compare() with frobnobdicate, we see that we have precisely
the described situation in Lisp, at least according to what
anonymous_c_lisper wrote and making some obvious inferences therefrom.

Probably this is why multiple dispatch is generally not found in
languages that are used to develop large, professional software
projects. It seems that multiple dispatch in general cannot be
implemented without requiring more explicit management of dispatch
tables than occurs typically in single dispatch languages, and then
those dispatch tables become bottlenecks in the development process,
in turn placing an upper bound on effective team size and thus on
effective project size.
But that would be terrible!

That, however, is precisely what happens in dynamically-typed object-
oriented systems, since without static types the compiler cannot know
the types of the objects receiving particular messages.

It follows from your emotional outburst above that dynamically-typed
object-oriented systems are terrible. Interestingly, that category
appears to include CLOS.

Your outburst is rather puzzling given that you were formerly arguing
the other side.
Be concerned no longer. What would stop you from doing that?

I believe the concerns I have were adequately outlined above, with
code examples and a detailed explanation of the scaling problems,
supported by mathematical calculations and a reference. If you find
that insufficient, I am not sure that I can be of further assistance
to you in understanding the matter.
Oh, will you come off it? Do you intentionally adopt the most patently
absurd interpretation of every statement?

No, I merely take them at face value and derive what logical
conclusions I can. Note also that I did not specifically accuse you,
personally, of making the particular absurd insinuation referenced
above.
I'm sure that person (Kenny?) never believed such a thing, and I have no
idea why you think they did.

Because they expressed such a belief in their writing.
One could deny that 50% of all bugs are stealthy type errors, but since
we already did static typing these last few weeks, I won't get involved.

Type errors are only stealthy if one eschews the use of a language
with static type checking, of course.

For now, I leave you with another reference, an academic paper whose
conclusion, to my mind, indicates that implicitly-typed languages,
even statically-typed ones like OCaml, exhibit scaling problems caused
by supralinear growth with project size of type-error debugging
effort:

http://portal.acm.org/citation.cfm?id=176454.176460
 
G

gugamilare

Well, people, I am out of here. All Java and Lisp programmers here (at
least the ones that know how to have normal conversations), I am sorry
for all the noise that I provoked by putting wood on the fire. And I
don't intend to ever get into a flame war like this again. It is just
pointless and plain stupid, because, if people are flaming, it means
they are so religiously attached to their beliefs that they won't take
any of your arguments seriously and they will conveniently ignore all
good explanations you give.

And, yes Series, I've just shut up, and, if this makes you happy, even
better. If you want to respond to this and say that this last post
proves that I have no more arguments against your arguments, that I
can't disprove your theories, that the only arguments that I had was
to personally attack you and the Java language with not reason at all,
then I beg you, PLEASE do this, take this opportunity to say to
everyone that you were right all the time and that I was wrong.
Seriously. I will NOT try to convince anyone otherwise.
 
P

Pascal J. Bourguignon

Series Expansion said:
Considering his opinions on Jews

By some standards, the pro-Java side just won the debate right there.
Series Expansion <[email protected]> writes:
[an attribution is missing here, but it was obviously a Lisp partisan]
Then it's a good thing it's not necessary to edit any generic functions
to add methods, isn't it?

This statement contradicts an earlier statement that the means by
which methods are dispatched is through generic functions, which
contain dispatch tables that reference all of the methods that they
can dispatch.

In <[email protected]>
anonymous_c_lisper posted an example of a generic function:

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

It seems quite obvious that adding another method, this one with a new
class quux as a second argument type, would require editing that code
to:

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


In the twenty years I read usenet, I never saw anybody as dumb as
Series Expansion. Even gavino makes some progress sometimes.

Series: you haven't noticed the numerous examples given in those posts
where defmethod was used to define additionnal methods to a generic
function.
 
A

Adlai

By some standards, the pro-Java side just won the debate right there.

You should have included the message he was replying to there. He was
talking about Martin Luther, not you or MLK Jr.
Series Expansion <[email protected]> writes:

[an attribution is missing here, but it was obviously a Lisp partisan]
Then it's a good thing it's not necessary to edit any generic functions
to add methods, isn't it?

This statement contradicts an earlier statement that the means by
which methods are dispatched is through generic functions, which
contain dispatch tables that reference all of the methods that they
can dispatch.

In <[email protected]>
anonymous_c_lisper posted an example of a generic function:

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

It seems quite obvious that adding another method, this one with a new
class quux as a second argument type, would require editing that code
to:

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

The problem arises if it is not your code to edit. Then you cannot add
a frobnobdicate method to your quux class.

Actually, you can, just nobody pointed it out yet. There's a defmethod
macro that allows you to do something along the lines of:
(defmethod frobnobdicate ((foo a) (quux b))
body-form*)
BTW, the syntax for the parameter lists for a generic fn is different
from that of a method -- in a generic fn, you just specify the number
of arguments, and names you give them mainly serve for clarification
of purpose. In methods, the first name is a class or more rarely
specific object, and the second name is the name you want bound to the
corresponding argument to the method.
There appear to be only three alternatives here:
1. The problem arises;
2. anonymous_c_lisper was wrong about something; or
3. You are wrong about something.

The suggestion floated recently that code like the above be generated
by automation does not materially alter the parameters of this debate.
The above alteration, whether automated or not, poses a problem if the
code is not yours to modify, and an even larger problem if conflicting
modifications are made by different developers whose code will
eventually be combined, granting the assumption that

A few things:
- The code is never yours to modify unless it's open-source; however,
the definitions of specific methods within a generic function that
your code uses are ALWAYS yours to modify, either by adding a :method
form to a defgeneric form in your source code, or by writing a
defmethod form yourself to supplant an existing generic fn.
- defgeneric and defmethod are both examples of machine-generated
code, in a very similar way to how the JVM bytecode generated by
Java's class definition syntax is "machine-generated". There are two
differences though -- 1) anyone could write a similar form to
defgeneric that would look and feel like Lisp syntax, while Java's
class syntax is not available as an option to user-defined object
systems, and 2) Lisp's object system is implemented all in "normal"
non-OO Lisp; it was originally just a library that a bunch of people
wrote when OO became popular.
(defgeneric frobnobdicate (a b)
  :)method ((foo foo) (bar bar)) ;;arguments
   .. body)
  :)method ((foo foo) (baz baz))
   .. body)
  :)method ((foo foo) (quux quux))
   .. body)
  :)method ((foo foo) (quux quux))
  ..different body))

will fail in some manner or another.

I don't think it'll "fail"; just the first method for (frobnobdicate a-
foo a-quux) will be overwritten by the second method.
This particular corner of the debate is but one of many where evidence
has surfaced that strongly suggests that Lisp is centered around a
lone-wolf development model and, in particular, that in its present
form as described by you it is unsuited to use by a large team. Pair
programming may well be the largest team size up to which it will
scale given the numerous issues that have come to light.

Not necessarily. A defmethod form overriding or supplanting a generic
fn's capabilities will only apply to code within the package that
defmethod form appears in. Not making it external means that other
programmers could :use the package that has useful code which
internally uses the new method, but they wouldn't have to worry about
the original functionality of the same generic function, and could use
the original version in their code. It's possible that I'm wrong about
the details, but I hope that if I am, somebody who uses CLOS often can
correct me.
Even supposing that one were to have dispatch tables like the above,
widely-used macros, and similar constructs gate-kept by "owners"
within a larger development team, all requests to for instance add a
new dispatch to a generic function would have to go through the
appropriate gatekeepers. Whereupon the scaling problems described in
__The_Mythical_Man_Month__ come into play full-force; the volume of
such requests will tend to grow as the square of the number of
developers, and the number received by the owner of a particular piece
of such code will tend to grow linearly, soon overwhelming them. The
encapsulation and modularity of code offered by OO languages like Java
reduces this problem enormously, as only defining and changing widely-
used interfaces requires that level of coordination, and everyone can
work within the encapsulation walls of their classes as if alone
without fear that they will tread upon any toes. Even if they wish to
put a frobnobdicate method into a class named quux that they use to
implement their piece of the program, and other frobnobdicate methods
already exist.

You don't have to have access to the source code with the defgeneric
form to add a method.
I believe the concerns I have were adequately outlined above, with
code examples and a detailed explanation of the scaling problems,
supported by mathematical calculations and a reference. If you find
that insufficient, I am not sure that I can be of further assistance
to you in understanding the matter.

Once you created your object, you'd just add a few more lines after
the class definition (as opposed to in the class definition for the
Comparable stuff, if I understood your Java example correctly). These
lines would consist of a defmethod for the generic fn you were
interested in extending to support your object -- for example,
(defmethod compare ((my-obj x) (my-obj y)) code-goes-here). This would
not break any previous functionality of the COMPARE generic fn, except
for overwriting any previous method when both arguments are my-objs --
but in this example that wouldn't be the case because you're making a
new class.
No, I merely take them at face value and derive what logical
conclusions I can. Note also that I did not specifically accuse you,
personally, of making the particular absurd insinuation referenced
above.


Because they expressed such a belief in their writing.

No. They said something along the lines of what I referred to as the
bastardization of Orwell's "All animals are equal, but some animals
are more equal than others."

x86 is Turing-complete, along with Ruby, B, BrainFork, Java, Haskell,
Perl, and FORTRAN. But that goes to show that just being T-c doesn't
go very far to show the capabilities or special powers of a language.
Here's an example in Java's favor -- Java and Lisp are both T-c, but I
don't think you can easily, or at all, write Applet-style code in
Lisp, but it's one of the things Java was designed for. So you see,
people weren't saying Java isn't T-c, they were saying that just being
T-c isn't that big a deal anymore.
Type errors are only stealthy if one eschews the use of a language
with static type checking, of course.

For now, I leave you with another reference, an academic paper whose
conclusion, to my mind, indicates that implicitly-typed languages,
even statically-typed ones like OCaml, exhibit scaling problems caused
by supralinear growth with project size of type-error debugging
effort:

http://portal.acm.org/citation.cfm?id=176454.176460

I don't have enough experience under my belt to debate type systems.
However, I do know that using a good Lisp system -- and there are free
ones -- gets you the best of both worlds in type systems. If a Lisp
programmer decides one day that static typing is as good as you say it
is, it's trivial for them to write type-safe code in CL.


Please read and consider what I've said here. I'm really trying to
understand what it is that you're interested in finding out. I'm sorry
about a few posts where I behaved my age (skateboards and spraypaint).


- Adlai
 
P

Pascal J. Bourguignon

Adlai said:
(defmethod frobnobdicate ((foo a) (quux b))
body-form*)
BTW, the syntax for the parameter lists for a generic fn is different
from that of a method -- in a generic fn, you just specify the number
of arguments, and names you give them mainly serve for clarification
of purpose. In methods, the first name is a class or more rarely
specific object, and the second name is the name you want bound to the
corresponding argument to the method.

No, this is not C. We put the parameter and the type in the normal order.
 
P

Paul Donnelly

Series Expansion said:
If I did, it would mean that I received two different copies of the
same post, ergo that you posted two different copies of the same post,
given that the post in question was apparently authored by you.


So, it is your opinion that object orientation is a mistake?
No.

Fascinating.

Equally interesting is your implication that CLOS is not an object
oriented system; such systems being defined by encapsulating objects'
data *and their behavior*, i.e., among other things by placing methods
inside of objects.

No, they aren't defined by that. There are several things that an OO
system might include, such as automatic dispatch based on type, and
inheritance: things that CLOS has. There are other things (such as
private members and methods inside objects) that are optional.
As was noted previously in this thread, this has undesirable
consequences, namely, the need to completely specify *two* namespaces
for every operation involving a method call, rather than just one.
This raises the likelihood of name collisions and the verbosity of
code in equal measure.

No, it has no such consequence.
That this revelation comes from an avowed critic of Java's "bloat" is
especially noteworthy.


On what basis did you infer that nonsense? As can be seen in the
quoted material above, I explicitly stated only that the two clashing
support methods would be made private, and made no reference to making
anything else private.

You constantly infer nonsense. I was just taking my turn.


Yes, he was an obvious troll hundreds of posts ago. That doesn't mean
some poor c.l.j.p reader couldn't be misled.
 
L

Lew

Paul said:
Yes, he was an obvious troll hundreds of posts ago. That doesn't mean
some poor c.l.j.p reader couldn't be misled.

No "poor c.l.j.p reader could be misled" if you'd just take this thread off of
c.l.j.p. Please.

Advocacy for other programming languages is not the purpose of c.l.j.p., no
matter how excellent the other languages.
 
S

Series Expansion


It bears saying again that [irrelevant personal attack]

Your penchant for posting personal attacks is becoming tiresome.
Please refrain from doing so again. It does not bolster your
arguments; rather, it just serves to make you look petty.
The problem is that "the code which uses them" includes any code that
contains the text that triggers the macro and that occurs after the
macro in evaluation by the compiler.

It bears saying again that [irrelevant personal attack]

It bears saying again that your penchant for posting personal attacks
is becoming tiresome. Please refrain from doing so again. It does not
bolster your arguments; rather, it just serves to make you look petty.
I've written lots of macros, though, in a variety of places and
contexts.

It bears saying again that [irrelevant personal attack]

Insults and repetition are the last desperate resort of a debater who
has realized that he's losing the argument. You can't win on logical
grounds, so you respond with emotional outpourings of faith. When that
in turn proves futile, you change to a different form of emotional
argument, one that attacks the character or person of one of your
opponents and says nothing whatsoever about the actual subject of the
debate.

It would serve you better to remain silent once you have exhausted
your logical arguments regarding the topic. After that point, those
you have not convinced you will not convince and no amount of kicking
and screaming and throwing of temper tantrums will change that fact.

Since you are clearly uninterested in continuing to debate Lisp's
qualities logically, I see no point in continuing. The rest of your
post has been ignored. Have a nice day.
 
S

Series Expansion

[Paul's thrice-repeated boilerplate insult removed in the interests of
preserving some semblance of decorum]

I am starting to think that what he fails to see is ...

So your arguments, too, have now devolved into personal attacks
against the opposition.

It seems, then, there is very little left for me to do in this thread.

Most disappointing.
And he probably thinks that the compiler will look for texts that
look like macro and expand them.

That is what macro processors do, although more specifically the texts
must look like the macro's *name*.
Just trying to make things clear now, lispers don't need to read it
because they already know all of what I am explaining here. Lisp code
is a bunch of nested lists - that is why Lisp has so much parenthesis
(I won't be mad if anyone say this is not very good, I respect
everyone's opinion, but I PERSONALLY prefer code filled with
parenthesis then code filled with a non-uniform syntax like C or
Java).

You have a peculiar method of demonstrating that you respect
everyone's opinion. Ordinarily, one would not express such by means of
petty namecalling.
When we type

(+ 1 (* 2 3))

this is text that actually represents a tree.

I'm well aware of this; in fact, I probably know considerably more
about Lisp than you have given me credit for.
The inner list is composed by the symbol * and the numbers 2 and 3.
The compiler and all macros work based one that tree.

That the macro operates upon trees rather than linear strings does not
alter its fundamental nature as a macro.
Assuming that m
is a macro, when you write

(m (+ 1 (* 2 3)))

the compiler will parse the outer list and see that it is composed by
two elements: the symbol m and a inner list. Then the compiler will
think "oh, the symbol m names a macro." (ok, not exactly think, but
you get the point, right?).

This leads to one of the three major issues under discussion. If m
were a function, and someone were to add a macro named m in the right
place, it would alter the behavior of much of the code-base. This
could result from a typo or other accident, and might prove difficult
to debug.
The compiler will call that macro the exact way that it would call a
function, but, instead of evaluating the list (+ 1 (* 2 3)) to the
value 7 and call the macro with the value 7, it will call the macro
with the list itself, without evaluating it. It is just a list, a well known and very simple data
structure that even a beginner in programming with a minimal knowledge
of data structures know how to manipulate. And what does the macro
return? Another list, to be evaluated instead of the expression (+ 1
(* 2 3)).

Which ordinarily will contain that expression, wrapped in other code.

This causes the second of those three issues, namely, depending on
when, how often, and in what order the macro uses its arguments,
argument expressions with side effects may occur zero or more times in
any sequence. If foo(x,y) is a function call, the side effects of x
and y will occur once each, and in many languages, in that order. If
foo(x,y) is a macro call, it is possible for y's side effects not to
occur at all, or for the side effects to occur multiple times and in
an arbitrary sequence, for instance yxyyx. Worse, changes in the
macro's implementation may alter this, even changes that weren't
supposed to make a semantic difference, such as performance
optimizations.

It also causes the third: when the macro's result takes its place,
variables it uses may collide with variables around the call site.
Creating a nested scope, equivalent to using a {} block in C, inside
the macro to avoid this results in those variables now hiding
variables around the call site. If one of the hidden variables is used
in one of the call's argument expressions, it will fail to have the
intended effect.
The sequence of characters "(+ 1 (* 2 3))" were previously read and
transformed into a list long before the macro was called. Yes, BEFORE,
not during nor after. The entire form is read and parsed into lists,
and only then the macros found are expanded.

I already knew this, and it does not materially alter the points
raised above.
Only after the macros did
their job the compiler finally takes the resulting form (guess what?
another bunch of nested lists) and compiles it, produced the well
known machine code or byte code that I am sure everyone here is
familiar with and I don't need to get into details.

This presents a fourth potential issue. Macros cannot vary at run
time, nor can their argument lists. Those lists may operate upon
variables, but cannot themselves be variable.

Indeed, what macros do, some other languages do more cleanly using
closures. Instead of a macro m(x,y) there would be a function f(x,y)
whose arguments were closures. The function f would run the closures
amid running its own code and then return. Where a macro processor
would replace m with its expansion at compile time, the call to f
would be left alone.

With respect to issue one, f would lie in the namespace of ordinary
functions and any code declaring a different f would trigger an error
from the name collision.

With respect to issue two, f would still cause the side effects of x
and y in arbitrary number and order. However, f's arguments would be
syntactically recognizable as closures, for example Smalltalk blocks,
rather than being ordinary expressions in only ordinary function-call
syntax, mitigating issue two.

With respect to issue three, f would have its own local scope, not
nested in the scope of any call site, and therefore would be
"hygienic".

With respect to issue four, f could be called with closure-valued
variables instead of only with a closure literal, and would behave as
one would hope and expect.

The downside is performance: f could not be inlined by the compiler if
called with run-time-variable closures instead of run-time-constant
ones.

It seems that the macro m is therefore just an auto-inlining version
of f that cannot have run-time-variable closures, lacks a separate
naming scope from its call sites, and lacks a syntax to distinguish it
from an ordinary function call, allowing for both accidental
substitutions and confusion regarding sequencing and number of
occurrences of argument expression side effects.

In other words, m seems to lack advantages over f, whereas f has clear
advantages over m. Whenever m could work at all f could be inlined so
m does not even have a performance advantage; indeed sometimes f will,
whenever inlining it would bloat the object code enough to cause cache
misses but the compiler was smart enough to avoid inlining it under
those circumstances.
 
S

Series Expansion

It's an awfully good thing that Common Lisp didn't do that, then,
isn't it?

But it more or less did. The only types in Common Lisp appear to be
cons cells, nil, integers, and one or two other numeric types, and as
near as I can tell, variables and arguments are untyped anyway, so the
compiler won't bat an eye no matter what you assign to them.

Even Smalltalk appears to have more types, though it too is dynamic.
Variables and arguments lack types there, too, but all objects have a
fixed type from birth. CLOS is built on top of Lisp rather than built
*into* Lisp, by contrast, so its objects' classes are not something
the compiler can really know much about. This also precludes some
types of optimization, since all dispatch has to be done at run-time.

It is not dissimilar from how tables of function pointers in C can be
used to emulate object-oriented dispatch, but will not receive
optimizations from the C compiler that a C++ compiler would make to
its vtables. The C++ compiler both knows about the latter, and has
control over their layout.

A similar performance difference exists between C++ garbage collection
implementations and Java's. A C++ gc can't make any assumptions about
program data and object layout: every sequence of four bytes (every
aligned sequence, or sequence of eight bytes, on some architectures)
is potentially a pointer that should prevent its target from being
collected. A JVM's collector gets to benefit from the JVM knowing
exactly how objects are structured and laid out in memory; it can know
exactly what is really a pointer and what is some other kind of data.

This last at first seems to be about garbage collection, and about how
building something into the language and its tools instead of building
it on top of the language can create optimization opportunities, but
if you look closely you may note that it's actually also about types:
the JVM's collector can distinguish among pointers, ints, floats,
bools, doubles, longs, and shorts, whereas a C++ collector cannot,
because there's more run-time type information and because the
knowledge of this type information is built into the language tools,
compiler, and runtime rather than being up to the programmer's whims.

Lisp's garbage collector likewise can presumably distinguish pointers
from values and thus exhibit the efficiency of Java's. Unfortunately,
its object system is another story, to hear you guys tell it, because
it's implemented on top of the language, like object-oriented C code,
rather than built into the language, like C++ or Java objects. The one
difference being that CLOS was essentially made into a library, unlike
faking vtables in C, which tends to be done manually. That difference
may make CLOS easier to use, but it will not make it easier for the
compiler to optimize.
 
S

Series Expansion

Well , I did warn in [1] that the argument and counterargument
have been brought up before , years ago , on comp.lang.python so
you shouldn't be surprised if you encounter here it as well. I
think [1] appeared before you started commenting on macros.
What's this [1] shit? Some creative sort of pseudo-pronoun?
Who gives a crap. I can't figure it out without more information than
you've apparently chosen to provide.

[1] is a footnote.

You were writing a usenet post, not an academic paper. Please stick to
the style guidelines.
For the record, I never said such a thing.

You, personally, may not have, but your side of the debate did, in
<[email protected]>:

Ok, then let me summarize lisp macros as being hooks in the lisp
compiler.

Imagine what you could do if you could modify your compiler on
the fly

That your side's position is apparently somewhat incoherent does not
aid its credibility.
You're trolling, aren't you?

Your side's penchant for randomly inserting personal attacks into its
posts also does not aid its credibility.
I checked your Google profile and you only have posts in this
thread. So I guess you saw that a flamewar was brewing and you
decided to jump in to push people's buttons.

Actually, no. I was lurking, as new users commonly do, when a subject
came up that interested me sufficiently to decide to author a post,
essentially to ask whether Lisp had yet reached the maturity to be
used for desktop applications and similar everyday programming
purposes. It had not, but the question sparked a discussion that has
now unfortunately become somewhat acrimonious. It is worthy of note
that, in this thread, the primary sources of flamage thus far has been
comp.lang.lisp, not comp.lang.java.programmer, and that the
comp.lang.java.programmer poster with the largest contribution of
namecalling and vitriol thus far has been Lew, not I.
 
S

Series Expansion

I didn't say that the Java side is wrong. I just say things work
differently both ways, yadda yadda yadda

Oddly enough, this does not seem to be an apology or even an
acknowledgement of having been in error, despite the quoted material
immediately above it.

Furthermore, the following:

apparently was an outright lie. Remarkable.
But you still haven't given one argument independent of syntax and
implementation.

I have done so in several recent posts. Perhaps you have accidentally
marked them as "read" within your news client, prior to actually
reading them? I have done so again in some posts written after yours
above, but before this particular response of mine. I suggest you
locate and read all of the posts in question.
the way that the programmers think.

Is that to be your final redoubt, then? A claim that Lisp programmers'
thought processes are in fact alien, and that this enables them to
avoid many of the pitfalls that would affect any human programmers
attempting a large scale project in the language? You'll pardon me if
I find that difficult to believe without some kind of evidence.

On the other hand, there is much about the behavior of some of the
participants in this thread that could be explained by the hypothesis
that Lisp programmers are alien. Although Lew's behavior would remain
a mystery.
Unless the user knows the macro locally creates a variable. This
shadowing variable thing is well known - we are not amateurs - and we
take a lot of care when using features like that.

That you neglected to even address the point until now suggested that
perhaps you were unaware of it. One plausible explanation of that
would of course have been that you were amateurs. That would also
explain, through the psychological phenomenon of projection, the
claims recently mooted among you that we Java programmers are
amateurs.

If that is not the case, however, then those mysteries remain unsolved
for now.

A further examination of what you have just written is warranted now,
since it furnishes the Java side with the tools to achieve immediate
victory:
Unless the user knows the macro locally creates a variable.

And that, as they say, is "the rub". The user must know each macro's
detailed internals to use it safely, and not merely its intended
semantics and its call signature, unlike with a function or method.
This has been one of my contentions all along, and you have now
confirmed it in full public view. Thank you for that.

The inherent unsafety of macros, particularly the lack of a certain
encapsulation barrier that functions possess, and the problems
consequently attendant upon any editing of macro bodies in a large
code base thus established, I rest my case.
This shadowing variable thing is well known

I'm sure it is. One generally knows well the most frequent sources of
one's headaches.
we take a lot of care when using features like that.

Unfortunately, it is evident that you must take a lot of care when
anyone on the development team uses features like that, with "features
like that" including any nontrivial macro.
I have never seen other macro that captures some variable like that. It
is rare, and, when done, it is done very carefully.

Now this simply does not seem plausible. The only way to avoid the
noted issues completely is to avoid using any temporaries inside
nearly all macros, which would severely constrain what they can do. As
for "when done, it is done very carefully", this seems to allow no
scope for accidents.

Perhaps you have none, the consequences being so catastrophic that you
are very slow, careful, and deliberate, like workers in a virology lab
handling phials containing deadly pathogens. This is not going to
combine well with the fast-paced world of modern large-scale software
development efforts, however; that degree of caution is incompatible
with meeting next month's deadlines.

Unfortunately, there still seem to be over 100 more posts in this
thread. Obviously some participants are still posting voluminously,
even to the extent that it is not easy for me to get caught up. This
is probably because, unlike I, some of the participants have allowed
this to become personal for them, the result, as usual, being an
unfortunate amount of acrimony and a pointless waste of bandwidth.
 

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,691
Members
48,796
Latest member
Greg L.

Latest Threads

Top