Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

looking for a language with any of the following 4 charachteristics (all 4 would be nice).

9,942 views
Skip to first unread message

zaphod

unread,
Feb 11, 2002, 8:48:16 PM2/11/02
to
My idea of the perfect language would be something like any of the
four following:

1)Logo that concentrated on lisp tricks and didn't even HAVE
turtle-graphics
2)Forth w/out all that OS STUFF, and stack STUFF.
3)lisp without so many parentheses
4)C without structured programming concepts

Anyone got a good candidate?

I'll even let you tell me how dumb I am for wanting what I want.
It seems that the common denominator of the four languages I like is
that they are all extensible, and I think all could be said to have
charachteristics of functional languages.

Someone could make me extraordinarilly happy by a real nice thorough
analysis of my essentially stupid and trivial thought(s) here.

Daniel Barlow

unread,
Feb 12, 2002, 4:57:53 AM2/12/02
to
Sla...@ureach.com (zaphod) writes:

> 1)Logo that concentrated on lisp tricks and didn't even HAVE
> turtle-graphics
> 2)Forth w/out all that OS STUFF, and stack STUFF.
> 3)lisp without so many parentheses
> 4)C without structured programming concepts

5) Assembler without all that addressing mode cruft

6) Plain txt fils without the lttr '', bcaus lts fac it, it's silly


-dan

--

http://ww.tlnt.net/cliki/ - Link farm for fr CL-on-Unix rsourcs

Raymond Wiker

unread,
Feb 12, 2002, 5:40:30 AM2/12/02
to
Daniel Barlow <d...@telent.net> writes:

> Sla...@ureach.com (zaphod) writes:
>
> > 1)Logo that concentrated on lisp tricks and didn't even HAVE
> > turtle-graphics
> > 2)Forth w/out all that OS STUFF, and stack STUFF.
> > 3)lisp without so many parentheses
> > 4)C without structured programming concepts
>
> 5) Assembler without all that addressing mode cruft
>
> 6) Plain txt fils without the lttr '', bcaus lts fac it, it's silly

^ You missed one.

Of the original list, the three first items seemed to be about
removing a (the) "defining feature" of the language - seems like a
pretty pointless exercise.

--
Raymond Wiker Mail: Raymon...@fast.no
Senior Software Engineer Web: http://www.fast.no/
Fast Search & Transfer ASA Phone: +47 23 01 11 60
P.O. Box 1677 Vika Fax: +47 35 54 87 99
NO-0120 Oslo, NORWAY Mob: +47 48 01 11 60

Try FAST Search: http://alltheweb.com/

Marco Antoniotti

unread,
Feb 12, 2002, 10:13:22 AM2/12/02
to

Sla...@ureach.com (zaphod) writes:

I think that by definition, INTERCAL (whose design goal was to remove
any feature known to any other programming language) fits the bill.

Cheers


--
Marco Antoniotti ========================================================
NYU Courant Bioinformatics Group tel. +1 - 212 - 998 3488
719 Broadway 12th Floor fax +1 - 212 - 995 4122
New York, NY 10003, USA http://bioinformatics.cat.nyu.edu
"Hello New York! We'll do what we can!"
Bill Murray in `Ghostbusters'.

Nils Goesche

unread,
Feb 12, 2002, 11:45:06 AM2/12/02
to
In article <y6cit92...@octagon.mrl.nyu.edu>, Marco Antoniotti wrote:
>
> Sla...@ureach.com (zaphod) writes:
>
>> My idea of the perfect language would be something like any of the
>> four following:
>>
>> 1)Logo that concentrated on lisp tricks and didn't even HAVE
>> turtle-graphics
>> 2)Forth w/out all that OS STUFF, and stack STUFF.
>> 3)lisp without so many parentheses
>> 4)C without structured programming concepts
>>
>> Anyone got a good candidate?
>>
>> I'll even let you tell me how dumb I am for wanting what I want.
>> It seems that the common denominator of the four languages I like is
>> that they are all extensible, and I think all could be said to have
>> charachteristics of functional languages.
>>
>> Someone could make me extraordinarilly happy by a real nice thorough
>> analysis of my essentially stupid and trivial thought(s) here.
>
> I think that by definition, INTERCAL (whose design goal was to remove
> any feature known to any other programming language) fits the bill.

No, he wants a functional language. So, I think this is closer:

http://www.eleves.ens.fr:8080/home/madore/programs/unlambda/

Regards,
--
Nils Goesche
"Don't ask for whom the <CTRL-G> tolls."

PGP key ID 0x42B32FC9

Eric Moss

unread,
Feb 12, 2002, 3:29:24 PM2/12/02
to
zaphod wrote:
>
> My idea of the perfect language would be something like any of the
> four following:
>
> 1)Logo that concentrated on lisp tricks and didn't even HAVE
> turtle-graphics
> 2)Forth w/out all that OS STUFF, and stack STUFF.
> 3)lisp without so many parentheses
> 4)C without structured programming concepts
>
> Anyone got a good candidate?

Yes.

Common Lisp comes closest for you, despite your loathing of
parentheses. First off, your dislikes wrt the other languages appear to
be structural and therefore unavoidable. Your beef with Lisp appears to
be cosmetic. That is least problematic when it comes to making a
working piece of code.

Addressing the parentheses phobia, which I see in other students in my
AI course, I say several things.

Firstly, parentheses are actually a necessity. You have to have *some*
delimiter in a language, after all, and it can't be just whitespace.

Secondly, parentheses are an *advantage* over other delimiters. Note
that C uses {} and ; and " " and ",", so it only *appears* to not be
full of delimiters. Lisp is far more elegant, separating tokens with
whitespace and expressions with ().

Thirdly, with a good editor, the parentheses become minor blips on your
screen, and the indentation (which is orthogonal to what makes parsing
easy for the compiler) can be your guide. If you wanted, you could even
customize the indentation, although lots of experience indicates that
emacs does just fine.

To summarize, Lisp appears to have everything you want except for its
cosmetic "flaw", which isn't really a flaw. That can be gotten past
with experience or editor-tinkering. All the other languages have major
structural issues that can't be avoided.


Or something like that...

Eric

Thomas F. Burdick

unread,
Feb 12, 2002, 4:42:58 PM2/12/02
to
Eric Moss <eric...@alltel.net> writes:

> zaphod wrote:
> >
> > My idea of the perfect language would be something like any of the
> > four following:
> >
> > 1)Logo that concentrated on lisp tricks and didn't even HAVE
> > turtle-graphics
> > 2)Forth w/out all that OS STUFF, and stack STUFF.
> > 3)lisp without so many parentheses
> > 4)C without structured programming concepts
> >
> > Anyone got a good candidate?
>
> Yes.
>
> Common Lisp comes closest for you, despite your loathing of
> parentheses. First off, your dislikes wrt the other languages appear to
> be structural and therefore unavoidable. Your beef with Lisp appears to
> be cosmetic. That is least problematic when it comes to making a
> working piece of code.
>
> Addressing the parentheses phobia, which I see in other students in my
> AI course, I say several things.
>
> Firstly, parentheses are actually a necessity. You have to have *some*
> delimiter in a language, after all, and it can't be just whitespace.

Hell, since the parens are just the textual way of representing the
structure of the code, you could use a structure editor and never see
another paren again. Writing said editor is left as an exercise to
the reader.

--
/|_ .-----------------------.
,' .\ / | No to Imperialist war |
,--' _,' | Wage class war! |
/ / `-----------------------'
( -. |
| ) |
(`-. '--.)
`. )----'

Erik Naggum

unread,
Feb 12, 2002, 5:16:14 PM2/12/02
to
* Eric Moss <eric...@alltel.net>

| Addressing the parentheses phobia, which I see in other students in my AI
| course, I say several things.

I wonder if it is the parentheses or the enclosing delimiter. For some
time, now, I have been trying to understand how people react to Lisp, and
something occurred to me some tima ago that was recently reinforced. In
almost all other programming languages, parentheses are actually painful,
or symptoms of something painful. E.g., in those stupid infix syntaxes,
you need parentheses when the precedences of the operators you want to
combine are not related the way you want them to be. So the parentheses
become a means of resolving a conflict between the language and your
needs. In C-style languages, where type casts are necessary due to the
retarded type system, parentheses are used to resolve a conflict between
what the language thinks should be the type of something and what you
want it to be. The number of parentheses thus correlate with the level
of complexity, and the level of complexity with how hard it is to grasp.
The only "neutral" parentheses are those used in function calls. The
rest of the delimiters serve different purposes and also look different.

However, in (Common) Lisp, parentheses are the only game in town (well,
this is not true, but to the extent they are, bear with me), and all the
emotionsl responses to parentheses-as-pain-indicators from languages that
the programmer may have been previously exposed to come right back at him
at a very low level of consciousness. Any thinking person would observe
his reaction and think about it, but thinking peopla are never a problem.
Those who only react and feel that something must be wrong with all the
parentheses, may have a very particular reaction to parentheses. I have
had occasion to exploit this recently to test the hypothesis.

< and > are accetable delimiters these days, so I changed the reader and
printer to use them instead of ( and ). (The only practical problem was
that symbols with < and > in them needed to have that character escaped.)
Presented to two people who had previously been negative to Lisp, one of
them thought it was OK, now, the other went "you can't trick me into
liking Lisp". Presented to three people who were predicted to have a
strong dislike of parentheses, but had not had prior exposure to Lisp,
all three found it interesting, and one thought the parentheses of the
original code looked silly when presented with it -- the others quickly
figured out what the point of the exercise was, but did not react with
hostility to the parentheses. I found only one person whom I thought
would not be hostile to parentheses, but he was hostile to all the HTML
crap, instead, effectively being more annoyed with <> than with ().
This, of course, serves no useful statistical purposes, but I do not want
to run a research project on this. I would like to experiment with
working with this syntax for a while just to see how I think it works,
however. It might actually be the easiest way to get around the
parenthesis "perception problem".

/// 2002-02-12
--
In a fight against something, the fight has value, victory has none.
In a fight for something, the fight is a loss, victory merely relief.

Software Scavenger

unread,
Feb 13, 2002, 1:41:34 AM2/13/02
to
Erik Naggum <er...@naggum.net> wrote in message news:<32225409...@naggum.net>...

> I wonder if it is the parentheses or the enclosing delimiter. For some
> time, now, I have been trying to understand how people react to Lisp, and

My first reaction to Lisp parentheses before I started learning Lisp
was that there were three main reasons why I didn't like them. First,
I saw long strings of them in Lisp and wondered if I was expected to
count them every time I saw them, or how I could be sure they were
right without counting them. Second, parentheses are awkward on most
keyboards. They're more likely to be fumbled more often, because of
the combination of the shift key, the distance to the parentheses
keys, and the awkward combination of fingers used to type them.
Third, it seemed to me that infix syntax was making compilers do more
work to reduce the amount of work done by the programmer, and that
therefore the non-infix parentheses-based syntax was a way of taking
some of the work load off the compiler and putting it on the
programmer.

Holger Schauer

unread,
Feb 13, 2002, 5:33:27 AM2/13/02
to
On 12 Feb 2002, Software Scavenger wrote:
> Erik Naggum <er...@naggum.net> wrote in (some) message:

>> I wonder if it is the parentheses or the enclosing delimiter.
>> For some time, now, I have been trying to understand how people
>> react to Lisp, and
> First, I saw long strings of them in Lisp and wondered if I was
> expected to count them every time I saw them, or how I could be sure
> they were right without counting them.

That was the one thing I really hated in the intro-course on Lisp that
I have taken. Once I learned the joys of Emacs (some five years
later), the parentheses "problem" disappeared without a trace. Hence,
the first thing I actually showed my students this year was a really
awkward and painful written peace of Lisp code. Next, I showed them
what it would look like to write it in Emacs. I then turned to show
them the same code with parens removed and told them not to count
parens but to use the structure of the code. Now that the course is
done, most of the code they've written actually looks pretty lispy.

> Second, parentheses are awkward on most keyboards. They're more
> likely to be fumbled more often, because of the combination of the
> shift key, the distance to the parentheses keys, and the awkward
> combination of fingers used to type them.

You should take a look at a German keyboard and try the key
combinations necessary to insert curly braces. Alt-Gr-7 and 8. Now
that's awkward (and the reason why German programmers sometimes prefer
using qwerty keyboards over German qwerty ones).

Holger

--
--- http://www.coling.uni-freiburg.de/~schauer/ ---
Fachbegriffe der Informatik - Einfach erklärt
49: Version x.0
Kostenpflichtiger Preview als Bestandteil unserer Beta-Tests
(Kristian Köhntopp)

Brian Campbell

unread,
Feb 13, 2002, 10:25:41 AM2/13/02
to
In article <42e37222.02021...@posting.google.com>,
Sla...@ureach.com (zaphod) wrote:

> My idea of the perfect language would be something like any of the
> four following:
>
> 1)Logo that concentrated on lisp tricks and didn't even HAVE
> turtle-graphics
> 2)Forth w/out all that OS STUFF, and stack STUFF.
> 3)lisp without so many parentheses
> 4)C without structured programming concepts
>
> Anyone got a good candidate?

Well, to respond to exactly what you've asked for, I'd recommend Dylan
(which is a descendant of lisp with infix syntax) or ML (which is a
functional programming language with infix syntax, although it may seem
more weird to you than Dylan).

For Dylan, see the pages of the two implementations:
http://www.gwydiondylan.org (the open source implementation)
http://www.fun-o.com (the commercial implementation)

A web search should suffice for finding out stuff about ML (I've found
that when doing web searches about Dylan, I find lots of out of date
pages, so you have to know where to look to find the decent information).

>
> I'll even let you tell me how dumb I am for wanting what I want.
> It seems that the common denominator of the four languages I like is
> that they are all extensible, and I think all could be said to have
> charachteristics of functional languages.

Other languages you might want to consider but I can't say much about
are Oz/Mozart, Erlang, Haskell, Mercury, Smalltalk, or Self.

Of course, as plenty of other people have pointed out, the parentheses
in lisp really aren't that much of a problem, and lisp is far more
mature and complete than any of these other languages I've pointed out.
I've found that as I look at the newest features people are adding to
other languages and the problems people are encountering, they all seem
to have been solved in Lisp 20 years ago (that may be a slight
exaggeration, but not much of one).

Actually, though it makes me shudder to recommend it, the feature set of
perl seems to be slowly converging on an infix lisp, but perl is not a
language I'd recommend for anyone who wants anything close to resembling
elegance


>
> Someone could make me extraordinarilly happy by a real nice thorough
> analysis of my essentially stupid and trivial thought(s) here.

--
Brian Campbell
Real email: lambda (at) cs (dot) dartmouth (dot) edu

Ed L Cashin

unread,
Feb 13, 2002, 9:04:45 PM2/13/02
to
Erik Naggum <er...@naggum.net> writes:

...


> I would like to experiment with
> working with this syntax for a while just to see how I think it works,
> however. It might actually be the easiest way to get around the
> parenthesis "perception problem".

I don't know. Holger Schauer has a point: emacs makes it easy to edit
lisp, but many people don't use emacs. If I didn't already feel
confident that emacs will keep track of the parens and the indentation
for me on first encountering lisp, the nesting might appear
overwhelming.

Also, I remember thinking that lisp looked like "text vomit" compared
to languages whose structure lexically mirrors what's going on.
Here's an example in ruby:

{
"foo" => "bar",
"baz" => "burfle",
}.each { |i|
puts i
}

Which, once you're used to it, looks at a glance like a hash table
followed by some code to do for each thing in it. More importantly,
even before you're used to it, the structure suggests that there's
some structured data on top and some code on the bottom.

Lisp is more verbose, and at a glance always looks like text and
parentheses:

(let ((h (make-hash-table)))
(setf (gethash "foo" h) "bar")
(setf (gethash "foo" h) "bar")
(maphash
#'(lambda (k v)
(format t "~A~%" k)
(format t "~A~%" v)) h))

I know that an experienced lisper could create a read macro to support
a syntax like in the first example, but someone encountering lisp for
the first time might not know that.

My first time seeing a large amount of lisp code was in the emacs
sources.

--
--Ed L Cashin | PGP public key:
eca...@uga.edu | http://noserose.net/e/pgp/

zaphod

unread,
Feb 13, 2002, 10:06:23 PM2/13/02
to
Raymond Wiker <Raymon...@fast.no> wrote in message news:<86pu3br...@raw.grenland.fast.no>...

> Daniel Barlow <d...@telent.net> writes:
>
> > Sla...@ureach.com (zaphod) writes:
> >
> > > 1)Logo that concentrated on lisp tricks and didn't even HAVE
> > > turtle-graphics
> > > 2)Forth w/out all that OS STUFF, and stack STUFF.
> > > 3)lisp without so many parentheses
> > > 4)C without structured programming concepts
> >
> > 5) Assembler without all that addressing mode cruft
> >
> > 6) Plain txt fils without the lttr '', bcaus lts fac it, it's silly
>
> ^ You missed one.
>
> Of the original list, the three first items seemed to be about
> removing a (the) "defining feature" of the language - seems like a
> pretty pointless exercise.


I think I mentioned that! I covered all that junk. You probably read
the meat and ignored my side dishes! Don't eat ever eat in the
restaurant I want to own, or I might put a little surprise in the
secret sauce!
Thank you for replying!

zaphod

unread,
Feb 13, 2002, 10:08:06 PM2/13/02
to
Marco Antoniotti <mar...@cs.nyu.edu> wrote in message news:<y6cit92...@octagon.mrl.nyu.edu>...

> Sla...@ureach.com (zaphod) writes:
>
> > My idea of the perfect language would be something like any of the
> > four following:
> >
> > 1)Logo that concentrated on lisp tricks and didn't even HAVE
> > turtle-graphics
> > 2)Forth w/out all that OS STUFF, and stack STUFF.
> > 3)lisp without so many parentheses
> > 4)C without structured programming concepts
> >
> > Anyone got a good candidate?
> >
> > I'll even let you tell me how dumb I am for wanting what I want.
> > It seems that the common denominator of the four languages I like is
> > that they are all extensible, and I think all could be said to have
> > charachteristics of functional languages.
> >
> > Someone could make me extraordinarilly happy by a real nice thorough
> > analysis of my essentially stupid and trivial thought(s) here.
>
> I think that by definition, INTERCAL (whose design goal was to remove
> any feature known to any other programming language) fits the bill.
>
> Cheers

Intercal is a joke. I'm very stupid; but I'm just smart enough to know that!

Wade Humeniuk

unread,
Feb 13, 2002, 10:11:56 PM2/13/02
to

"Ed L Cashin" <eca...@uga.edu> wrote in message
news:863d04e...@cs.uga.edu...

>
> Also, I remember thinking that lisp looked like "text vomit" compared
> to languages whose structure lexically mirrors what's going on.
> Here's an example in ruby:
>
> {
> "foo" => "bar",
> "baz" => "burfle",
> }.each { |i|
> puts i
> }
>
> Which, once you're used to it, looks at a glance like a hash table
> followed by some code to do for each thing in it. More importantly,
> even before you're used to it, the structure suggests that there's
> some structured data on top and some code on the bottom.
>

I have a dumb question, but of what use is the preceding Ruby code? I do
not even see the hash table in that code, where is it and how do you refer
to it outside the code fragment? Overloading of {??

> Lisp is more verbose, and at a glance always looks like text and
> parentheses:
>
> (let ((h (make-hash-table)))
> (setf (gethash "foo" h) "bar")
> (setf (gethash "foo" h) "bar")
> (maphash
> #'(lambda (k v)
> (format t "~A~%" k)
> (format t "~A~%" v)) h))
>

All your ruby code above seems to do is

(write '((foo bar) (baz burfle)))

or more tersely

'((foo bar) (baz burfle))

Wade


zaphod

unread,
Feb 13, 2002, 10:16:06 PM2/13/02
to
Eric Moss <eric...@alltel.net> wrote in message news:<3C697B24...@alltel.net>...


From experience (very little, but it don't take more)it is not just
cosmetic to me! If it were just a matter of making sure you close all
of your parentheses; that would be fine (i've figured that out, just
close with a zero, on a count-down from all open parentheses), but the
problem is, I think you have to know the whole damned kit-and kaboodle
to know WHEN to open, and WHEN to close; either that or I have yet to
find anything that adresses the idea behind the opening and closing of
them.

Ed L Cashin

unread,
Feb 13, 2002, 10:20:55 PM2/13/02
to
"Wade Humeniuk" <hume...@cadvision.com> writes:

> "Ed L Cashin" <eca...@uga.edu> wrote in message
> news:863d04e...@cs.uga.edu...
> >
> > Also, I remember thinking that lisp looked like "text vomit" compared
> > to languages whose structure lexically mirrors what's going on.
> > Here's an example in ruby:
> >
> > {
> > "foo" => "bar",
> > "baz" => "burfle",
> > }.each { |i|
> > puts i
> > }

...


> I have a dumb question, but of what use is the preceding Ruby code? I do
> not even see the hash table in that code, where is it and how do you refer
> to it outside the code fragment? Overloading of {??

It simply illustrates that the code that creates a hash tables is
visually reminiscent of the relationships that the hash table
represents. To keep track of the variable for later you'd just use a
variable:

h = {


"foo" => "bar",
"baz" => "burfle",
}.each { |i|
puts i
}

h.each { |i| puts i } # or whatever you want to do with h


The lisp example did the same thing as the ruby example -- creating a
hash table and printing its contents. But my point was the visual
impact of the syntax and had nothing to do with the use of the example
code.

> > Lisp is more verbose, and at a glance always looks like text and
> > parentheses:
> >
> > (let ((h (make-hash-table)))
> > (setf (gethash "foo" h) "bar")
> > (setf (gethash "foo" h) "bar")
> > (maphash
> > #'(lambda (k v)
> > (format t "~A~%" k)
> > (format t "~A~%" v)) h))
> >
>
> All your ruby code above seems to do is
>
> (write '((foo bar) (baz burfle)))
>
> or more tersely
>
> '((foo bar) (baz burfle))

True.

zaphod

unread,
Feb 13, 2002, 10:23:28 PM2/13/02
to
Erik Naggum <er...@naggum.net> wrote in message news:<32225409...@naggum.net>...

Not with me. I have no problem with parentheses, except that I don't
know all the rules to their use, and I don't want to learn the entire
common-lisp language to find out; either. I may do so, but I WILL
find a better way, if I can!

zaphod

unread,
Feb 13, 2002, 10:31:37 PM2/13/02
to
Brian Campbell <lambd...@yahoo.com> wrote in message news:<lambda2000-0F772...@merrimack.dartmouth.edu>...


Thank You very much. I'm quite pleased. Have you checked out python, by the way?

Ed L Cashin

unread,
Feb 13, 2002, 11:09:56 PM2/13/02
to
Sla...@ureach.com (zaphod) writes:

...


> Not with me. I have no problem with parentheses, except that I
> don't know all the rules to their use, and I don't want to learn the
> entire common-lisp language to find out; either. I may do so, but I
> WILL find a better way, if I can!

As far as this lisp beginner can tell, it's pretty simple:

* parentheses go around a list

* when a list is evaluated the first thing is treated as a function
and the following things in the list are the function arguments.

There are abbreviations (like the single quote character) and special
cases (special forms), and extensions (like read macrose), but that
seems to be the general idea. Add the fact that lists can be elements
a list, and you're off!

Marc Spitzer

unread,
Feb 13, 2002, 11:36:40 PM2/13/02
to

Here are the rules that work for me, a begining lisper working on small
stuff, probably not the real reason but it has worked so far:

name ; it gets evaled no parens
(function_name ; it get evaled as a function, because it is the first
; thing that lisp sees after a open paren

Some thing like cond conditions or let apear different, they start with 2
parens, but that is because there is some stuff going on behind the seens.
With cond I think the first form is just checked for a boolena return value
so you need to scope what is checlked by wrapping it in a set of parens,
unless you are checking the value of a varable then you can just type it.
There I have contradicted my self, it is time to shut up now.

so the short answer is when you need a function use a paren and when it is
done close it.

good luck

marc

Tim Bradshaw

unread,
Feb 14, 2002, 6:58:57 AM2/14/02
to
* Ed L Cashin wrote:

> It simply illustrates that the code that creates a hash tables is
> visually reminiscent of the relationships that the hash table
> represents. To keep track of the variable for later you'd just use a
> variable:

> h = {
> "foo" => "bar",
> "baz" => "burfle",
> }.each { |i|
> puts i
> }

> h.each { |i| puts i } # or whatever you want to do with h


> The lisp example did the same thing as the ruby example -- creating a
> hash table and printing its contents. But my point was the visual
> impact of the syntax and had nothing to do with the use of the example
> code.

Yes, I think this is what Lisp is about. Languages like Perl or Ruby
(or C) have decided that one sort of thing is interesting, and have a
syntax which has been greatly optimized for that single thing. Perl
is *really good* at string-bashing code with regexps, C is really good
at very terse OS code that both runs and can be compiled in reasonable
time on a PDP11-class machine, and so on.

Lisp has decided not to decide. Rather than provide a great mass of
syntactic tricks to support some particular style or programming
technique, Lisp provides a minimalist syntax which is just adequate to
express nested structures of various kinds without making any
commitment as to their meaning. The programmer then decides what this
syntax means in any instance.

Lisp is a toolkit for language design not a toolkit for solving
problems in particular domain. Of course, people will typically
evolve special languages in Lisp if they need to spend enough time in
any one domain to make it worth while, but since those languages are
usually application specific and not well-known, it's always easy to
demonstrate that any given language has a better syntax for any given
application than Lisp does.

--tim

Erik Naggum

unread,
Feb 14, 2002, 8:12:00 AM2/14/02
to
* Ed L Cashin <eca...@uga.edu>

| Also, I remember thinking that lisp looked like "text vomit" compared
| to languages whose structure lexically mirrors what's going on.

It appears warranted by the various reactions people have posted and told
of elsewhere to conclude that Common Lisp is a language that is better
suited for those who are more verbal than visual in how they remember and
learn. Those who are more visual, tend to be thrown off by the lack of
visual clues and the preponderance of words they need to recognize in
order to "see" the structure. The verbal, who recognize words the way
the visual see pictures and figures, have no such problem.

However, since XML and the like is not the disaster it should have been,
I guess that either those who use it are completely clueless verbally as
well as visually (95% chance of being true) or people can learn to be
more verbal even if they are "naturally" visual (5% chance of being true).

This is not to imply that those who are more verbal than visual are
superior beings, but they are clearly more suited to certain tasks than
those who are more visual.

///

Erik Naggum

unread,
Feb 14, 2002, 8:15:22 AM2/14/02
to
* Sla...@ureach.com (zaphod)

| Not with me. I have no problem with parentheses, except that I don't
| know all the rules to their use, and I don't want to learn the entire
| common-lisp language to find out; either. I may do so, but I WILL
| find a better way, if I can!

Quite amazing. It is obviously superfluous to answer any of your
questions with technical answers. This is good to know.

///

Tim Bradshaw

unread,
Feb 14, 2002, 8:33:29 AM2/14/02
to
* Erik Naggum wrote:

> It appears warranted by the various reactions people have posted and told
> of elsewhere to conclude that Common Lisp is a language that is better
> suited for those who are more verbal than visual in how they remember and
> learn. Those who are more visual, tend to be thrown off by the lack of
> visual clues and the preponderance of words they need to recognize in
> order to "see" the structure. The verbal, who recognize words the way
> the visual see pictures and figures, have no such problem.

I think this is an interesting point. However I'm not sure it's right
or at least not uniquely right. I think I'm a terribly visual person
(although I also can read). Whenever I write systems in Lisp (or any
other language, but my only recent experience of non-trivial systems
is Lisp), I end up with a huge mass of throwaway `browser'-type tools
which show me pictures of the various structures in the system. I
find it fairly hard to work without these tools. One of the beauties
of Lisp, for me, is that it's so good at talking about complex data
structures, and that typically it's easy to get pictures of these
things of various kinds.

--tim

Holger Schauer

unread,
Feb 14, 2002, 8:43:10 AM2/14/02
to
On Thu, 14 Feb 2002, Erik Naggum wrote:
> * Ed L Cashin <eca...@uga.edu>
>| Also, I remember thinking that lisp looked like "text vomit"
>| compared to languages whose structure lexically mirrors what's
>| going on.

I think the structure of Lisp does mirror what's going on.



> It appears warranted by the various reactions people have posted
> and told of elsewhere to conclude that Common Lisp is a language
> that is better suited for those who are more verbal than visual in
> how they remember and learn. Those who are more visual, tend to
> be thrown off by the lack of visual clues and the preponderance of
> words they need to recognize in order to "see" the structure. The
> verbal, who recognize words the way the visual see pictures and
> figures, have no such problem.

I wonder on what basis you draw the conclusion that the distinction is
between verbal and visual and wonder even more about the possible
implications. For instance, a verbal learner should not be thrown off
by code like (member (car (list (do-something here (based on another
complicated computation) ... <bunch of further arguments elided>)))).
This seems counterintuitive to me, I think even experienced Lisp
programmers tend to have (reading) problems with such gross code. [1]

With respect to the more visual oriented, I think what helped me most
was to recognize that there is structure but that parentheses are not
an issue one needs to care about, as long as you do follow it. I think
Graham has an example in his "Ansi CL" book in which he presents some
Lisp code with and without the parens. It's getting the structure that
matters, not the parens. I think, a claim somebody made is likely to
be true across most programming languages, which is that it does not
really matter what style you're following, it's following the style
that matters [2].

But then again, I may be one of those who you would classify as a
visual oriented person, although I tend to see myself as being verbal
oriented. Come to think of it, I'm a very unlikely candidate for
participating in an obfuscated code contest, although I am uncertain
whether that tells a story or doesn't.

Holger

Footnotes:
[1] Some time ago, I made some whitespace modifications to some old
and very ugly looking code. I was not the only one feeling that the
result was much more readable afterwards.

[2] Of course, when you have to follow some style guideline enforced
by external forces, this may throw you off when its totally against
your personal preferences.

"/home/moehwald > echo "the quick brown fox jumps over the lazy dog" |
tr -d aeiou"
"Jetzt weiss ich endlich, wie ein gewisser A.K. seine Postings erstellt."
-- Sven Geggus in de.comp.os.unix.linux.misc

Marco Antoniotti

unread,
Feb 14, 2002, 8:58:25 AM2/14/02
to

Sla...@ureach.com (zaphod) writes:

> Marco Antoniotti <mar...@cs.nyu.edu> wrote in message news:<y6cit92...@octagon.mrl.nyu.edu>...

...

> > I think that by definition, INTERCAL (whose design goal was to remove
> > any feature known to any other programming language) fits the bill.
> >
> > Cheers
>
> Intercal is a joke. I'm very stupid; but I'm just smart enough to
> know that!

Given your username.... :)

42

Ed L Cashin

unread,
Feb 14, 2002, 9:03:09 AM2/14/02
to
Tim Bradshaw <t...@cley.com> writes:

...


> Yes, I think this is what Lisp is about. Languages like Perl or
> Ruby (or C) have decided that one sort of thing is interesting, and
> have a syntax which has been greatly optimized for that single
> thing. Perl is *really good* at string-bashing code with regexps, C
> is really good at very terse OS code that both runs and can be
> compiled in reasonable time on a PDP11-class machine, and so on.
>
> Lisp has decided not to decide. Rather than provide a great mass of
> syntactic tricks to support some particular style or programming
> technique, Lisp provides a minimalist syntax which is just adequate
> to express nested structures of various kinds without making any
> commitment as to their meaning. The programmer then decides what
> this syntax means in any instance.

Yes, and I think that's why it often requires a little bit of
experience with several programming that are good in a more limited
domain before lisp's generality can be recognized as a boon.

Marco Antoniotti

unread,
Feb 14, 2002, 9:10:19 AM2/14/02
to

Ed L Cashin <eca...@uga.edu> writes:

> Erik Naggum <er...@naggum.net> writes:
>
> ...
> > I would like to experiment with
> > working with this syntax for a while just to see how I think it works,
> > however. It might actually be the easiest way to get around the
> > parenthesis "perception problem".
>
> I don't know. Holger Schauer has a point: emacs makes it easy to edit
> lisp, but many people don't use emacs. If I didn't already feel
> confident that emacs will keep track of the parens and the indentation
> for me on first encountering lisp, the nesting might appear
> overwhelming.
>
> Also, I remember thinking that lisp looked like "text vomit" compared
> to languages whose structure lexically mirrors what's going on.
> Here's an example in ruby:
>
> {
> "foo" => "bar",
> "baz" => "burfle",
> }.each { |i|
> puts i
> }

(map* #'print
(make-hash-table* '(("foo" => "bar")
("baz" => "bar"))))

Hello!!!!!!

The point being that in CL you can modify the language, and make it
look like CL or something else.

Here is one of my favourite `primes' in conforming CL.

(in-package "SETL-USER")

(defun primes (max)
[n in (range 3 max 2)
/ (not (exist m in (range 3 (min (1- n) (+ 2 (sqrt n))) 2)
/ (= (mod n m) 0)))])

> I know that an experienced lisper could create a read macro to support
> a syntax like in the first example, but someone encountering lisp for
> the first time might not know that.

So? Does that warrant the application of Greenspun's Tenth? :)

> My first time seeing a large amount of lisp code was in the emacs
> sources.

A lot of ELisp code is not all that nice looking. Especially because
a lot of ELisp code does not (require 'cl) :)

Cheers

Christophe Rhodes

unread,
Feb 14, 2002, 9:17:32 AM2/14/02
to
Marco Antoniotti <mar...@cs.nyu.edu> writes:

> Here is one of my favourite `primes' in conforming CL.
>
> (in-package "SETL-USER")
>
> (defun primes (max)
> [n in (range 3 max 2)
> / (not (exist m in (range 3 (min (1- n) (+ 2 (sqrt n))) 2)
> / (= (mod n m) 0)))])

I appreciate the point, but I thought that we decided that "conforming
CL" programmes needed to include their macros and reader-macros to be
properly conforming... :-)

Christophe
--
Jesus College, Cambridge, CB5 8BL +44 1223 510 299
http://www-jcsu.jesus.cam.ac.uk/~csr21/ (defun pling-dollar
(str schar arg) (first (last +))) (make-dispatch-macro-character #\! t)
(set-dispatch-macro-character #\! #\$ #'pling-dollar)

Erik Naggum

unread,
Feb 14, 2002, 9:20:22 AM2/14/02
to
* Holger Schauer <Holger....@gmx.de>

| I wonder on what basis you draw the conclusion that the distinction is
| between verbal and visual and wonder even more about the possible
| implications.

Sigh. I wrote:

It appears warranted by the various reactions people have posted and
told of elsewhere to conclude that Common Lisp is a language that is
better suited for those who are more verbal than visual in how they
remember and learn.

| For instance, a verbal learner should not be thrown off by code like


| (member (car (list (do-something here (based on another complicated
| computation) ... <bunch of further arguments elided>)))). This seems
| counterintuitive to me, I think even experienced Lisp programmers tend to
| have (reading) problems with such gross code. [1]

On what basis do you conclude something about what a "verbal learner"
should or should not be thrown off by?

| But then again, I may be one of those who you would classify as a
| visual oriented person

Why do you think this is an either-or issue? When I write "more verbal
than visual" and try to be very clear that we are talking about a point
on a line between two extrama, please do not waste my time by assuming
that only the extrema are worth talking about. Nobody is "classified" as
a visual-oriented person, it is a matter of what you are more comfortable
with, not some one-bit flag in your personality.

Thom Goodsell

unread,
Feb 14, 2002, 9:32:23 AM2/14/02
to
Holger Schauer <Holger....@gmx.de> writes:
>
> I wonder on what basis you draw the conclusion that the distinction is
> between verbal and visual and wonder even more about the possible
> implications. For instance, a verbal learner should not be thrown off
> by code like (member (car (list (do-something here (based on another
> complicated computation) ... <bunch of further arguments elided>)))).
> This seems counterintuitive to me, I think even experienced Lisp
> programmers tend to have (reading) problems with such gross code. [1]
>
> With respect to the more visual oriented, I think what helped me most
> was to recognize that there is structure but that parentheses are not
> an issue one needs to care about, as long as you do follow it. I think
> Graham has an example in his "Ansi CL" book in which he presents some
> Lisp code with and without the parens. It's getting the structure that
> matters, not the parens. I think, a claim somebody made is likely to
> be true across most programming languages, which is that it does not
> really matter what style you're following, it's following the style
> that matters [2].
>

I don't believe Erik intended to suggest that verbal people can easliy
read poorly formatted code. Rather, lisp code is more about words than
about granting special meaning to every non-text character on your
keyboard. As a simple example, consider array access in Lisp and
C/C++/Java:

(aref *some-array* 10)
vs.
some_array[10];

In C, the braces take the place of "aref" and are easily spotted, even
by someone who has trouble spotting "aref" in a mass of text. Thus,
discounting syntactic characters (parens, semi-colons, and braces), C
code has a lot more non-character symbols than Lisp. The structure is
still important in both cases.

I show the extreme example of a visually-oriented language, but I've
so far managed to avoid learning any Perl.

Thom

--
(map 'string #'(lambda (char) (let ((char-code (char-code char)))
(code-char (if (< 64 char-code 123) (+ (mod (+ 13 char-code) 52) 65)
char-code)))) "Z...@IXG.IUS")

Julian Stecklina

unread,
Feb 14, 2002, 10:15:35 AM2/14/02
to
Sla...@ureach.com (zaphod) writes:

[...]

> Intercal is a joke. I'm very stupid; but I'm just smart enough to know that!

But it's nevertheless interesting. I got headache after the first few
pages of the "specification". :)

Regards,
Julian

--
Um meinen oeffentlichen Schluessel zu erhalten:
To get my public key:
http://math-www.uni-paderborn.de/pgp/

Dorai Sitaram

unread,
Feb 14, 2002, 10:26:39 AM2/14/02
to

I am inclined to agree, but just yesterday a coupla
posts here were praising special tools over
general tools. That also sounded somewhat agreeable
with at the time, except that their argument put CL
firmly on the side of the specializers, not
generalizers as the above seems to be doing (unless
Lisp is not being equated with CL).

--d

Holger Schauer

unread,
Feb 14, 2002, 10:05:08 AM2/14/02
to
On Thu, 14 Feb 2002, Erik Naggum wrote:
> * Holger Schauer <Holger....@gmx.de>
>| I wonder on what basis you draw the conclusion that the distinction
>| is between verbal and visual and wonder even more about the
>| possible implications.
>
> Sigh. I wrote:
>
> It appears warranted by the various reactions people have posted
> and told of elsewhere to conclude that Common Lisp is a language
> that is better suited for those who are more verbal than visual
> in how they remember and learn.

Yes, I actually read what you wrote but was not sure what exactly the
various reactions have led you to this conclusion, as I have
difficulties -- given what I've read in this thread -- to arrive at
the same.



>| For instance, a verbal learner should not be thrown off by code
>| like (member (car (list (do-something here (based on another
>| complicated computation) ... <bunch of further arguments
>| elided>)))). This seems counterintuitive to me, I think even
>| experienced Lisp programmers tend to have (reading) problems with
>| such gross code. [1]
>
> On what basis do you conclude something about what a "verbal
> learner" should or should not be thrown off by?

Good question. I was in fact just reacting to the second half of your
paragraph, substituting "visual learner" for your "those who are more
visual":

>> Those who are more visual, tend to be thrown off by the lack of
>> visual clues and the preponderance of words they need to
>> recognize in order to "see" the structure. The verbal, who
>> recognize words the way the visual see pictures and figures,
>> have no such problem.

As I said, I was wondering whether my "conclusion" would be a valid
implication of the distinction you put forward. It doesn't seem to be,
though. The question then is whether I'm bashing a strawmen or not (I
don't intend to).



>| But then again, I may be one of those who you would classify as a
>| visual oriented person
>
> Why do you think this is an either-or issue? When I write "more
> verbal than visual" and try to be very clear that we are talking
> about a point on a line between two extrama, please do not waste
> my time by assuming that only the extrema are worth talking about.
> Nobody is "classified" as a visual-oriented person, it is a matter
> of what you are more comfortable with, not some one-bit flag in
> your personality.

Yes, this is certainly true. However, I was wondering whether I'm as
verbal as I think I am and whether that leads me to some fast (and
wrong) conclusions.

Holger

Holger Schauer

unread,
Feb 14, 2002, 10:19:03 AM2/14/02
to
On 14 Feb 2002, Thom Goodsell wrote:
> I don't believe Erik intended to suggest that verbal people can
> easliy read poorly formatted code. Rather, lisp code is more about
> words than about granting special meaning to every non-text
> character on your keyboard.

Well, yes, I agree with that largely. I would not go as far as saying
that words don't matter in other languages (but then nobody said that,
either). They do matter, of course, as much as in CL, minus you've got
to get those non-text characters right first :-) Syntax can be pretty
annoying, but after all, it's just syntax, not semantics.

More to the point though, even if, in CL, words matter "more" than
other things, formatting still is an important matter. But formatting,
or structure, is clearly an issue of visually grasping what's going
on. That's an important support to (verbally) understanding code.

I hasten to add (that I believe) that throwing a bunch of non-text
characters all over the place to further enhance such support is
misguided.

> The structure is still important in both cases.

Exactly my point.

Holger

Tim Bradshaw

unread,
Feb 14, 2002, 10:48:56 AM2/14/02
to
* Dorai Sitaram wrote:

> I am inclined to agree, but just yesterday a coupla
> posts here were praising special tools over
> general tools. That also sounded somewhat agreeable
> with at the time, except that their argument put CL
> firmly on the side of the specializers, not
> generalizers as the above seems to be doing (unless
> Lisp is not being equated with CL).

If you are referring to the article I wrote where I said I didn't try
and write general libraries or tools, then that's not quite what I was
trying to say.

What I meant was that doing `library standard' or `language standard'
systems is, in my opinion, very hard indeed (and many of the so-called
`standard libraries' such as, for instance, the Win32 API are in my
opinion good examples of systems which are *failing* to be good enough
and thus require endless reinvention).

I'm all in favour of general tools (which should be library/language
standard), and I think that CL is a very good example of such a
general tool whose design is actually adequate in almost all areas
(that is meant to be very high praise: there aren't any bits of CL
which I find unusably badly designed, which is not something I've come
across very often).

*But*, since I think that design of general tools is so hard, or at
least it is hard for me, I tend to not try, but instead to design
special tools for the job at hand. That way I actually get the job
done.

So I wasn't making a value judgement, more trying to describe how I
work.

--tim


Marco Antoniotti

unread,
Feb 14, 2002, 11:26:34 AM2/14/02
to

Christophe Rhodes <cs...@cam.ac.uk> writes:

> Marco Antoniotti <mar...@cs.nyu.edu> writes:
>
> > Here is one of my favourite `primes' in conforming CL.
> >
> > (in-package "SETL-USER")
> >
> > (defun primes (max)
> > [n in (range 3 max 2)
> > / (not (exist m in (range 3 (min (1- n) (+ 2 (sqrt n))) 2)
> > / (= (mod n m) 0)))])
>
> I appreciate the point, but I thought that we decided that "conforming
> CL" programmes needed to include their macros and reader-macros to be
> properly conforming... :-)

Come on! Throw me a bone here! :) The IN-PACKAGE is quite a give away

Dorai Sitaram

unread,
Feb 14, 2002, 11:28:00 AM2/14/02
to
In article <ey3aduc...@cley.com>, Tim Bradshaw <t...@cley.com> wrote:
>* Dorai Sitaram wrote:
>
>> I am inclined to agree, but just yesterday a coupla
>> posts here were praising special tools over
>> general tools. That also sounded somewhat agreeable
>> with at the time, except that their argument put CL
>> firmly on the side of the specializers, not
>> generalizers as the above seems to be doing (unless
>> Lisp is not being equated with CL).
>
>If you are referring to the article I wrote where I said I didn't try
>and write general libraries or tools, then that's not quite what I was
>trying to say.
>...

>*But*, since I think that design of general tools is so hard, or at
>least it is hard for me, I tend to not try, but instead to design
>special tools for the job at hand. That way I actually get the job
>done.
>
>So I wasn't making a value judgement, more trying to describe how I
>work.

Actually, I was referring to Thomas [Burdick] and
Kent's articles rather than yours. If it was yours and
I was referring to it in a followup to you yourself,
let me assure you that I would find it weird to
third-person it so. :-)

--d

Pierre R. Mai

unread,
Feb 14, 2002, 10:38:03 AM2/14/02
to
Marco Antoniotti <mar...@cs.nyu.edu> writes:

> Ed L Cashin <eca...@uga.edu> writes:
>
> > Also, I remember thinking that lisp looked like "text vomit" compared
> > to languages whose structure lexically mirrors what's going on.
> > Here's an example in ruby:
> >
> > {
> > "foo" => "bar",
> > "baz" => "burfle",
> > }.each { |i|
> > puts i
> > }
>
> (map* #'print
> (make-hash-table* '(("foo" => "bar")
> ("baz" => "bar"))))

Or, another way:

(maphash (lambda (key value) (format t "~A => ~A~%" key value))
(equal-hash-table "foo" "bar" "baz" "bar"))

The point being that hash-tables (_unlike_ many other data-structures
in CL), lack both reader-syntax and simple creation functions. Thus
the disadvantage when compared to Ruby/Perl/...; but I consider that
accidental, since CL does have such support for things like lists,
vectors, arrays, etc.

Probably make-hash-table should take an initial-contents keyword arg,
just like make-array does, e.g.

(maphash (lambda (key value) (format t "~A => ~A~%" key value))
(make-hash-table :test #'equal
:initial-contents '(("foo" "bar") ("baz" "bar"))))

Regs, Pierre.

--
Pierre R. Mai <pm...@acm.org> http://www.pmsf.de/pmai/
The most likely way for the world to be destroyed, most experts agree,
is by accident. That's where we come in; we're computer professionals.
We cause accidents. -- Nathaniel Borenstein

Brian Campbell

unread,
Feb 14, 2002, 1:37:04 PM2/14/02
to
> Not with me. I have no problem with parentheses, except that I don't
> know all the rules to their use, and I don't want to learn the entire
> common-lisp language to find out; either. I may do so, but I WILL
> find a better way, if I can!

The rules are very simple. Everything in lisp is either an atom or a
list. Atoms are single values; numbers, variables, strings, or a couple
of assorted other things that you won't need to use that much. If you
want something more complex than one of those (like, applying a function
to some arguments), you need a list. Lists are delimited by parentheses,
and their first element is the function you are calling or the special
form you are using (I'll get to the difference between functions and
special forms later). So if you want to add 4 and 5, you use the +
function (yes, in lisp + is a function like any other, it's not some
special operator), you write:

(+ 4 5)
=> 9

It's as simple as that! Here are some more examples. Say I want to add 4
to the result of multiplying 5 by 2. Starting from the outside, I write:

(+ 4 ...)

This applies the function plus the the argument 4 and the result of the
multiplication (represented here as ...). Now how do you do the
multiplication? Exactly the same way you did the addition:

(+ 4 (* 5 2))
=> 14

All function application works exactly this way. The interpreter or
compiler executes code by evaluating it. Evaluation for an number or
string returns that number or string:

4
=> 4

"foo"
=> "foo"

Evaluation of a symbol which refers to a variable returns the value of
that variable:

;; x has been set or bound before to 5
x
=> 5

Evaluation of a list (which is a function application) evaluates every
element of the list (I'm simplifying a little bit here, and using the
semantics of Scheme, rather than Common Lisp, because it makes more
sense that way), and then applies the function which appears at the
beginning to the (evaluated) rest of the arguments (I will use < and >
to enclose the evalueated value of the elements of the list):

(+ 4 (* 5 2))
(<function:+> <number:4> ...)
(<function:*> <number:5> <number:2>) => 10
(<function:+> <number:4> <number:10>) => 14
=> 14

The difference between a function and a special form is that in a
special form, it doesn't go through and evaluate every element. Instead,
it looks at the first one, and based on that decides how to evaluate the
rest. For example, when you are using if, you don't want it to evaluate
both the true and false conditions. For example, if you're writing
something that controls a nuclear weapon launch (this example stolen
from SICP), you don't want the statement

(if (at-war? us)
(launch missile)
(keep-waiting))

to launch the missile every time the if is evaluated!

So you see, parentheses in lisp are actually much simpler than those in
other languages. In C, you need to learn about precedence rules, square
brackets, curly braces, and all kinds of other delimeters, and
parentheses are used for three different things (typecasting, function
calls, and grouping arithmetic statements), while in lisp they are only
used for function calls and special forms.

If you don't want to learn all of Common Lisp, I would recommend Scheme,
which is much conceptually simpler than Common Lisp, but works in the
same basic way. There are some good intros online; go to
<http://www.schemers.org/>. Especially good is Abelson and Sussman, and
Sussman's "Structure and Interpretation of Computer Programs" at
http://mitpress.mit.edu/sicp/full-text/book/book.html (the link is kind
of buried if you try to find it on schemers.org).

(apologies for presenting scheme and advocating scheme on
comp.lang.lisp, but I think that it's better to introduce someone who
doesn't understand all those parentheses to scheme, rather than common
lisp, where you don't evaluate every element of the list uniformly)

--
Brian Campbell
Real email: lambda (at) cs (dot) dartmouth (dot) edu

Daniel Barlow

unread,
Feb 14, 2002, 2:48:56 PM2/14/02
to
Brian Campbell <lambd...@yahoo.com> writes:

> The rules are very simple. Everything in lisp is either an atom or a
> list. Atoms are single values; numbers, variables, strings, or a couple
> of assorted other things that you won't need to use that much. If you

The first sentence is true.

As by definition an atom is anything that is not a cons, then insofar
as the second sentence is true, it's trivially true.

This gives us problems with the third sentence, as atoms thus include
things like packages, arrays, hash tables, and CLOS instances, which I
hope you will agree are generally _not_ "things that you won't need to
use that much"...

If in the second sentence you had instead said "Everything in lisp
_code_ is either an atom or a list", you could have made a rather more
defensible (if still not entirely justified) claim on the third
sentence, because code doesn't often contain literal hash tables.

OK, maybe I'm nit-picking, but confusing lisp code syntax with sexpr
syntax, and confusing the outward sexpr-based representation with the
actual objects are both common new-user mistakes, and I think it helps
to be exact with terminology when explaining.


-dan

--

http://ww.telent.net/cliki/ - Link farm for free CL-on-Unix resources

Wade Humeniuk

unread,
Feb 14, 2002, 7:42:07 PM2/14/02
to
>
> Probably make-hash-table should take an initial-contents keyword arg,
> just like make-array does, e.g.
>
> (maphash (lambda (key value) (format t "~A => ~A~%" key value))
> (make-hash-table :test #'equal
> :initial-contents '(("foo" "bar") ("baz"
"bar"))))

I think hash-tables are meant to store larger amounts of unordered data and
I cannot see using the :initial-contents to populate a 1000+ key/value pairs
(or for that matter 100,000 values). I would rebel at doing the typing.
For me, storing 2 key/value or even 100 values in a hash table is just not
worth it.

Wade


Brian Campbell

unread,
Feb 14, 2002, 7:31:37 PM2/14/02
to
In article <873d033...@noetbook.telent.net>,
Daniel Barlow <d...@telent.net> wrote:

> Brian Campbell <lambd...@yahoo.com> writes:
>
> > The rules are very simple. Everything in lisp is either an atom or a
> > list. Atoms are single values; numbers, variables, strings, or a couple
> > of assorted other things that you won't need to use that much. If you
>
> The first sentence is true.
>
> As by definition an atom is anything that is not a cons, then insofar
> as the second sentence is true, it's trivially true.

I need to define my terms. As the person I was explaing to doesn't
understand what all of the parentheses are for, I needed to make sure he
understood what atoms and lists were.

>
> This gives us problems with the third sentence, as atoms thus include
> things like packages, arrays, hash tables, and CLOS instances, which I
> hope you will agree are generally _not_ "things that you won't need to
> use that much"...

Do you see them literally in the code? It was the syntax, and how that
translated to the semantics, that I was explaining, not the actual set
of values that lisp can represent as data. Perhaps I should have been
more specific; rather than "everything in lisp", I should have said
"every expression in lisp". Besides numbers, symbols (which I called
variables here to draw the parallel with other programming languages),
strings, and lists, there's not much else that you see in the code.
There are vectors, and quoted symbols and lists, and a few other kinds
of atoms that can appear in the syntax, but as you said, you don't often
see literal hash tables. Also, since I was recommending he look into
Scheme if he didn't want to learn all of Common Lisp, I didn't want to
confuse him with things that were different between them; should I have
mentioned t and nil, or #t and #f? Should I have mentioned arrays, or
just vectors? As the atoms that I mentioned are common between both
scheme and common lisp, and make up 90% or more of the syntax that you
see, I decided to only include them.

>
> If in the second sentence you had instead said "Everything in lisp
> _code_ is either an atom or a list", you could have made a rather more
> defensible (if still not entirely justified) claim on the third
> sentence, because code doesn't often contain literal hash tables.
>
> OK, maybe I'm nit-picking, but confusing lisp code syntax with sexpr
> syntax, and confusing the outward sexpr-based representation with the
> actual objects are both common new-user mistakes, and I think it helps
> to be exact with terminology when explaining.

Yes, I was sloppy. I think that coming from the perspective of the
person I was writing for, it would still clear matters up more than it
would confuse him. Anyhow, both lisp syntax and sexpr syntax are the
syntax that can be parsed by the read function. There are additional
constraints on the lisp code, it is true, but lisp code is a use of
sexpressions for representing a program, and confusing the syntax with
the actual objects is a mistake, but that is why, when demonstrating
evaluation, I made sure to use a notation that distinguished objects
from their representation.

>
>
> -dan

Pierre R. Mai

unread,
Feb 14, 2002, 8:41:51 PM2/14/02
to
"Wade Humeniuk" <hume...@cadvision.com> writes:

The value for the initial-contents argument can be arrived at in any
way wanted. It is not limited to being a literal. Furthermore, in is
quite conceivable that the hash-table in question is going to grow to
many values (thereby validating the use of a hash-table), yet is
seeded with a smallish amount of initial-contents, where the typing
isn't problematic. And then there are many cases where you want to
interactively test a function that is specified to work on
hash-tables, where a few entries in the table suffices.

It is for those reasons that I think an initial-contents argument to
make-hash-table makes as much sense as it does for make-array. Of
course this is not something I'm going to fret about, but I've more
than once written a "make-hash-table-from-kv-pairs"-type function, and
wouldn't consider such an addition without some good will.

Of course your implicit point that alists are often a better choice
(which accidentally also have good support for literal input) for
smallish lookup tables is duly taken.

Gareth McCaughan

unread,
Feb 14, 2002, 9:04:51 PM2/14/02
to
Tim Bradshaw wrote:

> * Erik Naggum wrote:
>
> > It appears warranted by the various reactions people have posted and told
> > of elsewhere to conclude that Common Lisp is a language that is better
> > suited for those who are more verbal than visual in how they remember and
> > learn. Those who are more visual, tend to be thrown off by the lack of
> > visual clues and the preponderance of words they need to recognize in
> > order to "see" the structure. The verbal, who recognize words the way
> > the visual see pictures and figures, have no such problem.
>
> I think this is an interesting point. However I'm not sure it's right
> or at least not uniquely right. I think I'm a terribly visual person
> (although I also can read).

[etc]

Whereas I'm a visually terrible person :-), so according to Erik's
criterion it makes sense that I like Lisp; but I also find visual
tricks like syntax-colouring extremely helpful, in Lisp and also in
other languages. (Maybe I find those tricks helpful *because* I'm
not very visual; perhaps if my visual subsystem worked better it
would do those jobs unaided.)

And, despite being very "verbal", I do find that sometimes the
"verbosity" of Lisp bothers me. I don't think I've yet found an
instance where it's (1) genuine verbosity and (2) not easily
fixed with a bit of macrology or read-table manipulation; but
it can still cause discomfort. It's possible that the discomfort
is a useful signal that macrology might be in order.

*

Example: Earlier in the thread, someone posted a comparison between
two code snippets, one in Ruby and one in Lisp. Both had the form:
build a hash table containing known keys and values, then iterate
over it. The Ruby code was shorter and allegedly clearer. (I find
the ambiguous use of curly brackets in Ruby disagreeable, but never
mind that.) And it's true: the CL code is verbose and hard to read.

But, if you're doing a lot of that sort of thing then it's the work
of a minute (well, OK, five minutes) to write two simple macros so
you can write

(dohash (key value)
(hash ("foo" "bar") ("baz" "quux"))
(format t "~&~A -> ~A.~%" key value))

which seems to me just as clear (to someone with a little Lisp
experience; no one denies that Lisp takes getting used to) as

{"foo" => "bar", "baz" => "quux"}.each {
|key, value|
print key, " -> ", value, "\n"
}

or, for that matter,

for key,value in {"foo": "bar", "baz": "quux"}.items():
print key, "->", value, "\n"

except that FORMAT looks too much like line noise to some readers.
(Compression implies near-randomness.) Again, if you do a lot of
writing sequences of things to *STANDARD-OUTPUT* then it's the
work of another minute or two to write a function so you can say

(dohash (key value)
(hash ("foo" "bar") ("baz" "quux"))
(output key " -> " value #\Newline))

Ruby and Python and all sorts of other languages have advantages
over CL, but brevity and clarity aren't among them unless either
your programs are so short that brevity and clarity don't matter
anyway, or you're deliberately choosing to write CL in a way that
doesn't provide the sort of brevity and clarity you want.

*

(defvar *preferred-hash-test* 'equal)

(defmacro hash (&rest pairs)
(let ((result (gensym)))
`(let ((,result (make-hash-table :test ',*preferred-hash-test*)))
,@(loop for (key value) in pairs collect
`(setf (gethash ,key ,result) ,value))
,result)))

(defmacro dohash ((k v) hform &body body)
`(loop for ,k being each hash-key of ,hform using (hash-value ,v) do
. ,body))

(defun output (&rest values)
(loop for value in values do (princ value)))

--
Gareth McCaughan Gareth.M...@pobox.com
.sig under construc

zaphod

unread,
Feb 14, 2002, 11:50:46 PM2/14/02
to
Erik Naggum <er...@naggum.net> wrote in message news:<32226813...@naggum.net>...

> * Sla...@ureach.com (zaphod)
> | Not with me. I have no problem with parentheses, except that I don't
> | know all the rules to their use, and I don't want to learn the entire
> | common-lisp language to find out; either. I may do so, but I WILL
> | find a better way, if I can!
>
> Quite amazing. It is obviously superfluous to answer any of your
> questions with technical answers. This is good to know.

Yapp; reckon I'm an illiterat know knothing cluck; or maby you don't
know enough about me and my situation to know much at all about me or
my situation (look Ma; recursion). Sorry about my inadequacies. If I
put my attention purely on learning Common Lisp, I might surprise
someone with my astuteness as a student, then again; I might not. I
just wanted to let you know, that it's not neccasarilly an IRRATIONAL
dislike of parens. There just might be some rationality behind it.
In my case; I gave it a try, and discovered it wasn't as easy as I've
been lead to beleive, but I'm so dang low-brow, I hack trial and
error, when it seems right. I should have prefaced all with.
Me=newbie know-nothing, tho.
>
> ///

Erik Naggum

unread,
Feb 15, 2002, 2:37:45 AM2/15/02
to
* "Wade Humeniuk" <hume...@cadvision.com>

| I think hash-tables are meant to store larger amounts of unordered data and
| I cannot see using the :initial-contents to populate a 1000+ key/value pairs
| (or for that matter 100,000 values). I would rebel at doing the typing.
| For me, storing 2 key/value or even 100 values in a hash table is just not
| worth it.

When a hash-table is all you have, you tend to optimize it heavily. The
same goes for regexps. Both hash-tables and regular expressions are very
powerful and general tools, but they turn into monstrosities when all the
more specialized tools are effectively removed from the language they use.

Common Lisp has the disadvantage compared to the one-trick languages that
the different access functions for various kinds of mappings between key
and value are precisely that -- different. When there is only one way to
do it, being offered several ways is just confusing, and so people who
think "hash-table" when they should have thought "key-value mapping" will
miss simple and elegant things like property lists or association lists.

I mean, if { "foo" => "bar", "baz" => "zot" } is so great, why is not
(("foo" . "bar") ("baz" . "zot"))? Is it _only_ the sugar-coated syntax
that is so visually appealing to some? If so, a Common Lisp programmer
will write a small parser function that is called via the reader-macro
support to read this list. Why is this not more used? I belive it is
because most people who pine for other syntaxes have no clue how to go
about specifying them or writing parsers for them, and because once you
have grown that clue, you do not need it or, more importantly, want it.

But what the heck. Proof of concept follows.

(let ((mapping-types ()))
(defun readtable-mapping-type (readtable)
(check-type readtable readtable)
(or (cdr (assoc readtable mapping-types)) :alist))

(defun (setf readtable-mapping-type) (mode readtable)
(check-type readtable readtable)
(check-type mode (member :alist :plist :eq :eql :equal :equalp))
(let ((existing (assoc readtable mapping-types)))
(if existing
(setf (cdr existing) mode)
(push (cons readtable mode) mapping-types))))

(defun mapping-reader (stream char)
(declare (stream stream) (ignore char))
(loop
with mapping-type = (readtable-mapping-type *readtable*)
with key and value
with hashtable = (case mapping-type
(:eq (make-hash-table :test #'eq))
(:eql (make-hash-table :test #'eql))
(:equal (make-hash-table :test #'equal))
(:equalp (make-hash-table :test #'equalp)))
do
(when (eql #\} (peek-char t stream t nil t))
(read-char stream t nil t)
(loop-finish))
(setq key (read stream t nil t))
(if (eql #\= (peek-char t stream t nil t))
(read-char stream t nil t)
(error 'parse-error :stream stream))
(unless (eql #\> (read-char stream t nil t))
(error 'parse-error :stream stream))
(setq value (read stream t nil t))
(case (peek-char t stream t nil t)
(#\, (read-char stream t nil t))
(#\} t)
(t (error 'parse-error :stream stream)))
if (eq mapping-type :alist) collect (cons key value) into list else
if (eq mapping-type :plist) collect key into list
and collect value into list else
do (setf (gethash key hashtable) value)
finally (case mapping-type
((:alist :plist) (return (list 'quote list)))
(t (return hashtable))))))

Now, suppose the above is available in the Common Lisp world. A file
that uses this syntax could go like this:

(eval-when (:execute :compile-toplevel)
(setq *readtable* (copy-readtable))
(set-macro-character #\{ #'mapping-reader)
(set-syntax-from-char #\} #\)))

(eval-when (:execute :compile-toplevel)
(setf (readtable-mapping-type *readtable*) :alist))

(defparameter *roman-alist*
{ "I" => 1,
"V" => 5,
"X" => 10,
"L" => 50,
"C" => 100,
"D" => 500,
"M" => 1000 })

(eval-when (:execute :compile-toplevel)
(setf (readtable-mapping-type *readtable*) :plist))

(defparameter *roman-plist*
{ "I" => 1,
"V" => 5,
"X" => 10,
"L" => 50,
"C" => 100,
"D" => 500,
"M" => 1000 })

(eval-when (:execute :compile-toplevel)
(setf (readtable-mapping-type *readtable*) :equal))

(defparameter *roman-hash*
{ "I" => 1,
"V" => 5,
"X" => 10,
"L" => 50,
"C" => 100,
"D" => 500,
"M" => 1000 })

I chose this design because I figured that it would be annoying to change
the data if the access functions would need to change and that it would
be more convenient to specify this via a readtable-local setting than add
a lot more syntax for it. If you have support for the in-syntaax form
and named readtables, creating a named readtable to invoke this syntax
would obviously be the best solution.

Now, if you want other kinds of things to go on within { }, it is not a
lot of trouble to build a parser by hand, provided you are not a moron
and create syntaxes the like of C++ or some other horrible monstrosity.

Creating a writer for alists, plists, and hashtables that write data in
this syntax is left as an exercise for the reader.

Copyright notice: Copyright © 2002 Erik Naggum. The code may be used to
create commercial products without charge or other license provided that
the author is credited in each source file that uses it or the syntax it
allows. Creation of derivative works is permitted under two conditions:
No rewrites to use if* or not to use loop are allowed, and the author
must be notified by e-mail at <er...@naggum.net>. Search engines are
permitted to index and retrieve this article in perpetuity and present to
users in either normal text or html-ized form, but no other form of re-
publication is permitted. Inclusion of this material in some "cookbook"
is expressly not permitted.

Erik Naggum

unread,
Feb 15, 2002, 2:45:52 AM2/15/02
to
* Brian Campbell <lambd...@yahoo.com>

| The rules are very simple.

Yeah. They go like this:

Rule #1: Don't feed the trolls.

Rule #2: Don't give the trolls the benefit of the doubt.

Rule #3: Don't let the trolls feed on you.

Rule #4: Sufficiently advanced ignorance is indistinguishable from trolls.

Rule #5: Get paid to write books for dummies and permanent newbies.

Erik Naggum

unread,
Feb 15, 2002, 3:05:28 AM2/15/02
to
* Sla...@ureach.com (zaphod)

| I just wanted to let you know, that it's not neccasarilly an IRRATIONAL
| dislike of parens.

You failed.

Kenny Tilton

unread,
Feb 15, 2002, 1:57:57 PM2/15/02
to

zaphod wrote:

> In my case; I gave [parentheses] a try, and discovered it wasn't as easy as I've


> been lead to beleive, but I'm so dang low-brow, I hack trial and
> error, when it seems right.

just curious: how long did you try? Did you have a nice
parentheses-matching editor to help?

thx

--

kenny tilton
clinisys, inc
---------------------------------------------------------------
"We have a pond and a pool. The pond would be good for you."
- Ty to Carl, Caddy Shack

Erann Gat

unread,
Feb 15, 2002, 2:56:24 PM2/15/02
to
In article <32227474...@naggum.net>, Erik Naggum <er...@naggum.net> wrote:

> Common Lisp has the disadvantage compared to the one-trick languages that
> the different access functions for various kinds of mappings between key
> and value are precisely that -- different.

...

> I mean, if { "foo" => "bar", "baz" => "zot" } is so great, why is not
> (("foo" . "bar") ("baz" . "zot"))? Is it _only_ the sugar-coated syntax
> that is so visually appealing to some?

I can't speak for anyone else of course, but what bothers me about alists
is not the syntax but exactly what you said in the first parahraph I
quoted: that the access functions for alists and other kinds of
associative maps are different. You say it's a disadvantage, and I
agree. It is a disadvantage because it tends to steer programmers towards
premature commitment to a particular implementation, and also towards
breaking abstractions (like pushing and popping things onto alists).

I would much prefer to simply specify that I want an associative map
without having to commit myself to a particular underlying
implementation. (Actually, associative maps are an important enough
abstraction that I think it's not unreasonable to think about taking the
decision away from the programmer and having the compiler or the runtime
system choose the implementation automatically.)

> But what the heck. Proof of concept follows.

[snip]

This is the right idea, but you need to add something like the ref macro
to complete the picture. By the time you've done that IMO you've done
enough work on a common enough problem that it's worth talking about
standardizing the interface and building it into implementations so
compilers can be smarter about optimizing it.

E.

Nils Goesche

unread,
Feb 15, 2002, 5:04:58 PM2/15/02
to
In article <gat-150202...@eglaptop.jpl.nasa.gov>, Erann Gat wrote:
> I can't speak for anyone else of course, but what bothers me about alists
> is not the syntax but exactly what you said in the first parahraph I
> quoted: that the access functions for alists and other kinds of
> associative maps are different. You say it's a disadvantage, and I
> agree. It is a disadvantage because it tends to steer programmers towards
> premature commitment to a particular implementation, and also towards
> breaking abstractions (like pushing and popping things onto alists).
>
> I would much prefer to simply specify that I want an associative map
> without having to commit myself to a particular underlying
> implementation. (Actually, associative maps are an important enough
> abstraction that I think it's not unreasonable to think about taking the
> decision away from the programmer and having the compiler or the runtime
> system choose the implementation automatically.)

But when there is no difference whatsoever in usage interface of
assoc lists or hash tables, why would we want to use assoc lists in
the first place? I always thought that the main advantage of assoc
lists is that you have all those nice list functions for operating
on them in addition to the boring gethash, and can share data in
sublists if you operate functionally on them.

Regards,
--
Nils Goesche
"Don't ask for whom the <CTRL-G> tolls."

PGP key ID 0x42B32FC9

Raymond Toy

unread,
Feb 15, 2002, 6:16:06 PM2/15/02
to
>>>>> "Erik" == Erik Naggum <er...@naggum.net> writes:

Erik> Copyright notice: Copyright © 2002 Erik Naggum. The code may be used to
Erik> create commercial products without charge or other license provided that
Erik> the author is credited in each source file that uses it or the syntax it
Erik> allows. Creation of derivative works is permitted under two conditions:
Erik> No rewrites to use if* or not to use loop are allowed, and the author

I don't quite follow the wording here. I think you're saying that any
of the following is forbidden:

1. rewrite this to use if*
2. rewrite this not to use loop

Right?

Ray

Erann Gat

unread,
Feb 15, 2002, 9:48:16 PM2/15/02
to
In article <a4k0ma$srct$1...@ID-125440.news.dfncis.de>, Nils Goesche
<car...@cartan.de> wrote:

I'm not 100% clear on what you're trying to say here, so I'm going to give
a couple of answers and hope a few of them are on-point.

1. Alists can be more efficient than hash tables, particularly for small
data sets.

2. Having "all those nice list functions" is only an advantage insofar as
they let you do something useful. Being able to operate on an alist as a
list is not in and of itself a feature, and can lead to problems if you're
not careful. I can't offhand think of anything useful you can do with an
alist that is fundamentally more difficult with a hashmap.

(Hashmaps, by the way, are one of Common Lisp's best kept secrets, one of
those "other" data types that doesn't get much attention among all the
hoopla over lists, atoms, and symbols. Hashmaps are tremendously useful,
and for a long time Common Lisp was the only language that had them.
Today C is about the only language in common use that doesn't have them.)

3. I don't understand the phrase "in addition to the boring gethash."
Gethash works only on hash tables, not on alists. To do the equivalent of
"gethash" on an alist you have to do (cdr (assoc ... more or less. I
also don't see why gethash is particularly more boring than any other
function.

4. Values stored in hash tables can share structure just as values stored
in alists can.

Was that anywhere near the mark?

E.

Nils Goesche

unread,
Feb 15, 2002, 10:42:00 PM2/15/02
to
In article <gat-150202...@192.168.1.50>, Erann Gat wrote:
> In article <a4k0ma$srct$1...@ID-125440.news.dfncis.de>, Nils Goesche
><car...@cartan.de> wrote:
>
>> In article <gat-150202...@eglaptop.jpl.nasa.gov>, Erann Gat wrote:
>> > I can't speak for anyone else of course, but what bothers me about alists
>> > is not the syntax but exactly what you said in the first parahraph I
>> > quoted: that the access functions for alists and other kinds of
>> > associative maps are different.

[snip]

>> But when there is no difference whatsoever in usage interface of
>> assoc lists or hash tables, why would we want to use assoc lists in
>> the first place?

[snip]

> I'm not 100% clear on what you're trying to say here, so I'm going to give
> a couple of answers and hope a few of them are on-point.

[snip]

> Was that anywhere near the mark?

Yes, absolutely, thank you. I misunderstood you. I thought you were
saying that you didn't like having to use `gethash' in one case and
cdr and assoc in the other case etc. because you wanted to be able
to change your program quickly to use one instead of the other. I
thought that in order to do that you would have to restrict yourself
to use only the common subset of interface both structures have. As
I /still/ think that alists are a more luxurious thing than hash
tables, for the programmer at least, I wouldn't want to restrict
myself to that common subset. But then, maybe I am still
misunderstanding you :-)

Regards,
--
Nils Goesche
Ask not for whom the <CONTROL-G> tolls.

PGP key ID 0xC66D6E6F

Erann Gat

unread,
Feb 15, 2002, 11:18:34 PM2/15/02
to
In article <a4kke8$gng$04$1...@news.t-online.com>, Nils Goesche
<car...@t-online.de> wrote:

> In article <gat-150202...@192.168.1.50>, Erann Gat wrote:
> > In article <a4k0ma$srct$1...@ID-125440.news.dfncis.de>, Nils Goesche
> ><car...@cartan.de> wrote:
> >
> >> In article <gat-150202...@eglaptop.jpl.nasa.gov>, Erann Gat wrote:
> >> > I can't speak for anyone else of course, but what bothers me about alists
> >> > is not the syntax but exactly what you said in the first parahraph I
> >> > quoted: that the access functions for alists and other kinds of
> >> > associative maps are different.
>
> [snip]
>
> >> But when there is no difference whatsoever in usage interface of
> >> assoc lists or hash tables, why would we want to use assoc lists in
> >> the first place?
>
> [snip]
>
> > I'm not 100% clear on what you're trying to say here, so I'm going to give
> > a couple of answers and hope a few of them are on-point.
>
> [snip]
>
> > Was that anywhere near the mark?
>
> Yes, absolutely, thank you. I misunderstood you. I thought you were
> saying that you didn't like having to use `gethash' in one case and
> cdr and assoc in the other case etc. because you wanted to be able
> to change your program quickly to use one instead of the other.

Yes, that is in fact what I was saying.

> I thought that in order to do that you would have to restrict yourself
> to use only the common subset of interface both structures have.

No, that is not what I was saying. Alists and hash tables have no common
subset in their interface. That's the problem. Erik's code solves half
of the problem. The 'ref' macro (discussed in another thread here a few
weeks ago) solves the other half. I'd like to see something like that
standardized.

> As
> I /still/ think that alists are a more luxurious thing than hash
> tables, for the programmer at least, I wouldn't want to restrict
> myself to that common subset.

Since the common subset is empty that would be a severe restriction. But
I'm curious: what is it about alists that you find "luxurious"?

E.

Erik Naggum

unread,
Feb 16, 2002, 1:06:26 AM2/16/02
to
* g...@jpl.nasa.gov (Erann Gat)

| 2. Having "all those nice list functions" is only an advantage insofar as
| they let you do something useful. Being able to operate on an alist as a
| list is not in and of itself a feature, and can lead to problems if you're
| not careful. I can't offhand think of anything useful you can do with an
| alist that is fundamentally more difficult with a hashmap.

Suppose it is a special variable. (let ((*alist* *alist*)) ...) allows
you to push key-value pairs on the list and have them work in a manner
very similar to scoping. You may temporarily push a single key-value
element to shadow another and then delete it when you are done, with a
simple (delete <key> <alist> :key #'car).

Alists are also just as efficient from key to value as from value to key.

Kent M Pitman

unread,
Feb 16, 2002, 1:29:06 AM2/16/02
to
Erik Naggum <er...@naggum.net> writes:

> * g...@jpl.nasa.gov (Erann Gat)
> | 2. Having "all those nice list functions" is only an advantage insofar as
> | they let you do something useful. Being able to operate on an alist as a
> | list is not in and of itself a feature, and can lead to problems if you're
> | not careful. I can't offhand think of anything useful you can do with an
> | alist that is fundamentally more difficult with a hashmap.

(I'm reading out of context and assuming hashmap == hash table.)

You never get something for nothing. Everything is a trade-off.

Alists and plists Maintain an ordering. MAPHASH often goes in a very
unintuitive ordering. You may not _want_ an ordering; that's a different
issue. But certainly there is value to be had from those abstractions.
Order can be important both to presentation and to algorithm.

Also, alists and plists don't suffer from rehash problems upon garbage
collection.

And alists and plists are often short and just plain faster than hash tables,
since computing a key for the hash table involves a certain up front cost
that may not really matter. This depends a little on the hash table
implementation, of course. But I think most implementations of hash tables
have a certain degree of this.

> Suppose it is a special variable. (let ((*alist* *alist*)) ...) allows
> you to push key-value pairs on the list and have them work in a manner
> very similar to scoping. You may temporarily push a single key-value
> element to shadow another and then delete it when you are done, with a
> simple (delete <key> <alist> :key #'car).

Does anyone really do this? I have never gotten satisfactory results from
doing DELETE on a list (or alist) that was shared. As soon as I know someone
else is using it I have to worry I'm not maintaining it well for them.
Consider that there are *seriously* obscure "DELETE bugs" waiting if you
do

(setq l1 (list 4 3 2 1))
(setq l2 (cons 5 l1))
(setq l3 (delete 4 l2))
(setq l4 (delete 2 l2))

l4 => (5 3 1)
l3 => (5 3 1)
l2 => (5 3 1)
l1 => (4 3 1)

> Alists are also just as efficient from key to value as from value to key.

Alists don't suffer any more than other list formats from the problem I just
mentioned. I agree they are "as good as" plists, etc.

I prefer plists just because (a) they have better accessors in the language
and (b) they don't get caught up in that "dot problem" of ((a . b)...) vs
((a b)...).

I describe the basic trade-off between alists and plists this way:

alists are private
plists are restartable

That is, ...

If you do (assoc 'x '((a . b) (x . y) (z . 3) (x . m))) you get back
(x . y). If you wanted the (x . m), there is no easy way to "restart"
the search from the prior point; you have to use MEMBER (which breaks
the alist abstraction) to get restartability). _However_, what you do
get with alists is data privacy. If I want to hand you an object you
can SETF in order to update the table, I don't have to expose entries
to you that are irrelevant; if it were a plist, the only location I
could hand you is the tail of the list, which points to other data you
shouldn't have. That is, plists are not very private.

But as to restartability, if you do (get-properties '(a b x y z 3 x m)
'(x)) you get back X, Y, (X Y Z 3 X M). The third value can be used
to continue searching (i.e., to restart); contrast with an alist
lookup, where you get back the entry, which is not something you can
restart.

Nils Goesche

unread,
Feb 16, 2002, 3:41:03 AM2/16/02
to

Hehe :-) I meant the conceptual interfaces. Even if you have some
syntax and functional interface for addressing both of them in the
same way, you would be restricted to /using/ both alists and hashtables
in the same way. Otherwise you would lose the ability to simply
exchange both data structures in your code.

> But I'm curious: what is it about alists that you find "luxurious"?

Erik Naggum and Kent Pitman described that. After I had posted
the article I was angry that I had forgotten to add ``There is no
such thing as a free lunch.'' I am happy to see that Kent Pitman
apparently had the very same association (no pun intended).

Pierre R. Mai

unread,
Feb 16, 2002, 8:38:09 AM2/16/02
to
g...@jpl.nasa.gov (Erann Gat) writes:

> 2. Having "all those nice list functions" is only an advantage insofar as
> they let you do something useful. Being able to operate on an alist as a
> list is not in and of itself a feature, and can lead to problems if you're
> not careful. I can't offhand think of anything useful you can do with an
> alist that is fundamentally more difficult with a hashmap.

Cheap cloning. One of the nicest things with alists is that under
certain circumstances, cloning them is as cheap as an assignment,
since they can just share tails, if you only modify the non-shared
structure part. While this sounds somewhat specialized, it often
comes up in the guise of alists as environment objects, where bindings
themselves are only ever removed when a complete environment is
destroyed (hence no need to modify structure), and assignment to the
bindings values is intended to propagate up/down the chain.

Erann Gat

unread,
Feb 16, 2002, 2:31:52 PM2/16/02
to
In article <sfwadua...@shell01.TheWorld.com>, Kent M Pitman
<pit...@world.std.com> wrote:

> (I'm reading out of context and assuming hashmap == hash table.)

Right. I've been doing too much C++ hacking lately. :-(

> You never get something for nothing. Everything is a trade-off.

No argument. The question is when (and how) those tradeoffs ought to be
made. One of the great things about Lisp (as has oft been pointed out by
you, Erik, and others) is that it allows a programmer to defer a lot of
decisions that other languages demand you make up front. If I write a
function in Java I have to decide up front how many arguments that
function will take, what the types of those arguments are, and what the
return type of the function will be. In Lisp I don't have to commit to
any of those things. I don't even have to commit to the *number* of
arguments, or even the name of the function! Opinions differ over whether
in the grand and glorious scheme of things this is a good thing, but in
the context of this newsgroup I'm going to take it as axiomatic that it
is.

What I'm saying is that when it comes to associative maps -- an extremely
important abstraction (arguably the most important in all of computer
science, but that's another discussion) -- this philosophy of deferring
decisions breaks down, at least within the bounds of the current
standard. I can't say "I want an associative map, and I want to defer the
decision of whether the underlying implementation will be an alist, a
plist, a hash-table, a binary-tree, a trie, or something else." The
standard strongly influences programmers to choose an implementation up
front, and Lisp culture tends to influence them away from hash-tables --
in Graham's and Norvig's books they are barely a blip on the radar, less
then a dozen pages out of nearly two thousand -- and towards alists and
plists. As a result, a lot of code gets written that is O(N) when it
could easily be O(log(N)) or even O(1). It works fine on small problems,
but it doesn't scale well, and it's a lot of work to go back and fix it.

> Alists and plists Maintain an ordering. MAPHASH often goes in a very
> unintuitive ordering. You may not _want_ an ordering; that's a different
> issue. But certainly there is value to be had from those abstractions.
> Order can be important both to presentation and to algorithm.

IMO this is conflating two separate issues. You have a collection of
things that you want to access in two different ways, by order, and by an
unordered index. You should maintain those two organizations separately,
i.e. you should be maintaining both a hash-table index and an ordered
container -- probably a list but possibly something else, like perhaps a
balanced tree if you want sorted order rather than by-insertion order.

> Also, alists and plists don't suffer from rehash problems upon garbage
> collection.

Now this is something I'm not familiar with. Could you elaborate?

> And alists and plists are often short and just plain faster than hash tables,
> since computing a key for the hash table involves a certain up front cost
> that may not really matter. This depends a little on the hash table
> implementation, of course. But I think most implementations of hash tables
> have a certain degree of this.

Yes, which is exactly the reason why just using hash tables and forgetting
about alists and plists is not the best answer.

E.

Erann Gat

unread,
Feb 16, 2002, 2:40:36 PM2/16/02
to
In article <32228283...@naggum.net>, Erik Naggum <er...@naggum.net> wrote:

> * g...@jpl.nasa.gov (Erann Gat)
> | 2. Having "all those nice list functions" is only an advantage insofar as
> | they let you do something useful. Being able to operate on an alist as a
> | list is not in and of itself a feature, and can lead to problems if you're
> | not careful. I can't offhand think of anything useful you can do with an
> | alist that is fundamentally more difficult with a hashmap.
>
> Suppose it is a special variable. (let ((*alist* *alist*)) ...) allows
> you to push key-value pairs on the list and have them work in a manner
> very similar to scoping. You may temporarily push a single key-value
> element to shadow another and then delete it when you are done, with a
> simple (delete <key> <alist> :key #'car).

Two comments.

First, the special variable is a red herring. What you say is equally
true whether or not *alist* is special.

Second, you can do exactly the same thing with a list of hash tables. In
fact, an alist is just a special case of this. You can think of a cons
cell as a brain-damaged hash table with a capacity of one entry and the
identity as the hash function.

> Alists are also just as efficient from key to value as from value to key.

If you really need a bidirectional mapping you can get one easily with a
pair of hash tables. And the runtime efficiency will be O(1) instead of
O(N).

E.

Erik Naggum

unread,
Feb 16, 2002, 3:35:15 PM2/16/02
to
* Erann Gat

| What I'm saying is that when it comes to associative maps -- an extremely
| important abstraction (arguably the most important in all of computer
| science, but that's another discussion) -- this philosophy of deferring
| decisions breaks down, at least within the bounds of the current standard.

Not so. If you are at all uncertain about how to deal with these things,
you either write macros or functions to hide the implementation technique
you (need to) use, and those macros would be named after the particular
association mapping needed, not afte the functionality alone.

| I can't say "I want an associative map, and I want to defer the decision
| of whether the underlying implementation will be an alist, a plist, a
| hash-table, a binary-tree, a trie, or something else."

Of course you can. Why have you turned into such a mindless troll?
Lest you have forgotten because of your C++ exposure of late, over here
in Common Lisp land, we shape the language to suit our needs, we do not
only used the lowest-level built-in functionality without modification or
reflection upon our needs.

> Also, alists and plists don't suffer from rehash problems upon garbage
> collection.

| Now this is something I'm not familiar with. Could you elaborate?

Is it not obvious? If an eq or eql hashtable hashes on the machine
address of the object, which is a pretty obvious thing to do, those
machine addresses will change if garbage collection moves live objects,
such as many GC algorithms do. Therefore, such a hashtable will need to
survive those object movements, somehow. This may not be a trivial task.
For instance, symbols, which are very useful in eq hashtables, have their
own hashing code as part of the symbol structure in Allegro CL to avoid
this high cost. Something similar to this can obviously not be done for
a lot of other useful hashing keys.

Message has been deleted

Thomas F. Burdick

unread,
Feb 16, 2002, 4:22:22 PM2/16/02
to
g...@jpl.nasa.gov (Erann Gat) writes:

> What I'm saying is that when it comes to associative maps -- an extremely
> important abstraction (arguably the most important in all of computer
> science, but that's another discussion) -- this philosophy of deferring
> decisions breaks down, at least within the bounds of the current
> standard. I can't say "I want an associative map, and I want to defer the
> decision of whether the underlying implementation will be an alist, a
> plist, a hash-table, a binary-tree, a trie, or something else."

Weren't you just posting a second ago about how much you like the REF
generic function? I'm certainly not the first person to go "I don't
even want to think about what kind of associating data structure I
want here -- I'll just say how I want to dereference it, and deal with
the how later -- (defgeneric ref ...". The standard gives you all you
need to write your application-specific abstractions to delay decisions.

The only reason to worry about standardizing something as trivial as
REF is in case everyone started having slightly different versions all
over the place. That would make it annoying to share code. Or, to
enable cute optimizations. It's certainly not needed to give
programmers the tool. And while it's a supported extension on the
Lisp system I'm working on, I'm dubious as to whether it needs any
sort of spec outside of the (hypothetical) Ciel-80 users' manual.

> The standard strongly influences programmers to choose an
> implementation up front, and Lisp culture tends to influence them
> away from hash-tables -- in Graham's and Norvig's books they are
> barely a blip on the radar, less then a dozen pages out of nearly
> two thousand -- and towards alists and plists.

Of course. Using hash tables sucks for debugging. It's easy to read
and maipulate a- and p-lists. You get shared tails cheaply. And you
get a record of how they got to where they are, because they're
ordered. Even when I know I'm going to end using a hash table, I
start by using an alist.

> As a result, a lot of code gets written that is O(N) when it could
> easily be O(log(N)) or even O(1). It works fine on small problems,
> but it doesn't scale well, and it's a lot of work to go back and fix
> it.

This shouldn't be true for well-written code. Just rewrite your
access functions. And remember, O(1) is a complexity signature,
algorithmically, it behaves as (1 + c1). And O(N) really means
((c2 * N) + c3). I'm certain you know this, but if c3 and c4 are
sufficiently small comapared to c1, the O(N) algorithm can be better.
Hashing time, the effects of GC, time spent rebalancing trees
... sometimes it's worth it, sometimes not.

--
/|_ .-----------------------.
,' .\ / | No to Imperialist war |
,--' _,' | Wage class war! |
/ / `-----------------------'
( -. |
| ) |
(`-. '--.)
`. )----'

Tim Bradshaw

unread,
Feb 16, 2002, 3:51:14 PM2/16/02
to
* Erann Gat wrote:

> Second, you can do exactly the same thing with a list of hash tables. In
> fact, an alist is just a special case of this. You can think of a cons
> cell as a brain-damaged hash table with a capacity of one entry and the
> identity as the hash function.

You can do the same thing, but it's several hundred times more
expensive to do.

--tim

Tim Bradshaw

unread,
Feb 16, 2002, 3:57:29 PM2/16/02
to
* Erann Gat wrote:
> What I'm saying is that when it comes to associative maps -- an extremely
> important abstraction (arguably the most important in all of computer
> science, but that's another discussion) -- this philosophy of deferring
> decisions breaks down, at least within the bounds of the current
> standard.

I'm not averse to a standard (or de-facto standard) common interface
to associative maps. However in my code I find that in all the cases
where I would have problems because of the differing interfaces the
usage is either very local indeed (for instance within a little
collection of functions to implement a binding scheme or occurs
check), or it sits behind some other interface (FIND-CHILD-NAMED /
ADD-CHILD-NAMED or something, where the implementation can (and
sometimes does) change. The only places where I globally expose an
implementation are where I care about fast binding (and the
implementation is then an alist). So *for me* (italics intentional)
the gain would be very small.

--tim

Erik Naggum

unread,
Feb 16, 2002, 5:04:04 PM2/16/02
to
* Erann Gat

| First, the special variable is a red herring. What you say is equally
| true whether or not *alist* is special.

Huh? I gave a couple examples that should be enlightening. I am sorry
that I do not have space to include the entire universe in every example
to make sure that is also true but not mentioned because it is probably
not useful in the process of _understanding_ the example. If you have to
get everything "just so", please let me know, and I will try to label my
examples "not suitable for Erann Gat", instead of trying to cope with
your "special needs" for you.

| Second, you can do exactly the same thing with a list of hash tables.

Really? gethash works on a list of hash tables? Are you same guy who
whined that you could not defer the choice of association type in the
standard language? Suddenly you are allowed to rewrite the whole
language in order to argue that you can do with gethash what you can do
with assoc, even though it is not actually supported in the language.
You have gone from knowledgable in Common Lisp to a foll and a troll.

| In fact, an alist is just a special case of this. You can think of a
| cons cell as a brain-damaged hash table with a capacity of one entry and
| the identity as the hash function.

Yeah, that is a certainly brain-damaged way to look at it.

> Alists are also just as efficient from key to value as from value to key.

| If you really need a bidirectional mapping you can get one easily with a
| pair of hash tables. And the runtime efficiency will be O(1) instead of
| O(N).

Great, so now I have two different hashtables that need to be syncronized
with some extraneous code and one accessor for both instead of one data
structure and two accessor functions. Or perhaps you have forgotten
about rassoc now that you have turned to C++ to get your performance fix?

I have, after spending about 3 months with relational databases and SQL,
started to miss support for independent indexing (via hashtables, say)
and relational algebra. I would like to have been able to do these
things in-memory without the need for a fully-fledged database engine,
and not have to change the language I used when I wanted such an engine.
Thinking and designing at such a high level, I could not care less how
things are implemented below the levels I am interested in.

zaphod

unread,
Feb 16, 2002, 8:21:46 PM2/16/02
to
Erik Naggum <er...@naggum.net> wrote in message news:<32227491...@naggum.net>...

> * Sla...@ureach.com (zaphod)
> | I just wanted to let you know, that it's not neccasarilly an IRRATIONAL
> | dislike of parens.
>
> You failed.

Oh well; Hey; if I were a line in a Snobol4 program, that would mean
you'd be likely to have trouble getting passed me. I probably am too
dumb to be involved too much in programming language discussions, tho.
I hope for continued forgiveness, on the part of most concerned, for
my many failings and inadequacies. I'm in no mood to try to sound
better than state of me-p. I here formally state that I make no
claims to being anything that deserv3es respect. Can we flame off
now?
>
> ///

zaphod

unread,
Feb 16, 2002, 8:33:15 PM2/16/02
to
Kenny Tilton <kti...@nyc.rr.com> wrote in message news:<3C6D5AEC...@nyc.rr.com>...

> zaphod wrote:
>
> > In my case; I gave [parentheses] a try, and discovered it wasn't as easy as I've
> > been lead to beleive, but I'm so dang low-brow, I hack trial and
> > error, when it seems right.
>
> just curious: how long did you try?

a total of 12 hours, with an at-least 2 week, if not 3-week interval
in between, and no user manual. My situation is kinda strange, and so
is my motivation and goal. I should not have implied that I was
typical, and should have laso made it more clear that my idea that
there are rational reasons to dislike parens is only relative to the
examples the author of the thesis arg offered. It's not that
rational, but seems to me to be more rational than the "reminds me of
the time" sort of examples that the author offered.

Did you have a nice
> parentheses-matching editor to help?

Nope. Mulisp 86, with EXTREMELY scanty documentation.
I'm still having lot's of trouble. My goals and motivations (for lack
of a better word) are, asI say, kinda eccentric. For one thing; I'd
like to know...this thing seems to have a single error message, or no
more than 2that I've run into. Not real informative; ya know. Is
that in the nature of lisp, or something I'm running into due to me,
or due to peculiarities of MULISP, exactly and particularly (figured
I'd try to get that question in there). Do most not-forkid's
languages tend to be scanty in describing how you messed up?
Anyone know?
>
> thx

Gareth McCaughan

unread,
Feb 16, 2002, 8:52:22 PM2/16/02
to
Erann Gat wrote:

> (Hashmaps, by the way, are one of Common Lisp's best kept secrets, one of
> those "other" data types that doesn't get much attention among all the
> hoopla over lists, atoms, and symbols. Hashmaps are tremendously useful,
> and for a long time Common Lisp was the only language that had them.
> Today C is about the only language in common use that doesn't have them.)

C++ doesn't have them. A C++ "map" pretty much has to be
implemented with some kind of tree structure. Some versions
of the STL have "hashmap" classes, but they are not in the
standard.

I believe Visual Basic doesn't have hash tables. Nor,
so far as I know, does COBOL. Nor Fortran. Nor Scheme.

It is, however, true that Perl, Python, Ruby and Java
have hash tables. Is that what you meant? :-)

--
Gareth McCaughan Gareth.M...@pobox.com
.sig under construc

Kenny Tilton

unread,
Feb 17, 2002, 2:55:31 AM2/17/02
to

zaphod wrote:
>
> Kenny Tilton <kti...@nyc.rr.com> wrote in message news:<3C6D5AEC...@nyc.rr.com>...
> > zaphod wrote:
> >
> > > In my case; I gave [parentheses] a try, and discovered it wasn't as easy as I've
> > > been lead to beleive, but I'm so dang low-brow, I hack trial and
> > > error, when it seems right.
> >
> > just curious: how long did you try?
>
> a total of 12 hours, with an at-least 2 week, if not 3-week interval
> in between, and no user manual.

uh-oh. we don't call that "trying".

> Did you have a nice
> > parentheses-matching editor to help?
>
> Nope.

Well then fuggedaboutit. If you want to explore the Greatest Language on
Earth: (1) do so with an editor that groks Lisp (including parens); (2)
spend, oh, twenty-four hours on it; and (3) jeezus h. christ, worry
about something more important than parentheses; are you a programmer or
a troll?

kenny

Erann Gat

unread,
Feb 17, 2002, 10:16:04 AM2/17/02
to

That depends. If you store only one item per hash table, then yes, that
would be pretty stupid. But if you store a whole frame in each hash table
and your frames are large then hash tables can be significantly more
efficient.

E.

Erann Gat

unread,
Feb 17, 2002, 10:25:45 AM2/17/02
to
In article <slrna6u36m.246a....@g.local>,
Gareth.M...@pobox.com wrote:

> Erann Gat wrote:
>
> > (Hashmaps, by the way, are one of Common Lisp's best kept secrets, one of
> > those "other" data types that doesn't get much attention among all the
> > hoopla over lists, atoms, and symbols. Hashmaps are tremendously useful,
> > and for a long time Common Lisp was the only language that had them.
> > Today C is about the only language in common use that doesn't have them.)
>
> C++ doesn't have them. A C++ "map" pretty much has to be
> implemented with some kind of tree structure. Some versions
> of the STL have "hashmap" classes, but they are not in the
> standard.

True, but the GNU STL has them. It's probably only a matter of time
before hashmaps are a de facto standard in C++ (if they aren't already).

> I believe Visual Basic doesn't have hash tables. Nor,
> so far as I know, does COBOL. Nor Fortran. Nor Scheme.
>
> It is, however, true that Perl, Python, Ruby and Java
> have hash tables. Is that what you meant? :-)

Yes. Of course.

E.

Erann Gat

unread,
Feb 17, 2002, 10:45:18 AM2/17/02
to
In article <B8942DBD.77B0%the...@cs.umass.edu>, Louis Theran
<the...@cs.umass.edu> wrote:

> It's not that hard to write a library that lets you do this. (We have such
> a thing where I work.) Though you do have to write it. I agree that the
> standard could have been more friendly in this regard, but it doesn't seem
> to be getting in the way. Or am I missing something?

No, I don't think you're missing anything. All I'm saying is that IMO
converging on a de facto standard for an abstract associative map not tied
to any particular implementation would be worthwhile.

E.

Erann Gat

unread,
Feb 17, 2002, 10:29:21 AM2/17/02
to
In article <32228858...@naggum.net>, Erik Naggum <er...@naggum.net> wrote:

> * Erann Gat
> | First, the special variable is a red herring. What you say is equally
> | true whether or not *alist* is special.
>
> Huh? I gave a couple examples that should be enlightening.

Really? Where? I found only one code snippet from you in this thread
(http://groups.google.com/groups?selm=3222747467111424%40naggum.net), and
it had no special variables in it at all.

E.

Thomas F. Burdick

unread,
Feb 17, 2002, 2:28:28 PM2/17/02
to
Kenny Tilton <kti...@nyc.rr.com> writes:

> and (3) jeezus h. christ, worry about something more important than
> parentheses; are you a programmer or a troll?

I thought the answer to this one had been clear for some time.

Tim Bradshaw

unread,
Feb 17, 2002, 3:04:48 PM2/17/02
to
* Erann Gat wrote:

> That depends. If you store only one item per hash table, then yes, that
> would be pretty stupid. But if you store a whole frame in each hash table
> and your frames are large then hash tables can be significantly more
> efficient.

Erik specifically said `push a single value'.

--tim

Christophe Rhodes

unread,
Feb 17, 2002, 3:12:02 PM2/17/02
to
g...@jpl.nasa.gov (Erann Gat) writes:

Oh, goody, a volunteer!

Or did you want this standard to appear magically?

Christophe

No, I'm not bitter :-)
--
Jesus College, Cambridge, CB5 8BL +44 1223 510 299
http://www-jcsu.jesus.cam.ac.uk/~csr21/ (defun pling-dollar
(str schar arg) (first (last +))) (make-dispatch-macro-character #\! t)
(set-dispatch-macro-character #\! #\$ #'pling-dollar)

Christopher C. Stacy

unread,
Feb 17, 2002, 3:52:04 PM2/17/02
to
>>>>> On Sun, 17 Feb 2002 07:45:18 -0800, Erann Gat ("Erann") writes:
Erann> All I'm saying is that IMO converging on a de facto standard
Erann> for an abstract associative map not tied to any particular
Erann> implementation would be worthwhile.

If you want an abstract associative map, I think that's what the
MAKE-HASH-TABLE and GETHASH are supposed to be. ASSOC and MEMBER
and stuff are for when you also need the data to be in a list.

If you need to get inside to mess with the implementation...

Lisp's "hash tables" do not need to actually be based on hash codes
and buckets. An implementation could provide "hash table" objects
that are really just alists (or whatever) under the covers.

The implementation of the object could change at run-time when
the system noticed that performance was not optimal for the current
implementation; sort of a "meta re-hash". (This was proposed for
the Symbolics implementation, but I am not sure it was implemented:
more trouble than worth it, or maybe it turned out that hashing was
faster even for small tables anyway.)

It would be nice if Common Lisp opened up the underlying protocol
for implementing new kinds of ("hash") tables based on CLOS.

The Lisp Machine provided some of that: PUT-HASH, GET-HASH, SWAP-HASH,
CLEAR-HASH, REM-HASH, MODIFY-HASH, MAP-HASH and NEXT-ELEMENT (for LOOP
interation paths); and some internal ones CHOSE-NEW-SIZE, GROW,
COPY-HASH, NEW-ARRAY.

The Lisp Machine also had the HEAP (prioritized list) data type
that provided similar table functionality.

Erik Naggum

unread,
Feb 17, 2002, 4:15:05 PM2/17/02
to
* Erann Gat

| Really? Where? I found only one code snippet from you in this thread
| (http://groups.google.com/groups?selm=3222747467111424%40naggum.net), and
| it had no special variables in it at all.

Troll. No more food for you.

Kenny Tilton

unread,
Feb 18, 2002, 12:15:17 AM2/18/02
to

"Thomas F. Burdick" wrote:
>
> Kenny Tilton <kti...@nyc.rr.com> writes:
>
> > and (3) jeezus h. christ, worry about something more important than
> > parentheses; are you a programmer or a troll?
>
> I thought the answer to this one had been clear for some time.

:) My assessment has varied from post to post, kind of a Heisenberg
thing...

k

Erann Gat

unread,
Feb 19, 2002, 12:58:29 AM2/19/02
to

Yes, and I extrapolated to the more difficult case of a large number of
values. But fine, we'll do it your way.

(defun hassoc (key loh) ; loh = list-or-hashtable
(acond ( (null loh) nil )
( (hash-table-p loh) (gethash key loh) )
( (consp (car loh))
(if (eq key (caar loh))
(car loh)
(hassoc key (cdr loh))) )
; And while we're at it...
( (and (hash-table-p (car loh)) (gethash key (car loh)))
(cons key it) )
(t (hassoc key (cdr list)))))

(This code is untested.)

Remember, the topic under discussion was my claim that there's nothing you
can do with alists that would be fundamentally more difficult to do with
hash tables.

Now, what was the point you were trying to make?

E.

Erann Gat

unread,
Feb 19, 2002, 1:44:51 AM2/19/02
to
In article <32229693...@naggum.net>, Erik Naggum <er...@naggum.net> wrote:

> * Erann Gat
> | Really? Where? I found only one code snippet from you in this thread
> | (http://groups.google.com/groups?selm=3222747467111424%40naggum.net), and
> | it had no special variables in it at all.
>
> Troll. No more food for you.

Good! Except for one thing: I wasn't trolling. Let me show you what a
real troll looks like:

<troll>
On second thought, you're really not worth the effort.
</troll>

This has been a test of the emergency trolling system. If this had been
an actual troll no doubt Erik will be unable to refrain from having the
last word and letting us all know.

E.

Tim Bradshaw

unread,
Feb 19, 2002, 4:49:26 AM2/19/02
to
* Erann Gat wrote:

> Now, what was the point you were trying to make?

That binding a single value is expensive if you use hashtables.

I can't read your code because it's weirdly formatted and uses what is
obviously some special conditional macro which it fails to
define. However as far as I can see it does not solve this problem,
but instead clumsily defines a `generic function' for lookup which has
a couple of fixed cases to deal with hashtables and alists. I suppose
your argument is that you can make hashtables cheap by, erm, using
alists instead. Well, OK, I agree with that.

I wish I was Erik and could think of some really blistering abuse at
this point. Perhaps if enough people scream at you you'll go away for
good.

--tim


Duane Rettig

unread,
Feb 19, 2002, 6:00:08 AM2/19/02
to
g...@jpl.nasa.gov (Erann Gat) writes:

> Remember, the topic under discussion was my claim that there's nothing you
> can do with alists that would be fundamentally more difficult to do with
> hash tables.

How about POP?

--
Duane Rettig Franz Inc. http://www.franz.com/ (www)
1995 University Ave Suite 275 Berkeley, CA 94704
Phone: (510) 548-3600; FAX: (510) 548-8253 du...@Franz.COM (internet)

Erik Naggum

unread,
Feb 19, 2002, 8:33:43 AM2/19/02
to
* Erann Gat

| Now, what was the point you were trying to make?

What _really_ happened when you lost your faith in Lisp?

Will Deakin

unread,
Feb 19, 2002, 10:52:20 AM2/19/02
to
Erik Naggum wrote:
> What _really_ happened when you lost your faith in Lisp?
Maybe we need to set up a fund to pay for c++ deprogramming. I know
some nice people who have got some experience with deprogramming
moonies...then again, is it worth it?

;)w


Will Deakin

unread,
Feb 19, 2002, 10:55:38 AM2/19/02
to
Christophe Rhodes wrote:
> No, I'm not bitter :-)
So you're a *lager*!

;)w

Erann Gat

unread,
Feb 19, 2002, 1:18:03 PM2/19/02
to
In article <43czx4...@beta.franz.com>, Duane Rettig <du...@franz.com> wrote:

> g...@jpl.nasa.gov (Erann Gat) writes:
>
> > Remember, the topic under discussion was my claim that there's nothing you
> > can do with alists that would be fundamentally more difficult to do with
> > hash tables.
>
> How about POP?

I guess it depends on what you consider fundamentally more difficult.
Popping an alist costs you esssentially nothing because this capability is
built into the language, whereas to "pop" a hash table you'd need to write
probably 10-20 lines of code. If you consider that "fundamentally more
difficult" then I concede the point (but would also point out that Erik
wrote much more than that for his apparently throwaway "proof of concept"
that led to this discussion.)

E.

Erann Gat

unread,
Feb 19, 2002, 1:55:15 PM2/19/02
to
In article <ey37kp9...@cley.com>, Tim Bradshaw <t...@cley.com> wrote:

> * Erann Gat wrote:
>
> > Now, what was the point you were trying to make?
>
> That binding a single value is expensive if you use hashtables.
>
> I can't read your code because it's weirdly formatted and uses what is
> obviously some special conditional macro which it fails to
> define.

Sorry. You present yourself as a knowledgeable person and I was trying to
treat you that way.

ACOND is from Paul Graham's "On Lisp". It's like "COND" but it binds the
variable "IT" to the result of the condition in the consequent clause.

(defmacro acond (&rest clauses)
(if (null clauses)
nil
(let ((cl1 (car clauses))
(sym (gensym)))
`(let ((,sym ,(car cl1)))
(if ,sym
(let ((it ,sym)) ,@(cdr cl1))
(acond ,@(cdr clauses)))))))

And sorry about the werd formatting. I was writing that message on a
non-paren-balancing editor.

> However as far as I can see it does not solve this problem,
> but instead clumsily defines a `generic function' for lookup which has
> a couple of fixed cases to deal with hashtables and alists. I suppose
> your argument is that you can make hashtables cheap by, erm, using
> alists instead. Well, OK, I agree with that.

I'm glad you agree, but that's not the point I was trying to make. Let me
be very clear. You say your point was:

> That binding a single value is expensive if you use hashtables.

My point is: you are wrong. Binding a single value is *not* expensive
even if you use hash tables, as my code, clumsy and unrefined though it
may be, clearly shows. The cost of the binding is exactly the same in
both cases. There is an extra call to hash-table-p in my version, but a
good compiler should be able to optimize the call to gethash to get rid of
the redundant call, so the net cost in a good implementation is actually
zero, and even in a not-so-good implementation is very small.

Note that "making hashtables cheap" is a completely different issue, a
non-sequitur, and one which you injected into this conversation, not me.

> I wish I was Erik and could think of some really blistering abuse at
> this point.

Work like that is better left to the master.

> Perhaps if enough people scream at you you'll go away for good.

You really think that will help?

E.

Duane Rettig

unread,
Feb 19, 2002, 4:00:01 PM2/19/02
to
g...@jpl.nasa.gov (Erann Gat) writes:

> In article <43czx4...@beta.franz.com>, Duane Rettig <du...@franz.com> wrote:
>
> > g...@jpl.nasa.gov (Erann Gat) writes:
> >
> > > Remember, the topic under discussion was my claim that there's nothing you
> > > can do with alists that would be fundamentally more difficult to do with
> > > hash tables.
> >
> > How about POP?
>
> I guess it depends on what you consider fundamentally more difficult.

Well, "fundamentally more difficult" is your own phrase, so you'll
have to define it. The word "difficult" has several usages (especially
as an antonym), and it also has several dictionary meanings, including
the one I settled on (because the others didn't seem to fit) which defines
difficult as "presenting obstacles or trouble" (World Book). Thus the
fact that hash-tables don't give you POP without having to code something
makes it fundamentally more difficult than alists (which give you POP
for free) according to this definition.

> Popping an alist costs you esssentially nothing because this capability is
> built into the language, whereas to "pop" a hash table you'd need to write
> probably 10-20 lines of code. If you consider that "fundamentally more
> difficult" then I concede the point (but would also point out that Erik
> wrote much more than that for his apparently throwaway "proof of concept"
> that led to this discussion.)

If maps were the only thing that alists provided, then I would have
no argument with you. But alists can also serve as stacks, and it is
fundamentally more difficult (according to my own interpretation) to
implement a stack concept using hash-tables than with alists.

Consider the implementation of a lisp interpreter, which might implement
execution environments using an association between names and values
along several namespace axes. An easy design using either alists or
hash-tables. But wait; these mappings must also have stack-like qualities,
in that they must be able to be peeled back as well as augmented, so that
they retain correct mappings for variables, etc. as they leave the scope
of their lexical lifetimes (hence my issue about POP). In addition,
in order for a debugger to see within such a stack to show the user
internal states, handles must be able to be captured which show the
environment in its peeled back state, even without having been
actually peeled back. Alists provide for all of these requirements
trivially, but some clever coding is required in order for hash-tables to
be used in the same way.

Note that I actually did implement this, and our interpreter actually
uses first-class environments that are based on hash-tables instead of
alists since version 6.0. So why am I disagreeing with you? I actually
do agree that hash-tables are underutilized and are at least as useful as
alists, but I only disagree about whether all of the requirements which
alsist can satisfy can also be satisfied by hash-tables trivially.
My environments implementation is considerably more than 10-20 loc.

Erann Gat

unread,
Feb 19, 2002, 3:57:12 PM2/19/02
to
In article <32231144...@naggum.net>, Erik Naggum <er...@naggum.net> wrote:

> * Erann Gat
> | Now, what was the point you were trying to make?
>
> What _really_ happened when you lost your faith in Lisp?

Glad you asked!

Let me first tell you how I acquired my faith in Lisp, because my
experience was very different from yours (as told in
http://groups.google.com/groups?selm=3208226254834485%40naggum.net&output=gplain)

I started using Lisp in high school, in 1979, on an Apple II. It was my
third (computer) language, after Basic and Pascal. I fell in love with it
almost right away even though in retrospect I really didn't "get it" for a
very long time. (Maybe I still don't.)

In those days I was growing up in Oak Ridge, Tennessee, a town of about
30,000 people, whose main industry is a nuclear research facility, so I
had the good fortune of being around a lot of really smart people, but
they were mostly nuclear engineers and physicists, not computer
scientists. They knew a lot about fortran and how to solve differential
equations, but I was interested in AI. I wanted to build autonomous
robots.

I was drawn to Lisp for three reasons. First, it was the language of
choice for the area of work I wanted to get into. Second, it struck me
right away as more aesthetic than Pascal or Fortran, and aesthetics are
important to me. Finally, it was just so much easier to get things done
in Lisp than in any other language. And not just by a little bit.

This was really driven home in college, where I used Lisp while my
colleagues used Pascal and C (and sometimes PL/I or Fortran). What took
them days and weeks to do took me hours or minutes, and not because I was
that much smarter than they were, because when I wrote code in Pascal my
performance was actually much worse than theirs. I particularly remember
my first graduate course in compilers. I did my work in Lisp while my
colleagues all used Pascal. They turned in reams of printouts (some were
literally a foot high), while my entire output for the term was maybe
twenty pages of code (including comments).

That experience convinced me of two things. First, using Lisp was the
Right Thing and second, many things (perhaps most things, perhaps all
things) that appear to be hard are actually easy. (I have since changed
my mind on both points, but I'm getting ahead of myself.)

The next ten years pretty much confirmed these lessons. Around 1986
Macintosh Common Lisp (then called Coral Common Lisp) came along, and I
never looked back. As a programming environment it is still in class by
itself even after fifteen years.

<tangent>
I used a Symbolics Lisp machine for a few years in the late eighties and
my experience with it was very unfortunate. I found the LispM to be
horrifically complicated and badly underpowered for what it was trying to
do. I often got myself into situations where the machine was many, many
seconds, sometimes minutes, behind my keystrokes. It was so frustrating I
eventually just gave up on it and went back to my Macintosh.
</tangent>

In 1988 I went to work at JPL, and again I found myself running rings
around other programmers by using Lisp. I did things (like write
compilers for little mini-languages) that people using C (there was no C++
at the time) wouldn't even contemplate attempting.

At JPL I encountered an interesting phenomenon. I would have proposals
rejected on the grounds that what I was proposing was too hard and
couldn't be done, when in fact I knew that what I was proposing was
actually quite easy (if one used Lisp). It got so bad that I would
actually develop prototypes as part of the proposal writing process just
so that I could say, "Not only is this not hard, it has already been
done." (It actually got even worse than that, but putting the details on
the record would not be healthy for my career.)

I also encountered an astonishing prejudice against Lisp and towards C.
Between 1988 and 1991 I worked on the research program that led to the
Mars Pathfinder rover. We built three prototype rovers during that time,
and I either wrote the code or supervised the person who did on all of
them. All three of them were programmed not in Lisp, but in little
mini-languages whose compilers were written in Lisp. (The rovers
themselves only had 8 bit processors with a few hundred or a few thousand
bytes of memory so we couldn't run Lisp directly.)

But when it came time to write the code for Sojourner they wrote it in C.
As far as I know the possibility of using the work we had done on the
prototypes was never even considered. All I know is that I was never
approached about it.

A similar thing happened many years later on a project called Remote Agent
(RA), which was a flight experiment to demonstrate an autonomous control
system for a spacecraft.
(http://ic.arc.nasa.gov/ic/projects/remote-agent/) At the beginning of
the project we had a lot of prototype code written in Lisp, so it seemed
natural to me to just fly Lisp aborad the spacecraft. The resistance to
this idea was tremendous and unrelenting. Fortunately, we resisted
successfully. I say fortunately, because at one point an attempt was made
to port part of the code (the planner) to C++. Afer a year that effort
had to be abandoned. On the basis of that experience I think it's safe to
say that if we hadn't used Lisp the Remote Agent would not have happend.

Nonetheless, it was not an unconditional victory. RA was part of the
first New Millennium mission, which was the flagship for Dan Goldin's new
"better, faster, cheaper" initiative. As a result we were given a budget
and schedule that everyone knew up front was impossibly tight. When the
inevitable schedule and budget slips hit the fan, Lisp became the
scapegoat. The software integration engineer was asked at a very
prominent review board hearing (attended by over 100 people) what was the
most significant factor causing the schedule slips. His reply: Lisp. As
a result, RA was down-graded from the mainline flight software to a
two-day flight experiment.

That was pretty much the end of Lisp at JPL. On my next project I tried
again to sell it, but the political damage done by the Remote Agent
experience was insurmountable. Finally, out of frustration, I quit JPL
and went to work for Google.

I went to Google with my faith fully intact. Let me be more specific
about what I mean by that. I had the following mindset, cemented by
twenty years of experience: first, Lisp is great. It lets you be orders
of magnitude more productive than C, and it's much more reliable (no core
dumps!). Second, because Lisp is so great, the only reason a rational
person would choose not to use it is if they were ignorant. There
certainly were an awful lot of ignorant objections to Lisp at JPL. (BTW,
ignorant is not a pejorative term. If you think it is you are ignorant
and you need to go look the word up in a dictionary.) Third, I thought
that this ignorance could survive at JPL because it was not subject to
market forces.

There was always some niggling doubt in my mind about this last point.
Over the course of twenty years the following question had begun to bother
me more and more: if Lisp is such a massive productivity gain over C, why
doesn't it win in the market? At JPL suboptimal strategies can survive
because we're an FFRDC (federally funded research and development center)
and therefore somewhat insulated from market forces. But out there in the
real world there ought to be some people using Lisp to whomp the pants off
the C-using competition, and it just didn't seem to be happening. I came
up with the following theory: lots of people are using Lisp, but they
don't want the competition to know because they want the competition to
keep using C.

It was a plausible enough theory, except for two things. First, a secret
of this magnitude would be awfully hard to keep, and second, my own
experience in trying to hire Lisp programmers demonstrated to me that they
are very hard to find. I was reasonably well known in the Lisp
community. If there really were lots of people out there secretly using
Lisp and programmers were scarce I would have expected to find myself
being recruited, but I was not. At this point I was seriously considering
the possibility that there really was a thriving Lisp economy out there
somewhere, and that I was being excluded from it for some reason, like
maybe my reputation for being obnoxious. (But even that theory came
unraveled when you showed up, Erik.)

So I can't really go into many specifics about what happened at Google
because of confidentiality, but the upshot was this: I saw, pretty much
for the first time in my life, people being as productive and more in
other languages as I was in Lisp. What's more, once I got knocked off my
high horse (they had to knock me more than once -- if anyone from Google
is reading this, I'm sorry) and actually bothered to really study some of
these other languges I found *myself* suddenly becoming more productive in
other languages than I was in Lisp. For example, my language of choice
for doing Web development now is Python.

I also saw Peter Norvig come to Google and leave Lisp behind with no
apparent regrets. (Actually, Peter and I had talked about this while we
were both still at NASA, and he was already leaving Lisp behind, which I
found very distressing at the time.)

Finally, I read Paul Graham's recent writings. He's the only person I
know of who has actually gotten wealthy using Lisp. That doesn't make him
infallible, but I think it does make it prudent to pay attention to what
he has to say. At least when Paul says, "That's how I got to where I am,"
I don't have to wonder where that is.

That's the story in a very large nutshell. What happened when I lost my
faith was that I could no longer sustain it in the face of mounting
evidence to the contrary.

Let me just make two comments to those of you who have had the patience to
read this far: 1) thanks, and 2) my aim here is not to diss Lisp. My goal
is honestly constructive. I think that if Lisp does not evolve it will
die, and I don't want to see that happen. I still think Lisp is great. I
also think it can be, and should be, improved.

E.

Tim Bradshaw

unread,
Feb 19, 2002, 5:08:30 PM2/19/02
to
* Erann Gat wrote:

> Sorry. You present yourself as a knowledgeable person and I was trying to
> treat you that way.

I don't present myself in any way at all. *You* or others may make
assumptions based on what I write (such as: I've read and remember On
Lisp).

> You really think that will help?

Yes, I do think it would help if you went away.

Marco Antoniotti

unread,
Feb 19, 2002, 5:30:58 PM2/19/02
to

g...@jpl.nasa.gov (Erann Gat) eventually writes:

...

> Let me just make two comments to those of you who have had the patience to
> read this far: 1) thanks, and 2) my aim here is not to diss Lisp. My goal
> is honestly constructive. I think that if Lisp does not evolve it will
> die, and I don't want to see that happen. I still think Lisp is great. I
> also think it can be, and should be, improved.

I believe it is hard to disagree with the above. However, IMHO there
are at least two schools of thought that seem at odds.

1 - CL must be junked and something new must be "evolved" in its place.
2 - CL can evolve by incorporating things that are "out there".

It seems to me that most of the debate is whether (1) is better than
(2) and viceversa. Graham has obviously chosen (1). Other people
have simply left CL behind.

I prefer to stay in the (2) camp. Not that I believe that CL will get
anywhere. I just like it and I accept that working with CL is a
personal luxury. At the same time, as long as I will be able to, I
will consider CL my favourite hobby and participate in any effort that
can evolve it into a more usable environment.

Having said so, I'd bettr stop writing on C.L.L. and hack a little bit.

Cheers

--
Marco Antoniotti ========================================================
NYU Courant Bioinformatics Group tel. +1 - 212 - 998 3488
719 Broadway 12th Floor fax +1 - 212 - 995 4122
New York, NY 10003, USA http://bioinformatics.cat.nyu.edu
"Hello New York! We'll do what we can!"
Bill Murray in `Ghostbusters'.

Erik Naggum

unread,
Feb 19, 2002, 5:34:48 PM2/19/02
to
* Erann Gat
| Glad you asked!

Sigh. Will you _ever_ get a clue? (For full credit, your answer must be
2000 words or longer.)

A free hint for you: Cut your losses and just _move_on_. If Python is so
great, enjoy it for what it is, and make it your new community. Pursue
your happiness -- if it is to be found elsewhere, move accordingly.
Hanging around here apparently makes you progressively more unhappy.

Erann Gat

unread,
Feb 19, 2002, 5:17:05 PM2/19/02
to
In article <4d6z1u...@beta.franz.com>, Duane Rettig <du...@franz.com> wrote:

> Note that I actually did implement this, and our interpreter actually
> uses first-class environments that are based on hash-tables instead of
> alists since version 6.0. So why am I disagreeing with you? I actually
> do agree that hash-tables are underutilized and are at least as useful as
> alists, but I only disagree about whether all of the requirements which
> alsist can satisfy can also be satisfied by hash-tables trivially.
> My environments implementation is considerably more than 10-20 loc.

So I provided an existence proof of what you describe in less than 10
lines of code (using Paul Graham's ACOND macro, but it's probably still
<20 LOC using just standard CL), though I have no doubt that your
implementation does all kinds of wizzy things that mine doesn't.

I think we actually agree more than we disagree here. Remember, this
discussion started with Erik arguing against a generic dictionary syntax
on the grounds that alist syntax served the same purpose.
(http://groups.google.com/groups?selm=3222747467111424%40naggum.net&output=gplain)

Erik wrote:

> I mean, if { "foo" => "bar", "baz" => "zot" } is so great, why is not
> (("foo" . "bar") ("baz" . "zot"))? Is it _only_ the sugar-coated syntax
> that is so visually appealing to some?

My point is simply that no, it's not just the visual appeal. It's also
the fact that the first syntax is implementation-neutral while the second
syntax is not, and IMO that's an advantage. Erik hinted that he agreed
with this:

> Common Lisp has the disadvantage compared to the one-trick languages that
^^^^^^^^^^^^^^^^^^^^
> the different access functions for various kinds of mappings between key
> and value are precisely that -- different.

although with Erik it's sometimes hard to tell when he's being ironic and
when he's not.

I also just thought of another advantage: the first syntax lets you catch
certain errors at read time that the second syntax does not, e.g. (("foo"
. "bar") ("baz" . "zot") . bing)

Then Nils Goesche replied that alists are better *because* they are lists,
I asked why, and Erik responded with the shadowing argument, to which I
responded that you can do shadowing with hash tables too. I didn't spend
a lot of effort developing this argument because in trying to give people
the benefit of the doubt about what they already understood I assumed it
would be self-evidently true. I suppose it's not altogether inconceivable
that I have stumbled across something entirely new to the Lisp community
in my little code snippet. But I really doubt it.

E.

Erann Gat

unread,
Feb 19, 2002, 5:28:31 PM2/19/02
to
In article <sqwuxbz...@cam.ac.uk>, Christophe Rhodes <cs...@cam.ac.uk>
wrote:

> g...@jpl.nasa.gov (Erann Gat) writes:

> > No, I don't think you're missing anything. All I'm saying is that IMO
> > converging on a de facto standard for an abstract associative map not tied
> > to any particular implementation would be worthwhile.
>
> Oh, goody, a volunteer!
>
> Or did you want this standard to appear magically?

Not at all. I'd be happy to write a draft proposal, but before I do I'd
like some indication that someone besides me thinks this is worth doing.
Unlike Erik, I'm not always sure that I'm right about everything. I'd
also like some indication that even those who don't think it's worth doing
at least think it's not doing any harm. At the moment the feedback I'm
getting is pretty much the opposite.

E.

Thomas A. Russ

unread,
Feb 19, 2002, 3:42:18 PM2/19/02
to
g...@jpl.nasa.gov (Erann Gat) writes:

> 1. Alists can be more efficient than hash tables, particularly for small
> data sets.

Agreed. Many years ago we did some empirical tests and found that the
cross-over point on performance was for much larger alists than we would
have guessed. I recall it being somewhere around 50 items or so.

> 2. Having "all those nice list functions" is only an advantage insofar as
> they let you do something useful. Being able to operate on an alist as a
> list is not in and of itself a feature, and can lead to problems if you're
> not careful. I can't offhand think of anything useful you can do with an
> alist that is fundamentally more difficult with a hashmap.

Well, there is the shadowing of keys. This is much easier with a list
structure. In fact, one current application where this is handy is
dealing with XML namespaces, since those names can be shadowed.

5. Alists can use arbitrary comparison predicates, unlike hash tables.

--
Thomas A. Russ, USC/Information Sciences Institute t...@isi.edu

It is loading more messages.
0 new messages