From: frr
Subject: Be afraid of XML
Date: 
Message-ID: <7701505j1m6lq36eeo699q8f5turh20jlm@4ax.com>
The latest xml idiocy:
------------------------------------------------------------
Byte Code as XML 

I saw an article on TSS labeled "Thread dumps as XML," and thought to myself,
why couldn't byte code be done as XML? So I built a custom JVM and converted
rt.jar to my new XML byte code format. Now, this might seem an impossible
undertaking, but fortunately I had some extra hard drive space. My new rt.jar
is 620GB, but the class files are all human-readable now, and it's really nice
to be able to edit them in Notepad.
http://jroller.com/page/cpurdy/20040310
------------------------------------------------------------

Be afraid, be very afraid...

From: Rayiner Hashem
Subject: Re: Be afraid of XML
Date: 
Message-ID: <a3995c0d.0403111055.26f58f34@posting.google.com>
> Be afraid, be very afraid...
Knee-jerk reactions aside, I'm pretty sure he's joking :)
From: Michael Hudson
Subject: Re: Be afraid of XML
Date: 
Message-ID: <m3ad2ncpm0.fsf@pc150.maths.bris.ac.uk>
frr <······@telefonica.net> writes:

> The latest xml idiocy:
> ------------------------------------------------------------
> Byte Code as XML 
> 
> I saw an article on TSS labeled "Thread dumps as XML," and thought to myself,
> why couldn't byte code be done as XML? So I built a custom JVM and converted
> rt.jar to my new XML byte code format. Now, this might seem an impossible
> undertaking, but fortunately I had some extra hard drive space. My new rt.jar
> is 620GB, but the class files are all human-readable now, and it's really nice
> to be able to edit them in Notepad.
> http://jroller.com/page/cpurdy/20040310
> ------------------------------------------------------------
> 
> Be afraid, be very afraid...

I believe you may have been whooshed.  I certainly really really hope
so.

Cheers,
mwh

-- 
  (Unfortunately, while you get Tom Baker saying "then we 
   were attacked by monsters", he doesn't flash and make 
  "neeeeooww-sploot" noises.)
      -- Gareth Marlow, ucam.chat, from Owen Dunn's review of the year
From: Joe Marshall
Subject: Re: Be afraid of XML
Date: 
Message-ID: <y8q76x3h.fsf@ccs.neu.edu>
Michael Hudson <···@python.net> writes:

> frr <······@telefonica.net> writes:
>
>> The latest xml idiocy:
>> ------------------------------------------------------------
>> Byte Code as XML 
>> 
>> I saw an article on TSS labeled "Thread dumps as XML," and thought to myself,
>> why couldn't byte code be done as XML? So I built a custom JVM and converted
>> rt.jar to my new XML byte code format. Now, this might seem an impossible
>> undertaking, but fortunately I had some extra hard drive space. My new rt.jar
>> is 620GB, but the class files are all human-readable now, and it's really nice
>> to be able to edit them in Notepad.
>> http://jroller.com/page/cpurdy/20040310
>> ------------------------------------------------------------
>> 
>> Be afraid, be very afraid...
>
> I believe you may have been whooshed.  I certainly really really hope
> so.

I dunno, this doesn't seem much stupider than a lot of what people use
XML for.
From: Stefan Scholl
Subject: Re: Be afraid of XML
Date: 
Message-ID: <1ood0k8wxanoz.dlg@parsec.no-spoon.de>
On 2004-03-11 19:46:10, Joe Marshall wrote:

> I dunno, this doesn't seem much stupider than a lot of what people use
> XML for.

Sometimes it's OK to use XML and sometimes not.

And it's really hard to try to explain the difference in a specific
case when some people only know that XML is cool and helps to solve
some problems. Even questioning it is like heresy. :-(
From: John Thingstad
Subject: Re: Be afraid of XML
Date: 
Message-ID: <opr4peuuqixfnb1n@news.chello.no>
On Thu, 11 Mar 2004 16:10:16 +0100, frr <······@telefonica.net> wrote:

lol

I always wonder how long it will be before they realize that programs 
don't do much more than they did 5 years ago.
They add a ton of useless featues and take up more disk space and run 
slower.
XML is just one of many steps taken to develop bloat-ware.

Java is in it own right a champion here.
Take as an exampaple Borland C++ BuilderX.
A program written in Java for writing portable C/C++ code. (see the irony)
54 Mb min to run the program. Quickly it rises to 100 Mb.
Everthing slows down and after 2 hours of use it took me 5 minutes to 
select an item
in a combo-box. If this is the future I want no part in it.

>
> The latest xml idiocy:
> ------------------------------------------------------------
> Byte Code as XML
>
> I saw an article on TSS labeled "Thread dumps as XML," and thought to 
> myself,
> why couldn't byte code be done as XML? So I built a custom JVM and 
> converted
> rt.jar to my new XML byte code format. Now, this might seem an impossible
> undertaking, but fortunately I had some extra hard drive space. My new 
> rt.jar
> is 620GB, but the class files are all human-readable now, and it's 
> really nice
> to be able to edit them in Notepad.
> http://jroller.com/page/cpurdy/20040310
> ------------------------------------------------------------
>
> Be afraid, be very afraid...

-- 
Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
From: Tim Bradshaw
Subject: Re: Be afraid of XML
Date: 
Message-ID: <fbc0f5d1.0403111101.78877a3c@posting.google.com>
John Thingstad <··············@chello.no> wrote in message news:<················@news.chello.no>...

> Java is in it own right a champion here.

I think this is to misunderstand the problem.  I have always thought
(and I still think) that Java is an engineering masterpiece: a
language close enough to C(++) to be acceptable, yet simple enough for
average programmers to use, which fixes the most awful problems of
C/C++ (lack of memory management and bounds checking), and finally
with a good enough and modern enough library.

But the problem is in the above statement: *it's simple enough for
average programmers to use*, and we know about average programmers.

So what has happened is that suddenly a whole bunch of average
programmers are producing `working' programs, and inflicting them on
innocent bystanders.  There's a kind of technical definition of
`working' in play here. In C or C++, it is so hard to get substantial
programs to work *at all* because of memory issues that really
competent people are needed.  Even these really competent people can't
really get all the bugs out - witness the endless stream of
buffer-overflow issues in almost any highly-visible C or C++ system. 
But they get things mostly-working, and because they are really
competent they can do stuff like design half right.  But in Java, you
can get much further, because memory issues don't kill you.  In fact
you can produce substantial systems which sort-of run, without a
functioning brain at all.  And this is what's happening, and the
results are exactly what you'd expect.

Interestingly the same is historically true for Lisp: because Lisp
implementations generally protect you against the low-level issues
which blight C/C++ systems, average programmers can get further.  And
so `lisp is big and slow'.

--tim
From: Espen Vestre
Subject: Re: Be afraid of XML
Date: 
Message-ID: <kwwu5qv6nz.fsf@merced.netfonds.no>
··········@tfeb.org (Tim Bradshaw) writes:

> Interestingly the same is historically true for Lisp: because Lisp
> implementations generally protect you against the low-level issues
> which blight C/C++ systems, average programmers can get further.  And
> so `lisp is big and slow'.

Still, there seems to be a common conception that "lisp is rocket
science", i.e. not possible to even learn for the foot soldier
programmer. 
-- 
  (espen)
From: Tim Bradshaw
Subject: Re: Be afraid of XML
Date: 
Message-ID: <fbc0f5d1.0403120545.75c25f53@posting.google.com>
Espen Vestre <·····@*do-not-spam-me*.vestre.net> wrote in message news:<··············@merced.netfonds.no>...
> 
> Still, there seems to be a common conception that "lisp is rocket
> science", i.e. not possible to even learn for the foot soldier
> programmer.

Yes, I think that's right: it is rocket science. So Java is very
successful because lots of average programmers can learn it, while
only a few have the persistence to leanr Lisp (often academics and
other AI-type people).  But they still produce terrible programs.  So
lisp is big, slow and obscure, while Java is big, slow and popular.
From: Christian Lynbech
Subject: Re: Be afraid of XML
Date: 
Message-ID: <877jxpwus5.fsf@baguette.defun.dk>
>>>>> "Tim" == Tim Bradshaw <tfb> writes:

Tim> Espen Vestre <·····@*do-not-spam-me*.vestre.net> wrote in message news:<··············@merced.netfonds.no>...
>> 
>> Still, there seems to be a common conception that "lisp is rocket
>> science", i.e. not possible to even learn for the foot soldier
>> programmer.

Tim> Yes, I think that's right: it is rocket science. So Java is very
Tim> successful because lots of average programmers can learn it, while
Tim> only a few have the persistence to leanr Lisp.

I disagree. I am sure that it would be no harder to learn an average
programmer Lisp than it would be to learn him Java. In fact I even
think it could be easier or produce better results because Lisp is
truly multiparadigmatic and thus the average programmer gets the
benefit of a simpler syntax and a sandbox of simple imperative
primitives as a starting point rather than inflicting the full weight
of OO from the beginning.

However, average programmers will not touch Lisp since Lisp is not
popular. Java started as being just too cool and then got incredible
popular such that average programmers would not stop to think for a
second whether that particular choice is good or not.


------------------------+-----------------------------------------------------
Christian Lynbech       | christian ··@ defun #\. dk
------------------------+-----------------------------------------------------
Hit the philistines three times over the head with the Elisp reference manual.
                                        - ·······@hal.com (Michael A. Petonic)
From: David Steuber
Subject: Re: Be afraid of XML
Date: 
Message-ID: <m2u10t6zs2.fsf@david-steuber.com>
Christian Lynbech <·········@defun.dk> writes:

> However, average programmers will not touch Lisp since Lisp is not
> popular. Java started as being just too cool and then got incredible
> popular such that average programmers would not stop to think for a
> second whether that particular choice is good or not.

The thing is, Lisp *is* weird.  It uses lots of parens.  It uses
prefix notation.  It has fairly consistent syntax (with special forms
and macros being the only exceptions I know of at present).  Lisp
doesn't *look* like the programming languages most people see first.

Java has a strong superficial resemblence to C++.  It came out with
full on Sun marketing at a time when C++ was growing into a rather
large language.  It had (has?) Internet hype.  It is also not a bad
language when you are used to C/C++.  When you've never had it
before, garbage collection seems pretty cool to have.  And now with
all the mindshare, there are a lot of libraries for solving fairly
mundane business problems.

That said, Java does cause problems.  The huge mindshare for Java
subtracts talent from other languages.  I think this leads to the
classical problem of having a hammer, so every problem looks like a
nail.  It also can hinder progress in other languages.

Java is not so simple either.  Basic is even easier to learn I
expect.  Fortran isn't hard either.  A fundemental part of Java is
the rather large standard library.  If you expect a Java programming
job, you need to know J2EE as well.  Yikes.  And what does that
knowledge have to do with programming?  Not much.  People really are
expected to be interchangeable code monkeys.

A good programmer is a good programmer and a bad programmer is a bad
programmer.  I don't think the language changes that.  The language
may be an enabler.  I expect a good programmer who is proficient with
Lisp can do more than a good programmer who is proficient with just
Java.  Then again, the preceding sentence may contain a nasty
paradox.  A good programmer is likely to be proficient with several
languages or at least knowledgeable about them.

I think the biggest problem with Java though is that it is an
impediment to research.  J2EE and whatnot standardize solutions that
may be suboptimal.  Building a large system in Java is like building
a pyramid or a bridge.  Every step has to be thought out before
ground is broken.  Is that really a natural way to program?  Is that
a requirement to call software engineering a genuine engineering
discipline?

I'll confess up front that my style of programming has always been
more organic.  I have a general idea of what to do but not how to get
there.  So I doodle in the editor.  I am always throwing code away or
factoring code out.  The problem is with Java (or C++) that doesn't
scale well.  You reach a point where changes get painful.  I don't
know yet if that is different with Lisp.  I really hope that it is.

-- 
Those who do not remember the history of Lisp are doomed to repeat it,
badly.

> (dwim x)
NIL
From: Tim Bradshaw
Subject: Re: Be afraid of XML
Date: 
Message-ID: <fbc0f5d1.0403150319.5d13e675@posting.google.com>
> 
> I disagree. I am sure that it would be no harder to learn an average
> programmer Lisp than it would be to learn him Java. In fact I even
> think it could be easier or produce better results because Lisp is
> truly multiparadigmatic and thus the average programmer gets the
> benefit of a simpler syntax and a sandbox of simple imperative
> primitives as a starting point rather than inflicting the full weight
> of OO from the beginning.

[Aside, you can't use `learn' like that in standafd English - someone
learns something, or someone is taught something (by someone), but you
don't learn someone something.  Except possibly in some USian dialects
- `that'll learn him'.]

Well, I disagree with that I think.  I think you could argue that
people could learn a kind of fortran-subset of Lisp pretty easily. 
But they'd ask questions like `why the strange syntax?', `why do you
need QUOTE?' `What use is LAMBDA?'.  And the answers to those are
things like macros and closures and introspection.  And *those aren't
easy things to understand*.  So if you tried to teach people just the
simple subset of Lisp they'd just prefer Java, which *is* a simple
subset of Lisp, but with a bigger standard library and without the
baggage which is necessary for advanced things.

So, yes, you could teach people a Lisp subset and it wouldn't be much
harder than (say) Java, but it would be enough harder that they
wouldn't do it.  And they would be *right* not to do it.

--tim
From: Albert Reiner
Subject: Re: Be afraid of XML
Date: 
Message-ID: <m1ekruuqr3.fsf@reiner.chello.at>
··········@tfeb.org (Tim Bradshaw) writes:

>                                      I think you could argue that
> people could learn a kind of fortran-subset of Lisp pretty easily. 
> But they'd ask questions like `why the strange syntax?', `why do you
> need QUOTE?' `What use is LAMBDA?'.  And the answers to those are
> things like macros and closures and introspection.  And *those aren't
> easy things to understand*.

I'm curious: I think I know pretty well what macros and closures are, and they
always seemed quite natural and conceptually simple things to me (despite a
strong background in, i.a., Fortran).  But what is ``introspection'' supposed
to be?  CLiki does not know the term, so a (pointer to a) simple explanation
would be most welcome.

(My intuition would be that it has something to do with the possibility of
looking through and acting upon an expression tree, which would be reminiscent
of the more creative uses of `defn' in m4 to a certain degree.  BTW, am I
correct that there is no real analogue of `defn' in CL, i.e., that after
(defmacro a () (whatever)) I have no way of getting from 'a to '(whatever)?)

Regards,

Albert.
From: Thomas F. Burdick
Subject: Re: Be afraid of XML
Date: 
Message-ID: <xcv8yi16gvu.fsf@famine.OCF.Berkeley.EDU>
Albert Reiner <······@chello.at> writes:

> ··········@tfeb.org (Tim Bradshaw) writes:
> 
> >                                      I think you could argue that
> > people could learn a kind of fortran-subset of Lisp pretty easily. 
> > But they'd ask questions like `why the strange syntax?', `why do you
> > need QUOTE?' `What use is LAMBDA?'.  And the answers to those are
> > things like macros and closures and introspection.  And *those aren't
> > easy things to understand*.
> 
> I'm curious: I think I know pretty well what macros and closures are, and they
> always seemed quite natural and conceptually simple things to me (despite a
> strong background in, i.a., Fortran).  But what is ``introspection'' supposed
> to be?  CLiki does not know the term, so a (pointer to a) simple explanation
> would be most welcome.

Dynamic, image-based languages like Lisp and Smalltalk often have the
ability to introspect, ie to look at themselves.  For example, I can
define a function to get the docstrings for all functions that are in
the image:

  (defun document-functions ()
    (dolist (package (list-all-packages))
      (loop for symbol being the symbols in package
            when (fboundp symbol)
            do (format "~&~S - ~A" symbol (documentation symbol 'function)))))

This uses the introspective functions LIST-ALL-PACKAGES, FBOUNDP, and
DOCUMENTATION, as well as the introspective  for-as-packages LOOP clause.

Also, the MOP, among other things, defines an introspective layer to
CLOS.  You can find out all kinds of properties about classes, slots,
and objects that you are given at runtime.

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | No to Imperialist war |                        
     ,--'    _,'   | Wage class war!       |                        
    /       /      `-----------------------'                        
   (   -.  |                               
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Hannah Schroeter
Subject: Re: Be afraid of XML
Date: 
Message-ID: <c34tjb$aa4$1@c3po.use.schlund.de>
Hello!

Albert Reiner  <······@chello.at> wrote:
>[...]

>of the more creative uses of `defn' in m4 to a certain degree.  BTW, am I
>correct that there is no real analogue of `defn' in CL, i.e., that after
>(defmacro a () (whatever)) I have no way of getting from 'a to '(whatever)?)

You mean from (a) to the result of (whatever)?

macroexpand or macroexpand-1

To (whatever) itself (non-evaluated)... You could try using
(function-lambda-expression (macro-function 'a)), but that might
return nil if the source code isn't saved.

Kind regards,

Hannah.
From: Tim Bradshaw
Subject: Re: Be afraid of XML
Date: 
Message-ID: <fbc0f5d1.0403160238.6e27a767@posting.google.com>
Albert Reiner <······@chello.at> wrote in message news:<··············@reiner.chello.at>...
> 
> I'm curious: I think I know pretty well what macros and closures are, and they
> always seemed quite natural and conceptually simple things to me (despite a
> strong background in, i.a., Fortran).  But what is ``introspection'' supposed
> to be?  CLiki does not know the term, so a (pointer to a) simple explanation
> would be most welcome.
> 

I don't know what the politically-correct definition is, but I mean
things like being able to look at the package structure of a program
and (say) describe it somehow, or being able to examine who-calls and
who-uses information.  CL itself doesn't specify an enormous set of
introspective features, but it (more-or-less) gives you enough tools
to build your own, and most decent implementations support more (say
who-calls &c).  So maybe introspection is more a language cultural
thing.

--tim
From: Rayiner Hashem
Subject: Re: Be afraid of XML
Date: 
Message-ID: <a3995c0d.0403120820.b118228@posting.google.com>
> Still, there seems to be a common conception that "lisp is rocket
> science", i.e. not possible to even learn for the foot soldier
> programmer.
Lisp isn't rocket-science, its just different. And learning things
that are different is hard. When you just start learning CL, so many
differences just hit you at once (parens, car/cdr, generic functions,
symbols, quote, etc) that a programmer coming from a C++/Java
background just goes into shock. Many of them stop right there and
don't go any further. If the continue, they'll find that many of the
initial mental associations they've made (eg: Lisp symbol = C++
identifier) break down when confronted by advanced (for C++) usages
such as putting symbols in lists. The tools associated with Lisp are
also unfamiliar. You've got a different development paradigm
(interactive vs compile/test/debug), you've got a different
distribution paradigm, even a different compilation paradigm
(in-language vs external tool). Then there are libraries like CLIM
(panes and sheets and gadgets, oh my!) which personally strike fear
into my heart.

Some transitional resources for those new to Lisp, coming from
C++/Java would be very useful for Lisp teaching. It'd include basic
things, like pointing out valid parallels between Lisp features and
C++/Java features, partially valid parallels, invalid parallels, etc.
Some concrete comparisons would be great. Eg: pointing out how much
nicer it is to manipulate s-exprs in Lisp than it is to manipulate XML
using XSLT, or pointing out how things like the visitor pattern become
unnecessary with multiple dispatch. These things would do a lot to
dispel the myth that Lisp is too hard for mere mortals to understand.
From: Mario S. Mommer
Subject: Re: Be afraid of XML
Date: 
Message-ID: <fzishakjuh.fsf@germany.igpm.rwth-aachen.de>
·······@mindspring.com (Rayiner Hashem) writes:
> > Still, there seems to be a common conception that "lisp is rocket
> > science", i.e. not possible to even learn for the foot soldier
> > programmer.
> Lisp isn't rocket-science, its just different. And learning things
> that are different is hard. When you just start learning CL, so many
> differences just hit you at once (parens, car/cdr, generic functions,
> symbols, quote, etc) that a programmer coming from a C++/Java
> background just goes into shock. Many of them stop right there and
> don't go any further. If the continue, they'll find that many of the
> initial mental associations they've made (eg: Lisp symbol = C++
> identifier) break down when confronted by advanced (for C++) usages
> such as putting symbols in lists. The tools associated with Lisp are
> also unfamiliar. You've got a different development paradigm
> (interactive vs compile/test/debug), you've got a different
> distribution paradigm, even a different compilation paradigm
> (in-language vs external tool). Then there are libraries like CLIM
> (panes and sheets and gadgets, oh my!) which personally strike fear
> into my heart.

I have never understood this phenomenon. I am usually fairly happy
when things are different and interesting. And if on top of that they
are powerful, then I'm elated. I've never been afraid of a piece of
technical knowledge, and must say that I find the idea funny. I mean,
is it going to melt your brain?
From: Kenny Tilton
Subject: Re: Be afraid of XML
Date: 
Message-ID: <DBn4c.15898$c73.5192234@twister.nyc.rr.com>
Mario S. Mommer wrote:

> ·······@mindspring.com (Rayiner Hashem) writes:
> 
>>>Still, there seems to be a common conception that "lisp is rocket
>>>science", i.e. not possible to even learn for the foot soldier
>>>programmer.
>>
>>Lisp isn't rocket-science, its just different. And learning things
>>that are different is hard. When you just start learning CL, so many
>>differences just hit you at once (parens, car/cdr, generic functions,
>>symbols, quote, etc) that a programmer coming from a C++/Java
>>background just goes into shock.

Nah, novelty just makes it easier to get out of bed in the morning. If 
you want to really get me productive, put me on a project using a 
language I do not know.

  Many of them stop right there and
>>don't go any further. If the continue, they'll find that many of the
>>initial mental associations they've made (eg: Lisp symbol = C++
>>identifier) break down when confronted by advanced (for C++) usages
>>such as putting symbols in lists. The tools associated with Lisp are
>>also unfamiliar. You've got a different development paradigm
>>(interactive vs compile/test/debug), you've got a different
>>distribution paradigm, even a different compilation paradigm
>>(in-language vs external tool).

Fun! Fun! Fun!

  Then there are libraries like CLIM
>>(panes and sheets and gadgets, oh my!) which personally strike fear
>>into my heart.

I better be quiet, I've already been penalized fifteen yards* for 
taunting** once today.

>  
> I have never understood this phenomenon. I am usually fairly happy
> when things are different and interesting. And if on top of that they
> are powerful, then I'm elated. 

My little crew was literally running around yelling "Have you seen <your 
favorite Lisp feature here>!?" after we got the CDs from Digitool.

I think the real problem for those who are not true enthusiasts is that 
they do not see the possibilities in Lisp, never having aspired to more 
than a well-paying, recession-immune career in programming. (Doh!) Lisp 
is for folks who try to do Lisp even before they know it exists.

kt

* about fourteen meters
** Amercian football trash-talking


-- 
http://tilton-technology.com

Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film

Your Project Here! http://alu.cliki.net/Industry%20Application
From: Rayiner Hashem
Subject: Re: Be afraid of XML
Date: 
Message-ID: <a3995c0d.0403141220.4ea804cf@posting.google.com>
> I think the real problem for those who are not true enthusiasts is that 
> they do not see the possibilities in Lisp, never having aspired to more 
> than a well-paying, recession-immune career in programming. (Doh!) Lisp 
> is for folks who try to do Lisp even before they know it exists.
I don't think it takes an enthusiast to appreciate what Lisp can do.
The popularity of things like Modern C++, Microsoft's Xen, embedded
scripting languages, XML, etc, attests to the fact that lots of people
are trying to do Lisp even though they don't know it exists. Lisp does
what these other technologies are doing, except it does them better. I
think programmers out there would be receptive to understanding how
Lisp could solve those problems, if resources were available to make
Lisp more understandable in their context.
From: Jacek Generowicz
Subject: Re: Be afraid of XML
Date: 
Message-ID: <tyfznad6vvg.fsf@pcepsft001.cern.ch>
Kenny Tilton <·······@nyc.rr.com> writes:

> I think the real problem for those who are not true enthusiasts is
> that they do not see the possibilities in Lisp, never having aspired
> to more than a well-paying, recession-immune career in
> programming.

Yup ...

> Lisp is for folks who try to do Lisp even before they know it
> exists.

I think you've hit the nail squarely on the head here !

(Sorry for the AOL-style post, but this so accurately reflects my
experience and feelings that I just could not contain a useless
emotional outburst :-)
From: Rayiner Hashem
Subject: Re: Be afraid of XML
Date: 
Message-ID: <a3995c0d.0403141206.10b3e651@posting.google.com>
> I have never understood this phenomenon. I am usually fairly happy
> when things are different and interesting. And if on top of that they
> are powerful, then I'm elated. I've never been afraid of a piece of
> technical knowledge, and must say that I find the idea funny. I mean,
> is it going to melt your brain?
Its cognitive dissonance at work. Most people who already know
Java/C++ programming have a mental model of how programming works.
When they encounter Lisp, they naturally try to apply that model to
the new language, and when that fails, they get frustrated and angry.
Those who realize the potential of Lisp fight through the effects of
the dissonance and continue to learn it. Those who do not shy away
from it, and actually become embittered against it.

Now, I suppose you could approach each new piece of knowledge as a
brand new idea, without any preconceptions, and try to appreciate it
in its own right. However, people largely do not work that way.
From: David Steuber
Subject: Re: Be afraid of XML
Date: 
Message-ID: <m2ad2j3qeo.fsf@david-steuber.com>
·······@mindspring.com (Rayiner Hashem) writes:

> Now, I suppose you could approach each new piece of knowledge as a
> brand new idea, without any preconceptions, and try to appreciate it
> in its own right. However, people largely do not work that way.

It is actually very difficult to do.  Comming from a C/C++
background, I certainly do/did have a strong concept of how
programming should work.  Lisp does indeed challenge that model.
What I am doing is trying to set aside the C way in favor of the Lisp
way so that I can move ahead with Lisp.

It is like trying to open a closed mind.  The doors have rust on the
hinges and the windows are painted shut.

Is XML and family Greenspun's tenth rule in action?

-- 
Those who do not remember the history of Lisp are doomed to repeat it,
badly.

> (dwim x)
NIL
From: Rayiner Hashem
Subject: Re: Be afraid of XML
Date: 
Message-ID: <a3995c0d.0403151005.777b04a7@posting.google.com>
David Steuber <·············@verizon.net> wrote in message news:<··············@david-steuber.com>...
> ·······@mindspring.com (Rayiner Hashem) writes:
> 
> > Now, I suppose you could approach each new piece of knowledge as a
> > brand new idea, without any preconceptions, and try to appreciate it
> > in its own right. However, people largely do not work that way.
> 
> It is actually very difficult to do.  Comming from a C/C++
> background, I certainly do/did have a strong concept of how
> programming should work.  Lisp does indeed challenge that model.
> What I am doing is trying to set aside the C way in favor of the Lisp
> way so that I can move ahead with Lisp.
> 
> It is like trying to open a closed mind.  The doors have rust on the
> hinges and the windows are painted shut.
> 
> Is XML and family Greenspun's tenth rule in action?
Definitely. Not just XML, either. Consider:
- C++'s current love-affair with templates and metaprogramming. Like
macros, only more limited and more complicated.
- C++ libraries like Boost and Loki that provide features (eg: visitor
pattern, lambdas, closures, first-class-ish types) that are built-into
Lisp.
- Language extensions like Microsoft's Xen, which make it easier to
handle XML. Unlike Lisp macros, however, they have a hard-coded
domain-specific language, instead of allowing programmers to build
their own DSLs.
From: Pascal Bourguignon
Subject: Re: Be afraid of XML
Date: 
Message-ID: <87znajkr7f.fsf@thalassa.informatimago.com>
Mario S. Mommer <········@yahoo.com> writes:
> I have never understood this phenomenon. I am usually fairly happy
> when things are different and interesting. And if on top of that they
> are powerful, then I'm elated. I've never been afraid of a piece of
> technical knowledge, and must say that I find the idea funny. I mean,
> is it going to melt your brain?

http://www.reciprocality.org/ gives some clue  about why.  It may well
"melt" the brains of the other category...

-- 
__Pascal_Bourguignon__                     http://www.informatimago.com/
There is no worse tyranny than to force a man to pay for what he doesn't
want merely because you think it would be good for him.--Robert Heinlein
http://www.theadvocates.org/
From: Tayssir John Gabbour
Subject: Re: Be afraid of XML
Date: 
Message-ID: <866764be.0403130243.6fcc1bcf@posting.google.com>
·······@mindspring.com (Rayiner Hashem) wrote in message news:<···························@posting.google.com>...
> Some transitional resources for those new to Lisp, coming from
> C++/Java would be very useful for Lisp teaching. It'd include basic
> things, like pointing out valid parallels between Lisp features and
> C++/Java features, partially valid parallels, invalid parallels, etc.
> Some concrete comparisons would be great. Eg: pointing out how much
> nicer it is to manipulate s-exprs in Lisp than it is to manipulate XML
> using XSLT, or pointing out how things like the visitor pattern become
> unnecessary with multiple dispatch. These things would do a lot to
> dispel the myth that Lisp is too hard for mere mortals to understand.

Peter Seibel's book seems to be precisely about this.

But as to your point, the mechanics don't seem to be the interesting
part to lisp.  The most important part of teaching (and hardest?), I
imagine, is giving motivation to people who otherwise might not have
it.  People don't seem to care if it's easier to "cdr" down a "list"
than to traverse some XML object.  This stuff will be learned given
ample motivation and a sense of entering something beautiful.  Rather,
the question to be answered for them is, "What does it all mean?"

Lisp code is entered into a data structure that lisp may operate on. 
Does this have any relation with the fact that one can create pleasing
textual representations of a program?
http://lambda.pentaside.org/article/symbols.html

Lisp supports other paradigms.  What are they; why does one wish to
use them since imperative programming is already fast?  Without
getting into a flamewar.  Are there "paradigms" (as Robert Floyd might
use the term) which overlap others well?

(In most languages, paradigms announce their arrival like a sitcom
character, pausing for applause and dominating the scene.  They don't
work as an ensemble, where they would simply pick up roles when
needed.)

What does it mean to believe that different parts of code can have
complementary knowledge on how to solve unusual situations, and
communication between those parts is fruitful?  Why is it important to
merge exceptions and errorcodes into something more general?  This
might be a software-crisis-type problem -- we do not know how to
handle unusual situations in most languages, and the complexity shape
becomes unnatural within an app.

Has anyone ever noticed that programmers are interested in automating
things, but their languages are mostly unprogrammable?  The way to
program these languages is outside the system, with an external tool
which takes the program as input.  Why haven't most programmers
automated the simple task of for(i=0;i<LENGTH;i++){} ?  Which they
will retype thousands of times.  Why are they told to believe it's
safer for them if only the language designer creates the various loops
as he thinks best?

I suspect it is easier teaching newbies than those with firm
preconceptions.  A newbie will shrug when told it's possible to grab
function definitions and replace them with others so one command may
make a function self-caching.  But someone with preconceptions might
even ask why someone should have that power, why it can't be done in a
"safer" way by defining a new function with a different name which
caches.
From: Dave Roberts
Subject: Re: Be afraid of XML
Date: 
Message-ID: <RCk5c.15936$Cb.330251@attbi_s51>
Tayssir John Gabbour wrote:

> (In most languages, paradigms announce their arrival like a sitcom
> character, pausing for applause and dominating the scene.  They don't
> work as an ensemble, where they would simply pick up roles when
> needed.)

To me, this is the single greatest advantage of Lisp. This means that with
Lisp I can use a variety of programming styles, each suited to the
particular portion of the larger problem I am trying to solve, without
having to force the language to do something unnatural. It all just blends,
without a complicated syntax. Simply put, that is a huge advantage.

-- 
Dave Roberts
·············@re-move.droberts.com
From: Christian Lynbech
Subject: Re: Be afraid of XML
Date: 
Message-ID: <87u10tuult.fsf@baguette.defun.dk>
>>>>> "Rayiner" == Rayiner Hashem <·······@mindspring.com> writes:

Rayiner> Lisp isn't rocket-science, its just different. And learning things
Rayiner> that are different is hard.

Expanding on my own theory, I do not think that Lisp is hard by virtue
of being different.

Learning a new language, any new language, is always hard. There is a
painfull period (for some shorter than others) between learning the
principles of the language, which you can dig out of a magazine
article over a weekend, and till you have acquired a working
vocabulary and can say what you want to say without spending more time
flipping through the manual than typing on the keyboard. 

That always take time and if you compare yourself in that period to
how you would have performed with a language in which you are fluent,
no matter what that was, you will seem to be drowning in
unproductivity.

The difference is how hard you want to learn the new language. If you
are checking it out just to see what the craze is all about, you are
bound to give up before reaching an appropriate understanding of the new
language. If you have seen the light and really Really REALLY want to
learn, for whatever reason, you will also keep flogging yourself until
you have acheived the necessary proficiency.


------------------------+-----------------------------------------------------
Christian Lynbech       | christian ··@ defun #\. dk
------------------------+-----------------------------------------------------
Hit the philistines three times over the head with the Elisp reference manual.
                                        - ·······@hal.com (Michael A. Petonic)
From: Stefan Scholl
Subject: Re: Be afraid of XML
Date: 
Message-ID: <7p96jeln9425$.dlg@parsec.no-spoon.de>
On 2004-03-13 07:30:38, Christian Lynbech wrote:

> The difference is how hard you want to learn the new language. If you
> are checking it out just to see what the craze is all about, you are
> bound to give up before reaching an appropriate understanding of the new
> language.

Not every language. Some are very familiar even when they have new
concepts. Ruby for example. <http://www.ruby-lang.org/en/>

It's easy to use Ruby. The language doesn't force a specific
paradigm. So you can use a style you are used to. Later on you learn
to do it the Ruby way.
From: Rayiner Hashem
Subject: Re: Be afraid of XML
Date: 
Message-ID: <a3995c0d.0403141216.b2700ea@posting.google.com>
> Learning a new language, any new language, is always hard. There is a
> painfull period (for some shorter than others) between learning the
> principles of the language, which you can dig out of a magazine
> article over a weekend, and till you have acquired a working
> vocabulary and can say what you want to say without spending more time
> flipping through the manual than typing on the keyboard. 
That's not really true. Read Eric. S. Raymond's paper about learning
Python. You can start writing good Python code (if not, perhaps,
idiomatic Python code) in an extremely short amount of time. That's
because Python fits peoples' preconceptions. Its rather imperative,
its got a pretty standard syntax, its got a pretty standard object
model, a pretty standard collection of classes, etc. In a way, it
encapsulates most of the concepts that people are already used to in
Java/C++, only in a cleaner package. Thus, when making a transition to
Python, most people need only get used to what is new in Python,
rather than having to challenge fundemental, pre-existing concepts.
Lisp, on the other hand, requires people to challenge what they
already know, and that is why its perceived to be harder.
From: Tim Bradshaw
Subject: Re: Be afraid of XML
Date: 
Message-ID: <fbc0f5d1.0403151147.25cc1c33@posting.google.com>
·······@mindspring.com (Rayiner Hashem) wrote in message news:<···························@posting.google.com>...

> That's not really true. Read Eric. S. Raymond's paper about learning
> Python. You can start writing good Python code (if not, perhaps,
> idiomatic Python code) in an extremely short amount of time. That's
> because Python fits peoples' preconceptions. Its rather imperative,
> its got a pretty standard syntax, its got a pretty standard object
> model, a pretty standard collection of classes, etc. In a way, it
> encapsulates most of the concepts that people are already used to in
> Java/C++, only in a cleaner package. Thus, when making a transition to
> Python, most people need only get used to what is new in Python,
> rather than having to challenge fundemental, pre-existing concepts.
> Lisp, on the other hand, requires people to challenge what they
> already know, and that is why its perceived to be harder.

Precisely.  I'm glad you made it clear that `standard' means `like
C++/Java', but that's exactly the point of python: it's really close
to Java, while being interactive and having a couple of nods towards
Lisp (restricted lambda, lists that, actually, aren't lisp lists at
all, &c).  So it's easy, where Lisp is hard.
From: Raymond Wiker
Subject: Re: Be afraid of XML
Date: 
Message-ID: <86d67ifoy7.fsf@raw.grenland.fast.no>
Espen Vestre <·····@*do-not-spam-me*.vestre.net> writes:

> ··········@tfeb.org (Tim Bradshaw) writes:
>
>> Interestingly the same is historically true for Lisp: because Lisp
>> implementations generally protect you against the low-level issues
>> which blight C/C++ systems, average programmers can get further.  And
>> so `lisp is big and slow'.
>
> Still, there seems to be a common conception that "lisp is rocket
> science", i.e. not possible to even learn for the foot soldier
> programmer. 

        Lisp isn't rocket science, otherwise NASA would have used it :-)

-- 
Raymond Wiker                        Mail:  ·············@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/
From: John Thingstad
Subject: Re: Be afraid of XML
Date: 
Message-ID: <opr4quk6w0xfnb1n@news.chello.no>
You think they don't!
Check out the deep space one error revovery system ;)

On Fri, 12 Mar 2004 09:29:36 +0100, Raymond Wiker <·············@fast.no> 
wrote:

> Espen Vestre <·····@*do-not-spam-me*.vestre.net> writes:
>
>> ··········@tfeb.org (Tim Bradshaw) writes:
>>
>>> Interestingly the same is historically true for Lisp: because Lisp
>>> implementations generally protect you against the low-level issues
>>> which blight C/C++ systems, average programmers can get further.  And
>>> so `lisp is big and slow'.
>>
>> Still, there seems to be a common conception that "lisp is rocket
>> science", i.e. not possible to even learn for the foot soldier
>> programmer.
>
>         Lisp isn't rocket science, otherwise NASA would have used it :-)
>



-- 
Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
From: David Steuber
Subject: The LOOP macro (was Re: Be afraid of XML)
Date: 
Message-ID: <m2znal71l6.fsf_-_@david-steuber.com>
Espen Vestre <·····@*do-not-spam-me*.vestre.net> writes:

> ··········@tfeb.org (Tim Bradshaw) writes:
> 
> > Interestingly the same is historically true for Lisp: because Lisp
> > implementations generally protect you against the low-level issues
> > which blight C/C++ systems, average programmers can get further.  And
> > so `lisp is big and slow'.
> 
> Still, there seems to be a common conception that "lisp is rocket
> science", i.e. not possible to even learn for the foot soldier
> programmer. 

The LOOP macro is beginning to make me think something along those
lines:

  http://clhs.lisp.se/Body/m_loop.htm

The modified BNF notation is not something I ever internalized.  The
pages on the LOOP facility have some examples but I haven't groked
the thing yet.  Sure, the simple form is, well, simple.  What I do
not yet "get" is all the ways I can combine clauses in the extended
form.

The C for loop is so much simpler for me to understand.

I'm not saying LOOP is bad.  I'm sure it has a lot of power and is
perhaps more expresive than DO.  It is still quite a heavy construct
though.

-- 
Those who do not remember the history of Lisp are doomed to repeat it,
badly.

> (dwim x)
NIL
From: Kenny Tilton
Subject: Re: The LOOP macro (was Re: Be afraid of XML)
Date: 
Message-ID: <Rbx4c.15967$c73.5466945@twister.nyc.rr.com>
David Steuber wrote:

> Espen Vestre <·····@*do-not-spam-me*.vestre.net> writes:
> 
> 
>>··········@tfeb.org (Tim Bradshaw) writes:
>>
>>
>>>Interestingly the same is historically true for Lisp: because Lisp
>>>implementations generally protect you against the low-level issues
>>>which blight C/C++ systems, average programmers can get further.  And
>>>so `lisp is big and slow'.
>>
>>Still, there seems to be a common conception that "lisp is rocket
>>science", i.e. not possible to even learn for the foot soldier
>>programmer. 
> 
> 
> The LOOP macro is beginning to make me think something along those
> lines:
> 
>   http://clhs.lisp.se/Body/m_loop.htm
> 
> The modified BNF notation is not something I ever internalized.  The
> pages on the LOOP facility have some examples but I haven't groked
> the thing yet.  Sure, the simple form is, well, simple.  What I do
> not yet "get" is all the ways I can combine clauses in the extended
> form.
> 
> The C for loop is so much simpler for me to understand.

<g>

> 
> I'm not saying LOOP is bad.

I did (say "Bad LOOP! Bad!"), for about eight years. Not enough 
parentheses, ie, ridiculous syntax. But then I read here that it was 
efficient, ie, it did things like push-push-nreverse that I really 
loathed coding all the time, and Peter Seibel invited me to try his 
chapter on Loop. That did the trick, after several earlier swipes at the 
doc had failed. He does not offer a tutorial so much as he just breaks 
down the myriad keywords into reasonable subcategories, and that is 
enough to make the beast approachable.

   I'm sure it has a lot of power and is
> perhaps more expresive than DO.  It is still quite a heavy construct
> though.

Check, check, and check.

kt

-- 
http://tilton-technology.com

Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film

Your Project Here! http://alu.cliki.net/Industry%20Application
From: Peter Seibel
Subject: Re: The LOOP macro (was Re: Be afraid of XML)
Date: 
Message-ID: <m37jxptfee.fsf@javamonkey.com>
Kenny Tilton <·······@nyc.rr.com> writes:

> I did (say "Bad LOOP! Bad!"), for about eight years. Not enough
> parentheses, ie, ridiculous syntax. But then I read here that it was
> efficient, ie, it did things like push-push-nreverse that I really
> loathed coding all the time, and Peter Seibel invited me to try his
> chapter on Loop. That did the trick, after several earlier swipes at
> the doc had failed. He does not offer a tutorial so much as he just
> breaks down the myriad keywords into reasonable subcategories, and
> that is enough to make the beast approachable.

In case the OP or anyone else is interested that chapter is still
available at:

  <http://www.gigamonkeys.com/book/appendix-loop-for-black-belts.html>

Ignore the first paragraph is it's a transition from somewhere that
doesn't exist anymore but the meat of the chapter is what you're
interested in. (Eventually this chapter will be grafted back into the
book proper.)

And as always, I'm interested in feedback on any of the chapters
marked "Ready for review" at:

  <http://www.gigamonkeys.com/book/>

-Peter

-- 
Peter Seibel                                      ·····@javamonkey.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp
From: szymon
Subject: Re: The LOOP macro (was Re: Be afraid of XML)
Date: 
Message-ID: <c2v3l5$ejo$1@nemesis.news.tpi.pl>
Peter Seibel wrote{in his book: 34. Appendix: LOOP for Black-Belts}:

--------------------

"... So

(loop for i upto 10 collect i)

collects the first ten integers but ..."

--------------------

ten integers??

CL-USER> (length (loop for i upto 10 collect i))
11

miss I smthing?


regards, szymon.
From: Rob Warnock
Subject: Re: The LOOP macro (was Re: Be afraid of XML)
Date: 
Message-ID: <YOCdnTFgR8mIiM7d3czS-g@speakeasy.net>
szymon  <······@dont.have.email> wrote:
+---------------
| Peter Seibel wrote{in his book: 34. Appendix: LOOP for Black-Belts}:
| >  (loop for i upto 10 collect i)
| >  collects the first ten integers but ..."
| 
| ten integers??
| CL-USER> (length (loop for i upto 10 collect i))
| 11
| 
| miss I smthing?
+---------------

Nope. It's a typo. If he really wants ten, it should say either this:

	(loop for i from 1 upto 10 collect i)	; 1..10

or this:

	(loop for i below 10 collect i)		; 0..9


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Paul F. Dietz
Subject: Re: The LOOP macro (was Re: Be afraid of XML)
Date: 
Message-ID: <HZWdnXndd4XJss7dRVn-ug@dls.net>
szymon wrote:

> (loop for i upto 10 collect i)
> 
> collects the first ten integers but ..."
> 
> --------------------
> 
> ten integers??
> 
> CL-USER> (length (loop for i upto 10 collect i))
> 11
> 
> miss I smthing?


It's an almost-canonical fencepost error!

"A fence 100 feet long has a post every 10 feet.  How many posts
does it have?"

	Paul
From: Wolfhard Buß
Subject: Re: The LOOP macro
Date: 
Message-ID: <m3oer0vo17.fsf@buss-14250.user.cis.dfn.de>
* szymon writes:

> Peter Seibel wrote{in his book: 34. Appendix: LOOP for Black-Belts}:
:
> ten integers??
>
> CL-USER> (length (loop for i upto 10 collect i))
> 11
>
> miss I smthing?

No.

-- 
"Hurry if you still want to see something. Everything is vanishing."
                                       --  Paul C�zanne (1839-1906)
From: Peter Seibel
Subject: Re: The LOOP macro (was Re: Be afraid of XML)
Date: 
Message-ID: <m33c8cu1de.fsf@javamonkey.com>
szymon <······@dont.have.email> writes:

> Peter Seibel wrote{in his book: 34. Appendix: LOOP for Black-Belts}:
>
> --------------------
>
> "... So
>
> (loop for i upto 10 collect i)
>
> collects the first ten integers but ..."
>
> --------------------
>
> ten integers??
>
> CL-USER> (length (loop for i upto 10 collect i))
> 11
>
> miss I smthing?

Nope. That should be "below" not "upto". Sorry about that.

-Peter

-- 
Peter Seibel                                      ·····@javamonkey.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp
From: szymon
Subject: Re: The LOOP macro (was Re: Be afraid of XML)
Date: 
Message-ID: <c2vn00$nak$1@atlantis.news.tpi.pl>
Peter Seibel wrote:

> Nope. That should be "below" not "upto". Sorry about that.

No problem :), thx for replies.

---------------

BDW:

One sentence about type declarations (in your book, in black belt
appendix too) in LOOP, please.

regards, szymon.
From: Joe Marshall
Subject: Re: The LOOP macro
Date: 
Message-ID: <brn0ovkz.fsf@comcast.net>
Peter Seibel <·····@javamonkey.com> writes:

> szymon <······@dont.have.email> writes:
>>
>> ten integers??
>>
>> CL-USER> (length (loop for i upto 10 collect i))
>> 11
>>
>> miss I smthing?
>
> Nope. That should be "below" not "upto". Sorry about that.

I once worked on some lisp code that everywhere had this `interesting'
idiom:

(loop for i upto (1- whatever) ...)


-- 
~jrm
From: Ng Pheng Siong
Subject: Re: The LOOP macro (was Re: Be afraid of XML)
Date: 
Message-ID: <c334h1$jb2$1@mawar.singnet.com.sg>
According to szymon  <······@dont.have.email>:
> Peter Seibel wrote{in his book: 34. Appendix: LOOP for Black-Belts}:
> (loop for i upto 10 collect i)
> collects the first ten integers but ..."
> 
> ten integers??
> 
> CL-USER> (length (loop for i upto 10 collect i))
> 11
> 
> miss I smthing?

The NIL that terminates the list.

;-)


-- 
Ng Pheng Siong <····@netmemetic.com> 

http://firewall.rulemaker.net -+- Firewall Change Management & Version Control
http://sandbox.rulemaker.net/ngps -+- Open Source Python Crypto & SSL
From: Edi Weitz
Subject: Re: The LOOP macro
Date: 
Message-ID: <m3r7vtrig0.fsf@bird.agharta.de>
On Mon, 15 Mar 2004 19:47:38 +0100, Klaus Uhl <····@u-h-l.de> wrote:

> ····@netmemetic.com (Ng Pheng Siong) writes:
>
>> The NIL that terminates the list.
>
> No. The terminating NIL will never be counted by LENGTH.

Please read the message you replied to again and ask yourself what the
mysterious line

  ;-)

that you failed to quote might mean. Here's a hint:

  <http://www.pagetutor.com/hosted_sample/glossary.html#Smiley>

Edi.
From: szymon
Subject: :)
Date: 
Message-ID: <c36bha$mak$3@korweta.task.gda.pl>
Ng Pheng Siong wrote:
> According to szymon  <······@dont.have.email>:
> [blah, blah]
> 
> 
> The NIL that terminates the list.
> 
> ;-)
> 
> 

; newbie way to build a dot-list :] i (know about `list*')

[1]>  (prog1 #1='(1 2 3) (rplacd (last #1#) 'end))

(1 2 3 . END)

[2]> (list-length *)

*** - LIST-LENGTH: A true list must not end with END
Break 1 [3]> :q
                                             ;)

regards, szymon.
From: Rob Warnock
Subject: Re: :)
Date: 
Message-ID: <t5WcnfBOQ9yLucrd3czS-g@speakeasy.net>
szymon  <······@dev.null> wrote:
+---------------
| ; newbie way to build a dot-list :] i (know about `list*')
| [1]>  (prog1 #1='(1 2 3) (rplacd (last #1#) 'end))
| (1 2 3 . END)
+---------------

Newbie might find it helpful [as part of the path to becoming non-newbie]
to read the CLHS on the prohibitions against modifying literal program data,
and then perhaps write it this way:

   > (let ((x (list 1 2 3)))
       (rplacd (last x) 'end)
       x)

   (1 2 3 . END)
   >


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: David Steuber
Subject: Re: The LOOP macro (was Re: Be afraid of XML)
Date: 
Message-ID: <m27jxo74gu.fsf@david-steuber.com>
Peter Seibel <·····@javamonkey.com> writes:

> In case the OP or anyone else is interested that chapter is still
> available at:
> 
>   <http://www.gigamonkeys.com/book/appendix-loop-for-black-belts.html>

Thanks.  I'll look at this.

In principle, the CLHS contains all that is needed.  However, I think
I need someone to explain this to me the way an Englishman explains
something to a foreigner who does not speak English.  In other words,
speak loudly and slowly. ;-)

The problem with a programmable programming language is that it can
contain other programming languages in it.  LOOP.  FORMAT.  Does the
list go on?

-- 
Those who do not remember the history of Lisp are doomed to repeat it,
badly.

> (dwim x)
NIL
From: Kenny Tilton
Subject: Re: The LOOP macro (was Re: Be afraid of XML)
Date: 
Message-ID: <Z0P4c.18034$tP6.5609412@twister.nyc.rr.com>
David Steuber wrote:

> The problem with a programmable programming language is that it can
> contain other programming languages in it.  LOOP.  FORMAT.  Does the
> list go on?

There is no need to learn loop or the intricacies of format. I still do 
not know fancy format tricks. I admire your ambitiousness, but you might 
consider pacing yourself a little. Lisp is like skiing: easy to learn, 
hard to master.

kt

-- 
http://tilton-technology.com

Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film

Your Project Here! http://alu.cliki.net/Industry%20Application
From: Barry Margolin
Subject: Re: The LOOP macro (was Re: Be afraid of XML)
Date: 
Message-ID: <barmar-506FAB.22192213032004@comcast.ash.giganews.com>
In article <·······················@twister.nyc.rr.com>,
 Kenny Tilton <·······@nyc.rr.com> wrote:

> David Steuber wrote:
> 
> > The problem with a programmable programming language is that it can
> > contain other programming languages in it.  LOOP.  FORMAT.  Does the
> > list go on?
> 
> There is no need to learn loop or the intricacies of format. I still do 
> not know fancy format tricks. I admire your ambitiousness, but you might 
> consider pacing yourself a little. Lisp is like skiing: easy to learn, 
> hard to master.

I agree.  If it's not completely obvious how two LOOP clauses will 
interact, I avoid using LOOP entirely or don't use one of the clauses.  
LOOP and FORMAT are great for the straightforward stuff, and the fancy 
aspects can be great in some situations, but Lisp provides other ways to 
accomplish the same thing that can be more appropriate than complex 
combinations of these features.

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
From: David Steuber
Subject: Re: The LOOP macro (was Re: Be afraid of XML)
Date: 
Message-ID: <m28yi35z2y.fsf@david-steuber.com>
Kenny Tilton <·······@nyc.rr.com> writes:

> There is no need to learn loop or the intricacies of format. I still
> do not know fancy format tricks. I admire your ambitiousness, but you
> might consider pacing yourself a little. Lisp is like skiing: easy to
> learn, hard to master.

Well, I've got the face plant pretty much mastered.  Now I have to
watch out for the trees.

-- 
Those who do not remember the history of Lisp are doomed to repeat it,
badly.

> (dwim x)
NIL
From: rmagere
Subject: Re: The LOOP macro (was Re: Be afraid of XML)
Date: 
Message-ID: <c3s0gm$s8d$1@news.ox.ac.uk>
Peter Seibel wrote:
> And as always, I'm interested in feedback on any of the chapters
> marked "Ready for review" at:

I am really looking forward to see your chapters dealing with mp3 files.
[well this is some sort of feedback too.]
From: Wolfhard Buß
Subject: Re: The LOOP macro
Date: 
Message-ID: <m3vfl9uk19.fsf@buss-14250.user.cis.dfn.de>
* Kenny Tilton writes:

> I did (say "Bad LOOP! Bad!"), for about eight years. Not enough
> parentheses, ie, ridiculous syntax. But then I read here that it was
> efficient, ie, it did things like push-push-nreverse [...]

The idiom make-queue enqueue queue-list is more efficient than the
push nreverse idiom.

Lispniks suffering from lack of parenthesis in loop might look at
Johnathan Amsterdam's iterate. 

-- 
"Hurry if you still want to see something. Everything is vanishing."
                                       --  Paul C�zanne (1839-1906)
From: Joe Marshall
Subject: Re: The LOOP macro
Date: 
Message-ID: <k71opwl2.fsf@comcast.net>
·····@gmx.net (Wolfhard Bu�) writes:

> * Kenny Tilton writes:
>
>> I did (say "Bad LOOP! Bad!"), for about eight years. Not enough
>> parentheses, ie, ridiculous syntax. But then I read here that it was
>> efficient, ie, it did things like push-push-nreverse [...]
>
> The idiom make-queue enqueue queue-list is more efficient than the
> push nreverse idiom.

Not necessarily.  I believe Richard Waters did some empirical
measurements that showed that the difference is negligible.

-- 
~jrm
From: Nils Gösche
Subject: Re: The LOOP macro
Date: 
Message-ID: <lyu10syay3.fsf@cartan.de>
Joe Marshall <·············@comcast.net> writes:

> ·····@gmx.net (Wolfhard Bu�) writes:
> 
> > The idiom make-queue enqueue queue-list is more efficient than the
> > push nreverse idiom.
> 
> Not necessarily.  I believe Richard Waters did some empirical
> measurements that showed that the difference is negligible.

He wrote a very nice paper about it:

 http://www.merl.com/papers/TR93-17/

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

PGP key ID 0x0655CFA0
From: Rob Warnock
Subject: Re: The LOOP macro (was Re: Be afraid of XML)
Date: 
Message-ID: <L-CdnSfcbLu3kM7d3czS-g@speakeasy.net>
David Steuber  <·············@verizon.net> wrote:
+---------------
| The pages on the LOOP facility have some examples but I haven't groked
| the thing yet.  Sure, the simple form is, well, simple.  What I do not
| yet "get" is all the ways I can combine clauses in the extended form.
+---------------

I am, I like to think, by now reasonably comfortable with many of the
idioms of LOOP, e.g., the extremely useful destructuring of list items
into loop variables, and when you want to do that with IN versus ON,
and I tend to write fairly complex LOOPs with great success. Yet I still
get surprised occasionally when I think I'm doing "the right thing" and
it doesn't work.

For example, last night I was reading the NIST page on their Internet Time
Service[1], so just for fun I whipped together a small CMUCL script to:

1. print the local time,
2. grab the time from a random one of the NIST servers, and
3. print the local time again.

Here we see that local time is two seconds slow (oops!):

    % date-nist
    Sat Mar 13 04:58:45 2004   Local time
    Sat Mar 13 04:58:47 2004   nist1.datum.com
    Sat Mar 13 04:58:45 2004   Local time
    %

But my first cut at it contained the following -- note the AND:

    (defun fetch-time/rfc868 (host)
      (let* ((fd (connect-to-inet-socket host 37))
	     (stream (system:make-fd-stream fd
		      :element-type '(unsigned-byte 8))))
	(with-open-stream (s stream)
	  (loop for i below 4
		AND time = (read-byte s) then (+ (read-byte s) (* time 256))
	    finally (return time)))))

which when run fails as follows:

    > (fetch-time/rfc868 "time-c.timefreq.bldrdoc.gov")
    End-of-File on #<Stream for descriptor 6>
    Restarts:
      0: [ABORT] Return to Top-Level.
    ...

Replacing the AND with another FOR fixes the problem:

    > (defun fetch-time/rfc868 (host)
	(let* ((fd (connect-to-inet-socket host 37))
	       (stream (system:make-fd-stream fd
			:element-type '(unsigned-byte 8))))
	  (with-open-stream (s stream)
	    (loop for i below 4
		  AND time = (read-byte s) then (+ (read-byte s) (* time 256))
	      finally (return time)))))

    FETCH-TIME/RFC868
    > (fetch-time/rfc868 "time-c.timefreq.bldrdoc.gov")

    3288171947
    >

Now at first blush, it seemed that in this particular instance the
choice of AND (parallel binding) versus FOR (sequential binding)
*shouldn't* have made a difference, since neither term uses the
other's variable... but it did. Wow, magic. (*Whoo-EEE-ooo.*)

But upon further reflection, I figured out that it was doing exactly
as it's supposed to: When you have parallel variable bindings/steppings
(using AND), any loop termination tests are done *after* all of the
parallel variables have been stepped, whereas with sequential binding (FOR),
each termination test is done in order, and a later (inner) variable
isn't stepped (or tested) at all if the LOOP terminates due to an outer
variable limit. That is:

    > (loop for i below 4
            and j below 4
       finally (return (list i j)))

    (4 4)
    > (loop for i below 4
            for j below 4
       finally (return (list i j)))

    (4 3)
    >

Oh. Duh.

LOOP is definitely one of the parts of CL where you learn something new
every day...  ;-}  ;-}


-Rob

[1] <URL:http://www.boulder.nist.gov/timefreq/service/its.htm>

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Pascal Bourguignon
Subject: Re: The LOOP macro (was Re: Be afraid of XML)
Date: 
Message-ID: <87wu5ovcdv.fsf@thalassa.informatimago.com>
····@rpw3.org (Rob Warnock) writes:
>     > (loop for i below 4
>             for j below 4
>        finally (return (list i j)))
> 
>     (4 3)
>     >
> 
> Oh. Duh.
> 
> LOOP is definitely one of the parts of CL where you learn something new
> every day...  ;-}  ;-}

Actually, the  variables i and j  could very well not  be available in
the finally clause.   That's the reason why I  don't use extended loop
if I can help.


Note how clisp returns a conforming but differnet result too:

[193]> (loop for i below 4
             for j below 4
             finally (return (list i j)))
(4 4)

You should define:

  (defmacro lose-all-hope-ye-who-enter-here (&rest args) `(loop ,@args))


-- 
__Pascal_Bourguignon__                     http://www.informatimago.com/
There is no worse tyranny than to force a man to pay for what he doesn't
want merely because you think it would be good for him.--Robert Heinlein
http://www.theadvocates.org/
From: Justin Dubs
Subject: Re: The LOOP macro (was Re: Be afraid of XML)
Date: 
Message-ID: <2e262238.0403132131.69c397e9@posting.google.com>
Pascal Bourguignon <····@thalassa.informatimago.com> wrote in message news:<··············@thalassa.informatimago.com>...
> Actually, the  variables i and j  could very well not  be available in
> the finally clause.   That's the reason why I  don't use extended loop
> if I can help.

I disagree, but maybe my reading of the spec is wrong.

Section 6.1.1.4:

"A loop macro form expands into a form containing ONE OR MORE BINDINGS
FORMS (that establish bindings of loop variables) and a BLOCK AND A
TAGBODY (that express a looping control structure). The VARIABLES
ESTABLISHED IN LOOP ARE BOUND AS IF BY LET or lambda."

followed by:

"After the form is expanded, it consists of THREE BASIC PARTS IN THE
TAGBODY: the loop prologue, the loop body, and the LOOP EPILOGUE."

followed by:

"The LOOP EPILOGUE CONTAINS forms that are executed after iteration
terminates, such as FINALLY CLAUSES, if any, along with any implicit
return value from an accumulation clause or an termination-test
clause."

This implies to me that it must expand into something of a form
similar to:

(let (... bindings go here ...)
  (block ...
    (tagbody ... prologue ...
             ... body ...
             ... epilogue ...)))

There could, of course, potentially be many nested lets or some other
kind of binding form in place of it.

But, it seems clear the bindings have to be done outside the tagbody,
as they have to be visible from both the prologue and the body.  And
as that tagbody must also contain the epilogue... I'm not sure how the
bindings wouldn't be visible from it.

If I'm missing something obvious, please be patient.  I'm rather a
newbie to trying to interpret the hyperspec.  :-)

>   (defmacro lose-all-hope-ye-who-enter-here (&rest args) `(loop ,@args))

ouch.  ;-)

Justin Dubs
From: Pascal Bourguignon
Subject: Re: The LOOP macro (was Re: Be afraid of XML)
Date: 
Message-ID: <87r7vv3ixl.fsf@thalassa.informatimago.com>
······@eos.ncsu.edu (Justin Dubs) writes:

> Pascal Bourguignon <····@thalassa.informatimago.com> wrote in message news:<··············@thalassa.informatimago.com>...
> > Actually, the  variables i and j  could very well not  be available in
> > the finally clause.   That's the reason why I  don't use extended loop
> > if I can help.
> 
> I disagree, but maybe my reading of the spec is wrong.
> 
> Section 6.1.1.4:
> 
> "A loop macro form expands into a form containing ONE OR MORE BINDINGS
> FORMS (that establish bindings of loop variables) and a BLOCK AND A
> TAGBODY (that express a looping control structure). The VARIABLES
> ESTABLISHED IN LOOP ARE BOUND AS IF BY LET or lambda."
> 
> followed by:
> 
> "After the form is expanded, it consists of THREE BASIC PARTS IN THE
> TAGBODY: the loop prologue, the loop body, and the LOOP EPILOGUE."
> 
> followed by:
> 
> "The LOOP EPILOGUE CONTAINS forms that are executed after iteration
> terminates, such as FINALLY CLAUSES, if any, along with any implicit
> return value from an accumulation clause or an termination-test
> clause."
> 
> This implies to me that it must expand into something of a form
> similar to:
> 
> (let (... bindings go here ...)
>   (block ...
>     (tagbody ... prologue ...
>              ... body ...
>              ... epilogue ...)))
> 
> There could, of course, potentially be many nested lets or some other
> kind of binding form in place of it.
> 
> But, it seems clear the bindings have to be done outside the tagbody,
> as they have to be visible from both the prologue and the body.  And
> as that tagbody must also contain the epilogue... I'm not sure how the
> bindings wouldn't be visible from it.
> 
> If I'm missing something obvious, please be patient.  I'm rather a
> newbie to trying to interpret the hyperspec.  :-)

Yep. An implementation  may want to guarantee that  loop variables are
not  modified  by the  body  of  the loop  (to  ensure  the number  of
iteration  is  correct,  or  because  it  unroll  the  iterations  and
dispatches  them  to  several  threads/processors).   That's  why  the
binding could  be done  once per iteration.   Note that  the paragraph
about the loop epilogue only  speaks about the accumulation clauses or
termination  test, and  not about  the iteration  variables,  and only
about the  _result_ of these clauses,  not about how  their values are
obtained.  The fact that you may  refer to an iteration variable in an
accumulation clause or in the  termination test does not mean that you
can still refer it in the epilogue (finally clauses).


In  any case,  current  implementations  differ on  the  state of  the
iteration  variables in  the finally  clause, so  you cannot  use them
portably.

-- 
__Pascal_Bourguignon__                     http://www.informatimago.com/
There is no worse tyranny than to force a man to pay for what he doesn't
want merely because you think it would be good for him.--Robert Heinlein
http://www.theadvocates.org/
From: Justin Dubs
Subject: Re: The LOOP macro (was Re: Be afraid of XML)
Date: 
Message-ID: <2e262238.0403151547.7d98875f@posting.google.com>
Pascal Bourguignon <····@thalassa.informatimago.com> wrote in message news:<··············@thalassa.informatimago.com>...
> ······@eos.ncsu.edu (Justin Dubs) writes:
> 
> > Pascal Bourguignon <····@thalassa.informatimago.com> wrote in message news:<··············@thalassa.informatimago.com>...
> > > Actually, the  variables i and j  could very well not  be available in
> > > the finally clause.   That's the reason why I  don't use extended loop
> > > if I can help.
> > 
> > I disagree, but maybe my reading of the spec is wrong.
> > 
> > Section 6.1.1.4:
> > 
> > "A loop macro form expands into a form containing ONE OR MORE BINDINGS
> > FORMS (that establish bindings of loop variables) and a BLOCK AND A
> > TAGBODY (that express a looping control structure). The VARIABLES
> > ESTABLISHED IN LOOP ARE BOUND AS IF BY LET or lambda."
> > 
> > followed by:
> > 
> > "After the form is expanded, it consists of THREE BASIC PARTS IN THE
> > TAGBODY: the loop prologue, the loop body, and the LOOP EPILOGUE."
> > 
> > followed by:
> > 
> > "The LOOP EPILOGUE CONTAINS forms that are executed after iteration
> > terminates, such as FINALLY CLAUSES, if any, along with any implicit
> > return value from an accumulation clause or an termination-test
> > clause."
> > 
> > This implies to me that it must expand into something of a form
> > similar to:
> > 
> > (let (... bindings go here ...)
> >   (block ...
> >     (tagbody ... prologue ...
> >              ... body ...
> >              ... epilogue ...)))
> > 
> > There could, of course, potentially be many nested lets or some other
> > kind of binding form in place of it.
> > 
> > But, it seems clear the bindings have to be done outside the tagbody,
> > as they have to be visible from both the prologue and the body.  And
> > as that tagbody must also contain the epilogue... I'm not sure how the
> > bindings wouldn't be visible from it.
> > 
> > If I'm missing something obvious, please be patient.  I'm rather a
> > newbie to trying to interpret the hyperspec.  :-)
> 
> Yep. An implementation  may want to guarantee that  loop variables are
> not  modified  by the  body  of  the loop  (to  ensure  the number  of
> iteration  is  correct,  or  because  it  unroll  the  iterations  and
> dispatches  them  to  several  threads/processors).   That's  why  the
> binding could  be done  once per iteration.   Note that  the paragraph
> about the loop epilogue only  speaks about the accumulation clauses or
> termination  test, and  not about  the iteration  variables,  and only
> about the  _result_ of these clauses,  not about how  their values are
> obtained.  The fact that you may  refer to an iteration variable in an
> accumulation clause or in the  termination test does not mean that you
> can still refer it in the epilogue (finally clauses).
> 
> 
> In  any case,  current  implementations  differ on  the  state of  the
> iteration  variables in  the finally  clause, so  you cannot  use them
> portably.

I see what you mean.  Thanks for explaining it.

Justin Dubs
From: John Thingstad
Subject: Re: The LOOP macro (was Re: Be afraid of XML)
Date: 
Message-ID: <opr4y3yjpmxfnb1n@news.chello.no>
On 15 Mar 2004 15:47:32 -0800, Justin Dubs <······@eos.ncsu.edu> wrote:

I would like to point out that there is only one implementation of loop
,the one by MIT, used by (as far as I can see) all implementations.

>> In  any case,  current  implementations  differ on  the  state of  the
>> iteration  variables in  the finally  clause, so  you cannot  use them
>> portably.
>
> I see what you mean.  Thanks for explaining it.
>
> Justin Dubs



-- 
Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
From: Carl Shapiro
Subject: Re: The LOOP macro (was Re: Be afraid of XML)
Date: 
Message-ID: <ouyvfl4z933.fsf@panix3.panix.com>
John Thingstad <··············@chello.no> writes:

> On 15 Mar 2004 15:47:32 -0800, Justin Dubs <······@eos.ncsu.edu> wrote:
> 
> I would like to point out that there is only one implementation of loop
> ,the one by MIT, used by (as far as I can see) all implementations.

This is completely untrue.  While the so called "MIT LOOP" may have
the most extant derivatives (including two from Symbolics), it is not,
by far, the only implementation of the extended loop macro.

Non-believers may wish to consult the CMU AI Repository for a few
"open source" examples:

http://www-cgi.cs.cmu.edu/afs/cs.cmu.edu/project/ai-repository/ai/lang/lisp/code/iter/loop/    
From: Ivan Boldyrev
Subject: Re: The LOOP macro
Date: 
Message-ID: <ga3li1x2th.ln2@ibhome.cgitftp.uiggm.nsc.ru>
On 8686 day of my life John Thingstad wrote:
> On 15 Mar 2004 15:47:32 -0800, Justin Dubs <······@eos.ncsu.edu> wrote:
>
> I would like to point out that there is only one implementation of
> loop, the one by MIT, used by (as far as I can see) all
> implementations.

Doesn't GNU CLisp use diffrent implementation?  Someone resently
posted loop construct which returned different result in CLisp and
some other lisp...

-- 
Ivan Boldyrev

       Assembly of a Japanese bicycle requires greatest peace of spirit.
From: Peter Seibel
Subject: Re: The LOOP macro (was Re: Be afraid of XML)
Date: 
Message-ID: <m3hdwss9sz.fsf@javamonkey.com>
Pascal Bourguignon <····@thalassa.informatimago.com> writes:

> ····@rpw3.org (Rob Warnock) writes:
>>     > (loop for i below 4
>>             for j below 4
>>        finally (return (list i j)))
>> 
>>     (4 3)
>>     >
>> 
>> Oh. Duh.
>> 
>> LOOP is definitely one of the parts of CL where you learn something new
>> every day...  ;-}  ;-}
>
> Actually, the variables i and j could very well not be available in
> the finally clause.

How do you figure that? Why would the finally clause be any different
from any of the other clauses?

> Note how clisp returns a conforming but differnet result too:
>
> [193]> (loop for i below 4
>              for j below 4
>              finally (return (list i j)))
> (4 4)

Hmmm. I'm not sure I buy that that's conforming. Given that LOOP
provides AND for specifying parallel stepping, why should CLISP's
behavior here be considered correct?

-Peter

-- 
Peter Seibel                                      ·····@javamonkey.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp
From: Pascal Bourguignon
Subject: Re: The LOOP macro (was Re: Be afraid of XML)
Date: 
Message-ID: <87ekrwuzfa.fsf@thalassa.informatimago.com>
Peter Seibel <·····@javamonkey.com> writes:

> Pascal Bourguignon <····@thalassa.informatimago.com> writes:
> 
> > ····@rpw3.org (Rob Warnock) writes:
> >>     > (loop for i below 4
> >>             for j below 4
> >>        finally (return (list i j)))
> >> 
> >>     (4 3)
> >>     >
> >> 
> >> Oh. Duh.
> >> 
> >> LOOP is definitely one of the parts of CL where you learn something new
> >> every day...  ;-}  ;-}
> >
> > Actually, the variables i and j could very well not be available in
> > the finally clause.
> 
> How do you figure that? Why would the finally clause be any different
> from any of the other clauses?
> 
> > Note how clisp returns a conforming but differnet result too:
> >
> > [193]> (loop for i below 4
> >              for j below 4
> >              finally (return (list i j)))
> > (4 4)
> 
> Hmmm. I'm not sure I buy that that's conforming. Given that LOOP
> provides AND for specifying parallel stepping, why should CLISP's
> behavior here be considered correct?

Because the loop variables don't have to be available in the finally clause!
If they're available, their value is unspecified.

For example, the above loop could be implemented as:

    (do ((#g001 0 (1+ #g001))
         (#g002 0 (1+ #g002)))
        ((or (>= #g001 4) (>= #g002 4))
         (return (list i j))) ;; error, i and j are not bound
                              ;; or worse, return i and j from an outside
                              ;; lexical scope.
      (let ((i #g001) (j #g002))
        #| no body using i and j |# ))


-- 
__Pascal_Bourguignon__                     http://www.informatimago.com/
There is no worse tyranny than to force a man to pay for what he doesn't
want merely because you think it would be good for him.--Robert Heinlein
http://www.theadvocates.org/
From: Peter Seibel
Subject: Re: The LOOP macro (was Re: Be afraid of XML)
Date: 
Message-ID: <m3ad2ks42a.fsf@javamonkey.com>
Pascal Bourguignon <····@thalassa.informatimago.com> writes:

> Peter Seibel <·····@javamonkey.com> writes:
>
>> Pascal Bourguignon <····@thalassa.informatimago.com> writes:
>> 
>> > ····@rpw3.org (Rob Warnock) writes:
>> >>     > (loop for i below 4
>> >>             for j below 4
>> >>        finally (return (list i j)))
>> >> 
>> >>     (4 3)
>> >>     >
>> >> 
>> >> Oh. Duh.
>> >> 
>> >> LOOP is definitely one of the parts of CL where you learn something new
>> >> every day...  ;-}  ;-}
>> >
>> > Actually, the variables i and j could very well not be available in
>> > the finally clause.
>> 
>> How do you figure that? Why would the finally clause be any different
>> from any of the other clauses?
>> 
>> > Note how clisp returns a conforming but differnet result too:
>> >
>> > [193]> (loop for i below 4
>> >              for j below 4
>> >              finally (return (list i j)))
>> > (4 4)
>> 
>> Hmmm. I'm not sure I buy that that's conforming. Given that LOOP
>> provides AND for specifying parallel stepping, why should CLISP's
>> behavior here be considered correct?
>
> Because the loop variables don't have to be available in the finally
> clause! If they're available, their value is unspecified.

And why do you say they don't have to be available in the finally
clause? Granted I can't see anything in the spec that *specifically*
says they have to be but I can't see anything that specifically says
they have to available *anywhere*. Why should the finally clause be
any different from any other LOOP clause?

-Peter

-- 
Peter Seibel                                      ·····@javamonkey.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp
From: james anderson
Subject: Re: The LOOP macro (was Re: Be afraid of XML)
Date: 
Message-ID: <40544567.837F76AE@setf.de>
Peter Seibel wrote:
> 
> Pascal Bourguignon <····@thalassa.informatimago.com> writes:
> 
> ...
> >
> > Because the loop variables don't have to be available in the finally
> > clause! If they're available, their value is unspecified.
> 
> And why do you say they don't have to be available in the finally
> clause? Granted I can't see anything in the spec that *specifically*
> says they have to be but I can't see anything that specifically says
> they have to available *anywhere*. Why should the finally clause be
> any different from any other LOOP clause?

for what it's worth, while the discussion of local variable initialization includes

"[] local variables exist until loop iteration terminates, at which point they
cease to exist. Implicit variables are also established by iteration control
clauses and the into preposition of accumulation clauses."

which one might take to imply that their scope does not include the epilogue,
on the other hand, the description of local accumulators includes 

"If var is not supplied, it is equivalent to supplying an internal name for
var and returning its value in a finally clause. The var argument is bound as
if by the construct with."

and there are numerous examples which return a supplied accumulator from a
finally clause, which would imply that the scope of a binding which is
introduced must include the epilogue. at least with respect to "with".

 
...
From: Rob Warnock
Subject: Re: The LOOP macro (was Re: Be afraid of XML)
Date: 
Message-ID: <hSGdnZMZas1J-snd3czS-w@speakeasy.net>
Pascal Bourguignon  <····@thalassa.informatimago.com> wrote:
+---------------
| Because the loop variables don't have to be available in the finally clause!
| If they're available, their value is unspecified.
+---------------

Please cite some supporting evidence from the CLHS for this bizarre claim.
Note that CLHS "6.1.2.1 Iteration Control" says simply:

	All variables are initialized in the loop prologue. A variable
	binding has lexical scope unless it is proclaimed special; thus,
	by default, the variable can be accessed only by forms that lie
	textually within the loop. Stepping assignments are made in the
	loop body before any other forms are evaluated in the body. 

The FINALLY clause is definitely "textually within the loop", so it must
have access to all of the iteration control variables defined therein.


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Rob Warnock
Subject: Re: The LOOP macro (was Re: Be afraid of XML)
Date: 
Message-ID: <wiCdnWFv05gO6Mnd3czS-w@speakeasy.net>
I just wrote:
+---------------
| Pascal Bourguignon  <····@thalassa.informatimago.com> wrote:
| +---------------
| | Because the loop variables don't have to be available in the finally
| | clause! If they're available, their value is unspecified.
| +---------------
...
| The FINALLY clause is definitely "textually within the loop", so it must
| have access to all of the iteration control variables defined therein.
+---------------

Let me be a little more clear about what I'm suggesting/arguing. There are
actually two parts to this issue:

1. Whether the FINALLY clause is within the scope of the iteration variables.
   On this sub-point, I will continue to claim that it must be. And in
   fact your CLISP "counterexample" is no counterexample at all, since
   both *were* still visible!!

2. Whether the specific iteration variable which caused the loop to
   terminate (and any other variables in the *same* FOR...[AND...]*
   group) has been incremented past the termination condition or not
   when viewed by the FINALLY clause. On this sub-point I am less clear,
   and therefore will not argue particularly strongly one way or the
   other (though I confess a bias towards "stepping just before testing",
   see below). The reason for this uncertainty is an apparent conflict
   between the text in CLHS "6.1.2.1 Iteration Control" [emphasis added]:

	The for and as clauses iterate by using one or more local loop
	variables that are initialized to some value and that can be
	modified or STEPPED[1] AFTER EACH ITERATION. For these clauses,
	iteration terminates when a local variable reaches some supplied
	value or when some other loop clause terminates iteration. AT EACH
	ITERATION, VARIABLES CAN BE STEPPED[1] by an increment or a decrement
	or can be assigned a new value by the evaluation of a form).

   which implies that stepping occurs *after* each iteration [although
   the phrase "AT each iteration" raises some uncertainty], while CLHS
   "6.1.2.1.1 The for-as-arithmetic subclause" says:

	The variable var is BOUND to the value of form1 IN THE FIRST
	ITERATION AND IS STEPPED[1] by the value of form3 IN EACH SUCCEEDING
	ITERATION, or by 1 if form3 is not provided.

   That is, "in" could be anytime during an iteration outside of the body
   forms, which seems to leave open the possibility that stepping occurs
   before the *next* iteration if the termination condition is not met,
   and is not done if the termination condition is is met. Thus it is
   perhaps not totally unreasonable to allow the specific iteration
   variable which caused the loop to terminate (and its AND brethren)
   to *not* have been stepped when the loop terminates.

But whatever the case with the specific iteration variable which caused
the loop to terminate, the iteration variables which occur in *later* FORs
(sequential binding/stepping) must still contain the values they were last
stepped to (during the previous iteration) when the FINALLY is run. That is,
I concede that it is possible for the following form:

	(loop for i below 4
	      for j below 4
	  finally (return (list i j)))

to return either (4 3) or (3 3) [the latter only if the termination test
were smart enough to see that stepping "i" would take it to 4 or above], but
*not* (4 4)!! Therefore I would claim that CLISP is incorrect in this case.


-Rob

p.s. The form:

	(loop for i below 4
	      and j below 4
	  finally (return (list i j)))

could thus conceivably return either (3 3) or (4 4) [both CLISP & CMUCL
give the latter], but I believe that (4 3) and (3 4) should be forbidden
here. That is, in "parallel" steppings with AND, either all variables
in the FOR[AND]* set should be stepped before the final termination test
or none should. IMHO.

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Pascal Bourguignon
Subject: Re: The LOOP macro (was Re: Be afraid of XML)
Date: 
Message-ID: <87u10r46xz.fsf@thalassa.informatimago.com>
····@rpw3.org (Rob Warnock) writes:
> Let me be a little more clear about what I'm suggesting/arguing. There are
> actually two parts to this issue:
> 
> 1. Whether the FINALLY clause is within the scope of the iteration variables.
>    On this sub-point, I will continue to claim that it must be. And in
>    fact your CLISP "counterexample" is no counterexample at all, since
>    both *were* still visible!!
> 
> 2. Whether the specific iteration variable which caused the loop to
>    terminate (and any other variables in the *same* FOR...[AND...]*
>    group) has been incremented past the termination condition or not
>    when viewed by the FINALLY clause. On this sub-point I am less clear,
>    and therefore will not argue particularly strongly one way or the
>    other (though I confess a bias towards "stepping just before testing",
>    see below). The reason for this uncertainty is an apparent conflict
>    between the text in CLHS "6.1.2.1 Iteration Control" [emphasis added]:

In any  case, my point  is that the  standard is under  specifying and
muddy, and I'd  try to avoid the muddiest parts.  After been bitten by
the extended LOOP mud monster, I  consider it to be muddy enough to be
avoided.  The semantics of DO and DO* is completely clear in comparison.


-- 
__Pascal_Bourguignon__                     http://www.informatimago.com/
There is no worse tyranny than to force a man to pay for what he doesn't
want merely because you think it would be good for him.--Robert Heinlein
http://www.theadvocates.org/
From: Rob Warnock
Subject: Re: The LOOP macro (was Re: Be afraid of XML)
Date: 
Message-ID: <PXqdnXLEhNkYOcjd3czS-w@speakeasy.net>
Pascal Bourguignon <····@thalassa.informatimago.com> wrote:
+---------------
| In any case, my point is that the standard is under specifying
| and muddy, and I'd try to avoid the muddiest parts.
+---------------

I don't think we disagree all that much here.

+---------------
| After been bitten by the extended LOOP mud monster, I consider it
| to be muddy enough to be avoided. The semantics of DO and DO* is
| completely clear in comparison.
+---------------

On this point we should probably agree to disagree. Personally, while I
initially did find LOOP to be large, complex, & confusing, I now find a
fairly large subset of LOOP to be perspicuous enough, and for a number
of common tasks to be considerably more convenient that DO/DO*, particularly
given features like iteration variable destructuring and COLLECT/COUNT/SUM/&c.

And while I certainly still use DOTIMES, DOLIST, and DOHASH[1] where they
fit the task, I seldom find myself using DO/DO* any more. FWIW.


-Rob

[1] In CLISP, that is. In CMUCL, it's called DO-HASH (with the same args),
    but a trivial renaming macro fixes that. (And besides, it's easy enough
    to define from scratch.)

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Joel Ray Holveck
Subject: Re: The LOOP macro
Date: 
Message-ID: <87k71h6gbn.fsf@thor.piquan.org>
> On this point we should probably agree to disagree. Personally,
> while I initially did find LOOP to be large, complex, & confusing, I
> now find a fairly large subset of LOOP to be perspicuous enough, and
> for a number of common tasks to be considerably more convenient that
> DO/DO*, particularly given features like iteration variable
> destructuring and COLLECT/COUNT/SUM/&c.

Whenever I tell my (non-Lisp) friends about LOOP, I find it hard to
come up with an on-the-spot example that demonstrates its power.  It's
almost always something that can be written just as easily using
Perl's "for" (which can behave as our FOR V IN L, or our FOR V = X
THEN Y WHILE Z, like C's for).

Do you have a good example of LOOP's power / flexibility that doesn't
need much surrounding context to understand?

joelh
From: Peter Seibel
Subject: Re: The LOOP macro
Date: 
Message-ID: <m3u10lvl3r.fsf@javamonkey.com>
Joel Ray Holveck <·····@piquan.org> writes:

>> On this point we should probably agree to disagree. Personally,
>> while I initially did find LOOP to be large, complex, & confusing, I
>> now find a fairly large subset of LOOP to be perspicuous enough, and
>> for a number of common tasks to be considerably more convenient that
>> DO/DO*, particularly given features like iteration variable
>> destructuring and COLLECT/COUNT/SUM/&c.
>
> Whenever I tell my (non-Lisp) friends about LOOP, I find it hard to
> come up with an on-the-spot example that demonstrates its power.  It's
> almost always something that can be written just as easily using
> Perl's "for" (which can behave as our FOR V IN L, or our FOR V = X
> THEN Y WHILE Z, like C's for).
>
> Do you have a good example of LOOP's power / flexibility that doesn't
> need much surrounding context to understand?

Here are a few:

  (loop repeat 100 collect (random 10))

  (loop for x across array-of-numbers
        minimizing x into min
        maximizing x into max
        summing x into total
        counting t into count
        finally (return (list min max (/ total count))))

  (loop for w across widgets count (good-widget-p w))

-Peter

-- 
Peter Seibel                                      ·····@javamonkey.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp
From: Barry Margolin
Subject: Re: The LOOP macro
Date: 
Message-ID: <barmar-464B24.18220318032004@comcast.ash.giganews.com>
In article <··············@javamonkey.com>,
 Peter Seibel <·····@javamonkey.com> wrote:

> Joel Ray Holveck <·····@piquan.org> writes:
> 
> >> On this point we should probably agree to disagree. Personally,
> >> while I initially did find LOOP to be large, complex, & confusing, I
> >> now find a fairly large subset of LOOP to be perspicuous enough, and
> >> for a number of common tasks to be considerably more convenient that
> >> DO/DO*, particularly given features like iteration variable
> >> destructuring and COLLECT/COUNT/SUM/&c.
> >
> > Whenever I tell my (non-Lisp) friends about LOOP, I find it hard to
> > come up with an on-the-spot example that demonstrates its power.  It's
> > almost always something that can be written just as easily using
> > Perl's "for" (which can behave as our FOR V IN L, or our FOR V = X
> > THEN Y WHILE Z, like C's for).
> >
> > Do you have a good example of LOOP's power / flexibility that doesn't
> > need much surrounding context to understand?
> 
> Here are a few:
> 
>   (loop repeat 100 collect (random 10))
> 
>   (loop for x across array-of-numbers
>         minimizing x into min
>         maximizing x into max
>         summing x into total
>         counting t into count
>         finally (return (list min max (/ total count))))
> 
>   (loop for w across widgets count (good-widget-p w))

I think these are very good examples.  The power of LOOP isn't in the 
iteration; just about every programming language has reasonable 
iteration mechanisms.  The more unique feature is the action verbs like 
COLLECT and SUMMING.  Some languages may have a couple of these (like 
Perl's 'grep' and 'map'), but I don't think any other language has 
anything close to the set that LOOP offers (similar capabilitites can be 
found in the Series package for CL).

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
From: Rob Warnock
Subject: Re: The LOOP macro
Date: 
Message-ID: <t_Gdnc2iS4DqOcHd3czS-w@speakeasy.net>
Barry Margolin  <······@alum.mit.edu> wrote:
+---------------
| ... The power of LOOP isn't in the iteration; just about every
| programming language has reasonable iteration mechanisms.
| The more unique feature is the action verbs like COLLECT and SUMMING.
+---------------

And the automatic destructuring into iteration variables -- I find
myself using that a lot [see previous examples posted]. Things like:

	(loop for (key . value) in alist
	      and (key2 value2) on plist by #'cddr
	  ...)


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: André Thieme
Subject: Re: The LOOP macro
Date: 
Message-ID: <c3db5u$6au$1@ulric.tng.de>
Peter Seibel wrote:
>>Do you have a good example of LOOP's power / flexibility that doesn't
>>need much surrounding context to understand?
> 
> 
> Here are a few:
> 
>   (loop repeat 100 collect (random 10))

This first example is not overly impressive for people who work for 
example with Python (and list comprehension):
after importing the lib (from random import randint) I can do:

[randint(0, 10) for x in range(100)]

to get the same result.



>   (loop for x across array-of-numbers
>         minimizing x into min
>         maximizing x into max
>         summing x into total
>         counting t into count
>         finally (return (list min max (/ total count))))
> 
>   (loop for w across widgets count (good-widget-p w))

These two examples are in fact very nice I think, and the good thing is: 
I am coming closer (in my books) to "loop", in a few days I will reach 
it *cheers* :)

For the third example in Python one would either need to write a 
counting function which takes an object container (like "widgets") and a 
comparison function or you need to handle each case of counting 
specific, which also means to introduce temporary counting vars, etc.
Both ways are unnecessary "talkative" when compared with Peters loop 
examples.

I'm really looking forward for all the other good things Lisp will offer me.


Regards,
Andr�
--
"If Java is your hammer, every problem looks like a thumb"
From: Kenny Tilton
Subject: Re: The LOOP macro
Date: 
Message-ID: <bwr6c.79$DV6.39@twister.nyc.rr.com>
Andr� Thieme wrote:

> Peter Seibel wrote:
> 
>>> Do you have a good example of LOOP's power / flexibility that doesn't
>>> need much surrounding context to understand?
>>
>>
>>
>> Here are a few:
>>
>>   (loop repeat 100 collect (random 10))
> 
> 
> This first example is not overly impressive for people who work for 
> example with Python (and list comprehension):

We call this The "Nice, But I Am Not /Staggered/" Trap. :) But I will 
offer anyway a small pleasantness:

  (loop for row-no below (ceiling (length fonts) cols)
       when (mk-font-view fonts col-no row-no) ;; maybe no view back
       collect it)

We'll run out of fonts mid-column most likely, and also mk-font-view 
might be coded to effectively filter out certain fonts by not returning 
a view if the font, when opened, turns out to have certain attributes.

kt

-- 
http://tilton-technology.com

Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film

Your Project Here! http://alu.cliki.net/Industry%20Application
From: Brian Downing
Subject: Re: The LOOP macro
Date: 
Message-ID: <P0s6c.35738$JL2.407075@attbi_s03>
In article <············@ulric.tng.de>,
Andr� Thieme  <······································@justmail.de> wrote:
> Peter Seibel wrote:
> >   (loop for w across widgets count (good-widget-p w))
> 
> For the third example in Python one would either need to write a 
> counting function which takes an object container (like "widgets") and a 
> comparison function or you need to handle each case of counting 
> specific, which also means to introduce temporary counting vars, etc.
> Both ways are unnecessary "talkative" when compared with Peters loop 
> examples.

CL already has COUNT-IF, and for this example I think it looks much
better than the LOOP:

(count-if #'good-widget-p widgets)

It works across all sequences with the same syntax, too.

-bcd
-- 
*** Brian Downing <bdowning at lavos dot net> 
From: Peter Seibel
Subject: Re: The LOOP macro
Date: 
Message-ID: <m3ekrpvbxj.fsf@javamonkey.com>
Brian Downing <·············@lavos.net> writes:

> In article <············@ulric.tng.de>,
> Andr� Thieme  <······································@justmail.de> wrote:
>> Peter Seibel wrote:
>> >   (loop for w across widgets count (good-widget-p w))
>> 
>> For the third example in Python one would either need to write a 
>> counting function which takes an object container (like "widgets") and a 
>> comparison function or you need to handle each case of counting 
>> specific, which also means to introduce temporary counting vars, etc.
>> Both ways are unnecessary "talkative" when compared with Peters loop 
>> examples.
>
> CL already has COUNT-IF, and for this example I think it looks much
> better than the LOOP:
>
> (count-if #'good-widget-p widgets)
>
> It works across all sequences with the same syntax, too.

That's a good point. Originally I started out writing a slightly more
complicated example like:

  (loop for w across widgets
        count (red-p w) into red
        count (blue-p w) into blue
        count t into total
        finally (return (list red blue total)))

and decided to simplify it. Oh well.

-Peter

-- 
Peter Seibel                                      ·····@javamonkey.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp
From: =?ISO-8859-15?Q?Andr=E9_Thieme?=
Subject: Re: The LOOP macro
Date: 
Message-ID: <c3ejlq$1ml$1@ulric.tng.de>
Peter Seibel wrote:

>>CL already has COUNT-IF, and for this example I think it looks much
>>better than the LOOP:
>>
>>(count-if #'good-widget-p widgets)
>>
>>It works across all sequences with the same syntax, too.
> 
> 
> That's a good point. Originally I started out writing a slightly more
> complicated example like:
> 
>   (loop for w across widgets
>         count (red-p w) into red
>         count (blue-p w) into blue
>         count t into total
>         finally (return (list red blue total)))
> 
> and decided to simplify it. Oh well.

In Python you would first have to write "count-if" yourself.
Let's say it is given, then I would do something like:


x = [count-if(w, widgets) for w in [red-p, blue-p]]
x.append(reduce(add, x))


The Python equivalent is so short because it asumes that "count-if"
and "add" are already defined. But I think in many other languages it is 
a good bit more complicated!


Andr�
--
From: Marco Antoniotti
Subject: Re: The LOOP macro
Date: 
Message-ID: <Z_H6c.115$IJ5.84487@typhoon.nyu.edu>
Andr� Thieme wrote:

> Peter Seibel wrote:
> 
>>> CL already has COUNT-IF, and for this example I think it looks much
>>> better than the LOOP:
>>>
>>> (count-if #'good-widget-p widgets)
>>>
>>> It works across all sequences with the same syntax, too.
>>
>>
>>
>> That's a good point. Originally I started out writing a slightly more
>> complicated example like:
>>
>>   (loop for w across widgets
>>         count (red-p w) into red
>>         count (blue-p w) into blue
>>         count t into total
>>         finally (return (list red blue total)))
>>
>> and decided to simplify it. Oh well.
> 
> 
> In Python you would first have to write "count-if" yourself.
> Let's say it is given, then I would do something like:
> 
> 
> x = [count-if(w, widgets) for w in [red-p, blue-p]]
> x.append(reduce(add, x))

(let ((x
        [(count-if w widgets) such-that w in '(red-p blue-p)]))
   (append x (reduce '+ x)))

Cheers
--
marco
From: André Thieme
Subject: Re: The LOOP macro
Date: 
Message-ID: <c3fjig$o2p$1@ulric.tng.de>
Marco Antoniotti wrote:

>> In Python you would first have to write "count-if" yourself.
>> Let's say it is given, then I would do something like:
>>
>>
>> x = [count-if(w, widgets) for w in [red-p, blue-p]]
>> x.append(reduce(add, x))
> 
> 
> (let ((x
>        [(count-if w widgets) such-that w in '(red-p blue-p)]))
>   (append x (reduce '+ x)))

Hallo Marco!

As I have seen so far with loop you can sometimes do things that would
be not so easy and readable if you had used Java. And even in Python it
can sometimes seem slightly more complicated.
What I would really like to see if there is an example which would be
really hard to solve even in Python.
Maybe you have some ideas for that?


Andr�
--
From: Peter Seibel
Subject: Re: The LOOP macro
Date: 
Message-ID: <m33c84tt6j.fsf@javamonkey.com>
Andr� Thieme <······································@justmail.de> writes:

> Marco Antoniotti wrote:
>
>>> In Python you would first have to write "count-if" yourself.
>>> Let's say it is given, then I would do something like:
>>>
>>>
>>> x = [count-if(w, widgets) for w in [red-p, blue-p]]
>>> x.append(reduce(add, x))
>> (let ((x
>>        [(count-if w widgets) such-that w in '(red-p blue-p)]))
>>   (append x (reduce '+ x)))
>
> Hallo Marco!
>
> As I have seen so far with loop you can sometimes do things that
> would be not so easy and readable if you had used Java. And even in
> Python it can sometimes seem slightly more complicated. What I would
> really like to see if there is an example which would be really hard
> to solve even in Python. Maybe you have some ideas for that?

I have no idea what all can be done in Python with list comprehensions
but after a quick glance at the list comprehension stuff I suspect
that this loop which segregates elements of a list into three not
necessarily disjoint list might not be (easily) expressible as list
comprehension.

  (loop for x in things
        when (foo-p x) collect x into foos
        when (bar-p x) collect x into bars
        when (and (foo-p x) (bar-p x)) collect x into both
        finally (return (values foos bars both)))

Or if the predicate functions FOO-P and BAR-P are sufficiently
expensive that you don't want to compute more often than absolutely
necessary:

  (loop for x in things
        for foo-p = (foo-p x)
        for bar-p = (bar-p x)
        when foo-p collect x into foos
        when bar-p collect x into bars
        when (and foo-p bar-p) collect x into both
        finally (return (values foos bars both)))

-Peter

-- 
Peter Seibel                                      ·····@javamonkey.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp
From: =?ISO-8859-15?Q?Andr=E9_Thieme?=
Subject: Re: The LOOP macro
Date: 
Message-ID: <c3fugc$vqd$1@ulric.tng.de>
Peter Seibel wrote:

> I have no idea what all can be done in Python with list comprehensions

It is syntactic sugar, an easy way to get objects into a list.
In his "Python in a Nutshell" Alex Martelli says this:

"A common use of a for loop is to inspect each item in a sequence and
build a new list by appending the results of an expression computed on
some or all of the items inspected. The expression form, called a list
comprehension, lets you code this common idiom concisely and directly.
Since a list comprehension is an expression (rather than a block of
statements), you can use it directly wherever you need an expression
(e.g., as an actual argument in a function call, in a return statement,
or as a subexpression for some other expression)."



> but after a quick glance at the list comprehension stuff I suspect
> that this loop which segregates elements of a list into three not
> necessarily disjoint list might not be (easily) expressible as list
> comprehension.

A real advantage that loop offers is, that you can introduce temporary
variables (like "foos", "bars" and "both" in your example) without any
real effort. They play only a short role in a program and forgotten when
loop is over. In Python one would have to create lists first and give
them names. So, not to introduce temporary vars (one could delete them
but this would make it worse cause you would have to care about even
more then) I would encapsulate your loop in a function. So

>   (loop for x in things
>         when (foo-p x) collect x into foos
>         when (bar-p x) collect x into bars
>         when (and (foo-p x) (bar-p x)) collect x into both
>         finally (return (values foos bars both)))

could be written as:

def loop_things(things):
     foos = []
     bars = []
     both = []
     for x in things:
         if foo_p(x): foos.append(x)
         if bar_p(x): bars.append(x)
         if foo_p(x) and bar_p(x): both.append(x)
     return foos, bars, both

So I would do it without lisp comprehension. Besides the additional
definitions of "foos", "bars" and "both" then Python example is the
same, even some few keystrokes shorter.

I guess there are no examples of the use of loop which are really more
"powerfull" or shorter than a Python solution. For this Python is simply
already to "lispish" by having lists that are so easy to use, that here
is no room for some hidden extra power.
Compare with http://www.norvig.com/python-lisp.html

Anyway, I am thankfull for your examples cause it forced me to read more
about loop (from your site *g*) and now I have a very good overview and
am no longer scared, and I learned that one advantage of loop is, that
it can introduce temporary symbols that I don't need to care about.

One thing that would interest me:
could you possibly provide a Java solution to your loop examples?


Andr�
--
From: Peter Seibel
Subject: Re: The LOOP macro
Date: 
Message-ID: <m3ptb8s7or.fsf@javamonkey.com>
Andr� Thieme <······································@justmail.de> writes:

> Anyway, I am thankfull for your examples cause it forced me to read
> more about loop (from your site *g*) and now I have a very good
> overview and am no longer scared, and I learned that one advantage
> of loop is, that it can introduce temporary symbols that I don't
> need to care about.

Yup. LOOP is definitely one of those things that there's no single
feature that just staggers you with its power. But when you add up all
the bits it turns out to be quite easy to express many of the things
you'd want to express. And when you think about the percentage of
programs that are made up of loops of various kinds, it's not a small
win.

> One thing that would interest me: could you possibly provide a Java
> solution to your loop examples?

Nah. It'll do you good to figure it out yourself. ;-) Or don't
bother--they'd look similar to what you'd write in Python without list
comprehensions. Though with more type declarations. Unless of course
you had written some class to cover any one of the particular cases.

-Peter

-- 
Peter Seibel                                      ·····@javamonkey.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp
From: Gareth McCaughan
Subject: Re: The LOOP macro
Date: 
Message-ID: <87n069db2u.fsf@g.mccaughan.ntlworld.com>
Peter Seibel wrote:

> I have no idea what all can be done in Python with list comprehensions
> but after a quick glance at the list comprehension stuff I suspect
> that this loop which segregates elements of a list into three not
> necessarily disjoint list might not be (easily) expressible as list
> comprehension.
> 
>   (loop for x in things
>         when (foo-p x) collect x into foos
>         when (bar-p x) collect x into bars
>         when (and (foo-p x) (bar-p x)) collect x into both
>         finally (return (values foos bars both)))

This one as it stands can be written quite concisely and
readably in Python, at the (minor) cost of tripling the
loop overhead:

    ([x for x in things if foo_p(x)],
     [x for x in things if bar_p(x)],
     [x for x in things if foo_p(x) and bar_p(x)])

> Or if the predicate functions FOO-P and BAR-P are sufficiently
> expensive that you don't want to compute more often than absolutely
> necessary:
> 
>   (loop for x in things
>         for foo-p = (foo-p x)
>         for bar-p = (bar-p x)
>         when foo-p collect x into foos
>         when bar-p collect x into bars
>         when (and foo-p bar-p) collect x into both
>         finally (return (values foos bars both)))

For this one you'd have to write the loop explicitly; someone's
already posted a translation. But it doesn't end up being either
much longer or much uglier than the LOOP form above. Here's another
way to write it that avoids superfluous calls to foo_p and bar_p:

    temp = [(x,foo_p(x),bar_p(x)) for x in things]
    ([x for (x,foo,bar) in temp if foo],
     [x for (x,foo,bar) in temp if bar],
     [x for (x,foo,bar) in temp if foo and bar])

There's still extra loop overhead compared to the Lisp version,
but you don't use Python when every last cycle counts :-).

-- 
Gareth McCaughan
.sig under construc
From: Kenny Tilton
Subject: Re: The LOOP macro
Date: 
Message-ID: <xMr7c.2968$1C1.1642131@twister.nyc.rr.com>
Gareth McCaughan wrote:
> Peter Seibel wrote:
> 
> 
>>I have no idea what all can be done in Python with list comprehensions
>>but after a quick glance at the list comprehension stuff I suspect
>>that this loop which segregates elements of a list into three not
>>necessarily disjoint list might not be (easily) expressible as list
>>comprehension.
>>
>>  (loop for x in things
>>        when (foo-p x) collect x into foos
>>        when (bar-p x) collect x into bars
>>        when (and (foo-p x) (bar-p x)) collect x into both
>>        finally (return (values foos bars both)))
> 
> 
> This one as it stands can be written quite concisely and
> readably in Python,

Sure, it was a classic "Stagger-Me" Trap.

First was the selection of a mundane operation, iteration. I guess the 
OP thought that asking for a stagger-me on a variable assignment would 
give away his game.

Then came the "not requiring a lot of context" constraint, meaning 
something like:

     (loop for font in fonts ; (a closed over var)
           when (make-font-if-options-match font
                   (on-p serif-choice)
                   (on-p var-width-choice))
           collect it)

...would not work because it violates both constraints (closures being 
outside the loop-only constraint).

So it was a beauty of a trap, and god bless the savages of cll for 
trying to claw their way out. They did not notice the trap door:

   (loop for n below 3 do (print n))

That ain't Lisp syntax. This is Lisp syntax;

   (do ((n 1 (1+ n)))
        ((> n 3))
     (print n))


  at the (minor) cost of tripling the
> loop overhead:
> 
>     ([x for x in things if foo_p(x)],
>      [x for x in things if bar_p(x)],
>      [x for x in things if foo_p(x) and bar_p(x)])
> 
> 
>>Or if the predicate functions FOO-P and BAR-P are sufficiently
>>expensive that you don't want to compute more often than absolutely
>>necessary:
>>
>>  (loop for x in things
>>        for foo-p = (foo-p x)
>>        for bar-p = (bar-p x)
>>        when foo-p collect x into foos
>>        when bar-p collect x into bars
>>        when (and foo-p bar-p) collect x into both
>>        finally (return (values foos bars both)))
> 
> 
> For this one you'd have to write the loop explicitly; someone's
> already posted a translation. But it doesn't end up being either
> much longer or much uglier than the LOOP form above. Here's another
> way to write it that avoids superfluous calls to foo_p and bar_p:
> 
>     temp = [(x,foo_p(x),bar_p(x)) for x in things]
>     ([x for (x,foo,bar) in temp if foo],
>      [x for (x,foo,bar) in temp if bar],
>      [x for (x,foo,bar) in temp if foo and bar])
> 
> There's still extra loop overhead compared to the Lisp version,
> but you don't use Python when every last cycle counts :-).

Forget the cycles, look at all that repetition. Visually, it hides what 
is going on. And I have to hit every line of code to add or remove a 
selector. That code is unreadbale and unmaintainable, hence not equivalent.

Maybe Python has a way I could create new syntax to avoid all that 
clutter? I know Pythonistas place extraordinary value on visually clean 
code.

:)

kenneth


-- 
Home? http://tilton-technology.com
Cells? http://www.common-lisp.net/project/cells/
Cello? http://www.common-lisp.net/project/cello/
From: Gareth McCaughan
Subject: Re: The LOOP macro
Date: 
Message-ID: <87vfkwbsy7.fsf@g.mccaughan.ntlworld.com>
Kenny Tilton wrote:

[I said:]
>> This one as it stands can be written quite concisely and
>> readably in Python,
> 
> Sure, it was a classic "Stagger-Me" Trap.
> 
> First was the selection of a mundane operation, iteration. I guess the
> OP thought that asking for a stagger-me on a variable assignment would
> give away his game.

:-)

>>>  (loop for x in things
>>>        for foo-p = (foo-p x)
>>>        for bar-p = (bar-p x)
>>>        when foo-p collect x into foos
>>>        when bar-p collect x into bars
>>>        when (and foo-p bar-p) collect x into both
>>>        finally (return (values foos bars both)))
>>
>> For this one you'd have to write the loop explicitly; someone's
>> already posted a translation. But it doesn't end up being either
>> much longer or much uglier than the LOOP form above. Here's another
>> way to write it that avoids superfluous calls to foo_p and bar_p:
>>     temp = [(x,foo_p(x),bar_p(x)) for x in things]
>>     ([x for (x,foo,bar) in temp if foo],
>>      [x for (x,foo,bar) in temp if bar],
>>      [x for (x,foo,bar) in temp if foo and bar])
>> There's still extra loop overhead compared to the Lisp version,
>> but you don't use Python when every last cycle counts :-).
> 
> Forget the cycles, look at all that repetition. Visually, it hides
> what is going on. And I have to hit every line of code to add or
> remove a selector. That code is unreadable and unmaintainable, hence
> not equivalent.

Unreadability is in the mind of the reader. I find it
quite readable, though I do prefer the Lisp. Unfortunately
that's partly because I can't stop myself caring a bit
about all those wasted cycles.

I'm not so sure about the repetition. Here are the repetitions
in the Lisp code:

>>>  
>>>        for                  
>>>        for       = (      x)
>>>             foo-p         x         
>>>        when bar-p collect x into     
>>>        when      foo-p bar-p  collect x into     
>>>                                foos bars both

and here are the repetitions in the Python code:

>>                      x      (x)      x
>>       x     (x        ) in         foo  
>>      [x for (x,foo,bar) in temp if bar],
>>      [x for (x,foo,bar) in temp if foo     bar] 

I make that one fewer repeated character in the Python :-).

> Maybe Python has a way I could create new syntax to avoid all that
> clutter? I know Pythonistas place extraordinary value on visually
> clean code.

Ha. If only.

-- 
Gareth McCaughan
.sig under construc
From: Peter Seibel
Subject: Re: The LOOP macro
Date: 
Message-ID: <m3brmor1vi.fsf@javamonkey.com>
Gareth McCaughan <················@pobox.com> writes:

> Kenny Tilton wrote:

>> Forget the cycles, look at all that repetition. Visually, it hides
>> what is going on. And I have to hit every line of code to add or
>> remove a selector. That code is unreadable and unmaintainable,
>> hence not equivalent.
>
> Unreadability is in the mind of the reader. I find it quite
> readable, though I do prefer the Lisp. Unfortunately that's partly
> because I can't stop myself caring a bit about all those wasted
> cycles.
>
> I'm not so sure about the repetition. Here are the repetitions in
> the Lisp code:
>
>>>>  
>>>>        for                  
>>>>        for       = (      x)
>>>>             foo-p         x         
>>>>        when bar-p collect x into     
>>>>        when      foo-p bar-p  collect x into     
>>>>                                foos bars both
>
> and here are the repetitions in the Python code:
>
>>>                      x      (x)      x
>>>       x     (x        ) in         foo  
>>>      [x for (x,foo,bar) in temp if bar],
>>>      [x for (x,foo,bar) in temp if foo     bar] 
>
> I make that one fewer repeated character in the Python :-).

Sure. But another way to look at repetition is whether or not
something seemingly unrelated has to be changed to accomadate another
change. This seems more interesting because the real cost of
repetition is the cost of changes--if you you cut-n-paste code reuse
then every seemingly small change requires a lot of textual changes
compared to better factored code.

For instance, consider adding a third predicate baz-p and
corresponding list to each version. In the Lisp version, we add two
lines and modify two:

  (loop for x in things
        for foo-p = (foo-p x)
        for bar-p = (bar-p x)
        for baz-p = (baz-p x)                            ; added
        when foo-p collect x into foos
        when bar-p collect x into bars
        when baz-p collect x into bazes                  ; added
        when (and foo-p bar-p baz-p) collect x into both ; modified
        finally (return (values foos bars bazes both)))  ; modified

But in the Python version you have to touch *every* line:

   temp = [(x,foo_p(x),bar_p(x),baz_p(x)) for x in things]
   ([x for (x,foo,bar,baz) in temp if foo],
    [x for (x,foo,bar,baz) in temp if bar],
    [x for (x,foo,bar,baz) in temp if baz],
    [x for (x,foo,bar,baz) in temp if foo and bar and baz])

-Peter

-- 
Peter Seibel                                      ·····@javamonkey.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp
From: Gareth McCaughan
Subject: Re: The LOOP macro
Date: 
Message-ID: <87d6748m89.fsf@g.mccaughan.ntlworld.com>
Peter Seibel wrote:

[Kenny Tilton:]
>>> Forget the cycles, look at all that repetition. Visually, it hides
>>> what is going on. And I have to hit every line of code to add or
>>> remove a selector. That code is unreadable and unmaintainable,
>>> hence not equivalent.

[me:]
>> Unreadability is in the mind of the reader. I find it quite
>> readable, though I do prefer the Lisp. Unfortunately that's partly
>> because I can't stop myself caring a bit about all those wasted
>> cycles.
>>
>> I'm not so sure about the repetition. Here are the repetitions in
>> the Lisp code:
...
>> and here are the repetitions in the Python code:
...
>> I make that one fewer repeated character in the Python :-).
> 
> Sure. But another way to look at repetition is whether or not
> something seemingly unrelated has to be changed to accomadate another
> change. This seems more interesting because the real cost of
> repetition is the cost of changes--if you you cut-n-paste code reuse
> then every seemingly small change requires a lot of textual changes
> compared to better factored code.

Yes; that's an insightful way of looking at it.

> For instance, consider adding a third predicate baz-p and
> corresponding list to each version. In the Lisp version, we add two
> lines and modify two:
...
> But in the Python version you have to touch *every* line:

Yep. I hope I didn't give the impression that I prefer the
Python version. It has its advantages, but if I have to
choose I'll take LOOP every time. It's not like it would
be difficult to make a read-macro to turn

    [A for B in C if D]

into

    (loop for B in C when D collect A)

after all. The one thing that's better about the Python
version, other than that it saves a few keystrokes, is that
Python's handling of "sequences" (generalized things you
can iterate over) is much nicer than CL's handling of
"sequences" (lists and vectors-including-strings, and
nothing else). The runtime cost would be a bit painful
in a generally-fast language like CL, though; it doesn't
hurt much in a generally-slow language like Python :-).

SERIES deals with quite a lot of these issues pretty
nicely, of course...

-- 
Gareth McCaughan
.sig under construc
From: ·········@random-state.net
Subject: Re: The LOOP macro
Date: 
Message-ID: <c3ora3$5ge4m$1@midnight.cs.hut.fi>
Gareth McCaughan <················@pobox.com> wrote:


> Python's handling of "sequences" (generalized things you
> can iterate over) is much nicer than CL's handling of
> "sequences" (lists and vectors-including-strings, and

> SERIES deals with quite a lot of these issues pretty
> nicely, of course...

As does "Iterate": http://boinkor.net/lisp/iterate-ansi-0.9.1.tgz

Cheers,

  -- Nikodemus
From: Jacek Generowicz
Subject: Re: The LOOP macro
Date: 
Message-ID: <tyfzna62uzr.fsf@pcepsft001.cern.ch>
·········@random-state.net writes:

> http://boinkor.net/lisp/iterate-ansi-0.9.1.tgz

Is there a summary of what it is, somewhere more easily accessible
than the inside of that tarball ?
From: Dirk Gerrits
Subject: Re: The LOOP macro
Date: 
Message-ID: <61l8c.105524$EI2.33968@amsnews05.chello.com>
Jacek Generowicz wrote:
> ·········@random-state.net writes:
> 
> 
>>http://boinkor.net/lisp/iterate-ansi-0.9.1.tgz
> 
> 
> Is there a summary of what it is, somewhere more easily accessible
> than the inside of that tarball ?

http://www.cliki.net/iterate :

"iterate is a lispy and extensible replacement for the LOOP macro. It is 
also a utility library.

It was written by Jonathan Amsterdam at MIT and recently ported to 
Common Lisp.

Some examples:

(iterate (for (key . item) in alist)
	 (collect key into keys)
	 (collect item into items)
	 (finally (return (values keys items))))

collects keys and items of an alist into two values

It also supports generators:

(iterate (generate i from 0 to 6)
	 (for (key . value) in '((a . 2) (zero . 10) (one . 20) (d . 5)))
	 (when (>= value 10)
	   (collect (cons key (next i)))))


=> ((ZERO . 0) (ONE . 1))

and allows easy finding of extrema:

(iterate (for elt in list-of-lists)
	 (finding elt maximizing (length elt)))

finds the longest list in a list of lists and generates pretty fast 
code, too. (-:

The recent ASDF-installable package is at:

Download ASDF package from 
http://boinkor.net/lisp/iterate/iterate-current.tar.gz
iterate is also a part of Screamer."


Dirk Gerrits
From: a
Subject: Re: The LOOP macro
Date: 
Message-ID: <xRl8c.74185$vn.221870@sea-read.news.verio.net>
Is collect found only in loop and iterate or is there a separate 'collect'
package? Isn't collecting a separate concept from iteration? (And if so
then, rhetorically, why are the concepts conflated within iteration macros
instead of implemented separately?)  I'm thinking of a collect that can
operate across function call boundaries, is tagged to allow simultaneous
collecting to more than one target, and is nestable. It's not so bad to
write but if there's a canonical package out there, I'd use it instead of
what I'd write.


"Dirk Gerrits" <····@dirkgerrits.com> wrote in message news:61l8c.105524
...
> (iterate (for (key . item) in alist)
> (collect key into keys)
> (collect item into items)
> (finally (return (values keys items))))
>
> collects keys and items of an alist into two values
>
> It also supports generators:
>
> (iterate (generate i from 0 to 6)
> (for (key . value) in '((a . 2) (zero . 10) (one . 20) (d . 5)))
> (when (>= value 10)
>    (collect (cons key (next i)))))
>
>
> => ((ZERO . 0) (ONE . 1))
...
From: Pascal Costanza
Subject: Re: The LOOP macro
Date: 
Message-ID: <c3sq3s$ru7$1@newsreader2.netcologne.de>
a wrote:

> Is collect found only in loop and iterate or is there a separate 'collect'
> package? Isn't collecting a separate concept from iteration? (And if so
> then, rhetorically, why are the concepts conflated within iteration macros
> instead of implemented separately?)  I'm thinking of a collect that can
> operate across function call boundaries, is tagged to allow simultaneous
> collecting to more than one target, and is nestable. It's not so bad to
> write but if there's a canonical package out there, I'd use it instead of
> what I'd write.

For example, see http://www.tfeb.org/lisp/hax.html#COLLECTING

I recall seeing similar definitions elsewhere, but I don't know here 
exactly.

A standard "pure" ANSI idiom is to use PUSH for collecting and NREVERSE 
for bringing the result into the right order.


Pascal

-- 
1st European Lisp and Scheme Workshop
June 13 - Oslo, Norway - co-located with ECOOP 2004
http://www.cs.uni-bonn.de/~costanza/lisp-ecoop/
From: Rob Warnock
Subject: Re: The LOOP macro
Date: 
Message-ID: <psKcnVYLR_AjL__d3czS-w@speakeasy.net>
Pascal Costanza  <········@web.de> wrote:
+---------------
| a wrote:
| >  ...   I'm thinking of a collect that can
| > operate across function call boundaries, is tagged to allow simultaneous
| > collecting to more than one target, and is nestable. It's not so bad to
| > write but if there's a canonical package out there, I'd use it instead of
| > what I'd write.
| 
| For example, see http://www.tfeb.org/lisp/hax.html#COLLECTING
| 
| I recall seeing similar definitions elsewhere, but I don't know here 
| exactly.
+---------------

Also see the EXTENSIONS:COLLECT macro that comes with CMUCL, which
seems to do much the same thing as COLLECTING. The doc string:

  "Collect ({(Name [Initial-Value] [Function])}*) {Form}*
  Collect some values somehow.  Each of the collections specifies a bunch
  of things which collected during the evaluation of the body of the form.
  The name of the collection is used to define a local macro, a la MACROLET.
  Within the body, this macro will evaluate each of its arguments and collect
  the result, returning the current value after the collection is done.
  The body is evaluated as a PROGN; to get the final values when you are
  done, just call the collection macro with no arguments.

  Initial-Value is the value that the collection starts out with, which
  defaults to NIL.  Function is the function which does the collection.
  It is a function which will accept two arguments: the value to be collected
  and the current collection.  The result of the function is made the new
  value for the collection.  As a totally magical special-case, the Function
  may be Collect, which tells us to build a list in forward order; this
  is the default. If an Initial-Value is supplied for Collect, the stuff
  will be rplacd'd onto the end.  Note that Function may be anything
  that can appear in the functional position, including macros and lambdas."

You can use it like this:

	> (collect ((list) (sum 0 +) (prod 1 *))
	    (list :foo)
	    (sum 4)
	    (list :bar :baz :gorp)
	    (when t
	      (prod 7))
	    (loop for i from 10 to 12
	      do (sum i))
	    (prod 6 2)
	    (list :quux)
	    (values (list) (sum) (prod)))

	(:FOO :BAR :BAZ :GORP :QUUX)
	37
	84
	> 


-Rob

p.s. Note that because the variable LIST was MACROLET-bound within
the COLLECT (probably a violation of the CLHS on my part), you can't
use the system LIST within this call. So change the variable name
to MY-LIST...

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Tim Bradshaw
Subject: Re: The LOOP macro
Date: 
Message-ID: <fbc0f5d1.0403260752.be2646b@posting.google.com>
Pascal Costanza <········@web.de> wrote in message news:<············@newsreader2.netcologne.de>...
> a wrote:
> 
> > Is collect found only in loop and iterate or is there a separate 'collect'
> > package? Isn't collecting a separate concept from iteration? (And if so
> > then, rhetorically, why are the concepts conflated within iteration macros
> > instead of implemented separately?)  I'm thinking of a collect that can
> > operate across function call boundaries, is tagged to allow simultaneous
> > collecting to more than one target, and is nestable. It's not so bad to
> > write but if there's a canonical package out there, I'd use it instead of
> > what I'd write.
> 
> For example, see http://www.tfeb.org/lisp/hax.html#COLLECTING
> 

[Anyone who has tried this has probably discovered that www.tfeb.org
is having a bad time at present.  If you look in the DNS you'll find
out what I screwed up, but the answer is
http://80.176.160.38/lisp/hax.html#COLLECTING for now]

One of the nive things about collecting implemented the way that it is
there is that it scopes right.  For instance, you can do something
like this:

(collecting
  (collect #'(lambda (x)
               (collect x))))

Which will create a list whose first element is a function which will
collect stuff into the list.

--tim
From: Marcus Breiing
Subject: Re: The LOOP macro
Date: 
Message-ID: <WlItqYoq8PA@breiing.com>
* a

> I'm thinking of a collect that can operate across function call
> boundaries, is tagged to allow simultaneous collecting to more than
> one target, and is nestable.

This loopophobe admits to having written one like that.  I'm currently
reading cll over the sort of link that makes editing even plain posts
like this one painful, so sorry for not including examples or code.
If you're still interested, I can post more on the weekend.

Marcus

-- 
Marcus Breiing    http://breiing.com/postings/WlItqYoq8PA
From: Dirk Gerrits
Subject: Re: The LOOP macro
Date: 
Message-ID: <%JX8c.36307$s9.19947@amsnews02.chello.com>
a wrote:
> Is collect found only in loop and iterate or is there a separate 'collect'
> package? Isn't collecting a separate concept from iteration? (And if so
> then, rhetorically, why are the concepts conflated within iteration macros
> instead of implemented separately?)  

Collection is just one of several commonly used 'iteration patterns' and 
as such is provided by many 'iteration macro packages' such as LOOP and 
Series. It's certainly possible to separate it from the rest of the 
iteration stuff (as Pascal's and Rob's provided links seem to indicate), 
but you're going to need some other iteration stuff anyway (as the 
examples at those links also show).

> I'm thinking of a collect that can operate across function call
> boundaries, is tagged to allow simultaneous collecting to more than
> one target, and is nestable. It's not so bad to write but if there's
> a canonical package out there, I'd use it instead of what I'd write.

I'm not exactly sure but it seems that Generators & Gatherers (described 
in appendix B of CLTL2 and available as part of the Series package) 
fullfill these requirements. Generators & Gatherers are pretty 
interesting in that they are not one iteration macro like LOOP but 
rather a collection of functions working well together. The same holds 
for Series, which has the additional property of allowing a very 
funcional style of programming without giving up the efficiency of 
iteration.

More info at:

Appendix A and B of CLTL2: http://www.supelec.fr/docs/cltl/clm/node1.html

AIM-1082 and AIM-1083: 
http://publications.ai.mit.edu/publications/pubsDB/pubs.html

http://series.sourceforge.net/

Regards,
Dirk Gerrits
From: Karl Pflästerer
Subject: Re: The LOOP macro
Date: 
Message-ID: <m3y8ps1nrs.fsf@hamster.pflaesterer.de>
On 22 Mar 2004, Peter Seibel <- ·····@javamonkey.com wrote:

> change. This seems more interesting because the real cost of
> repetition is the cost of changes--if you you cut-n-paste code reuse
> then every seemingly small change requires a lot of textual changes
> compared to better factored code.

I'm far from defending Python against Lisp but before you start
comparing Python code to Lisp code the code should be written in a way
which doesn't try to mimic it's written in Lisp; vice versa it would
also be wrong.

> For instance, consider adding a third predicate baz-p and
> corresponding list to each version. In the Lisp version, we add two
> lines and modify two:

>   (loop for x in things
>         for foo-p = (foo-p x)
>         for bar-p = (bar-p x)
>         for baz-p = (baz-p x)                            ; added
>         when foo-p collect x into foos
>         when bar-p collect x into bars
>         when baz-p collect x into bazes                  ; added
>         when (and foo-p bar-p baz-p) collect x into both ; modified
>         finally (return (values foos bars bazes both)))  ; modified

> But in the Python version you have to touch *every* line:

>    temp = [(x,foo_p(x),bar_p(x),baz_p(x)) for x in things]
>    ([x for (x,foo,bar,baz) in temp if foo],
>     [x for (x,foo,bar,baz) in temp if bar],
>     [x for (x,foo,bar,baz) in temp if baz],
>     [x for (x,foo,bar,baz) in temp if foo and bar and baz])

I don't think anyone would really write the code like that; the list
comprehension gives here absolutely no advantage; neither in readability
nor in speed or memory usage. You traverse a list 5 times where 1 time
would suffice and use roughly the double amount of memory normally
necessary.

If you wrote eg.:

foos, bars, bazes, all = [], [], [], []
for x in things:
    foo, bar, baz = foo_p(x), bar_p(x), baz_p(x)
    if foo: foos.append(x)
    if bar: bars.append(x)
    if baz: bazes.append(x)
    if foo and bar and baz: all.append(x)


sure you have some variables sticking in top level (but the same is true
for the lisp comp version since the variables created inside the list
comprehension remain existent with their last value after the list comp
finishes (a failure of Python IMO which perhaps will get changed))
whereas in the loop version they exist only in the scope of the loop.
But you have faster and less memory using code which is also easier to
change (the changes you made to the loop version are nearly the same
which had to be made in the for loop of Python).



   KP

-- 
If you give someone a program, you will frustrate them for a day; if you teach
them how to program, you will frustrate them for a lifetime.
                                                                   - Anonymous
***************** http://www.strauss.za.com/sla/code_std.html ****************
From: André Thieme
Subject: Re: The LOOP macro
Date: 
Message-ID: <c3o6q5$mbs$1@ulric.tng.de>
Karl Pfl�sterer wrote:

> sure you have some variables sticking in top level (but the same is true
> for the lisp comp version since the variables created inside the list
> comprehension remain existent with their last value after the list comp
> finishes (a failure of Python IMO which perhaps will get changed))
> whereas in the loop version they exist only in the scope of the loop.
> But you have faster and less memory using code which is also easier to
> change (the changes you made to the loop version are nearly the same
> which had to be made in the for loop of Python).

This is what I see as an advantage of loop over Pythons solution as I
already mentioned in my posting before. It is very nice to create some
temporary symbols on the fly while in Python I have to create them by
myself.
Not that this is a "huge" difference, but some other people already
pointed out in some other threads that Lisps advatages are usually of
incremental nature.

I don't know if I am interpreting Norvig correctly on this one, but for
me it seems he mainly sees one advantage of Lisp over Python: speed of
execution. Regarding the "power" in programming it seems to me that he
sees them both at the top.


Andre

PS: Tomorrow my copy of
"Paradigms of Artificial Intelligence Programming" will arrive :-)
From: Jacek Generowicz
Subject: Re: The LOOP macro
Date: 
Message-ID: <tyf4qse4c8a.fsf@pcepsft001.cern.ch>
Andr� Thieme  <······································@justmail.de> writes:

> Karl Pfl�sterer wrote:
>
> I don't know if I am interpreting Norvig correctly on this one, but for
> me it seems he mainly sees one advantage of Lisp over Python: speed of
> execution. Regarding the "power" in programming it seems to me that he
> sees them both at the top.

Ah, so they've added macros to Python? Cool. I'm a bit surprised
though, only a few months ago the folks over at c.l.py were pretty
adamant that macros offered power which Pythonistas simply did not
want in their language.

:-)
From: Björn Lindberg
Subject: Re: The LOOP macro
Date: 
Message-ID: <hcslllq9s62.fsf@fnatte.nada.kth.se>
Jacek Generowicz <················@cern.ch> writes:

> Andr� Thieme  <······································@justmail.de> writes:
> 
> > Karl Pfl�sterer wrote:
> >
> > I don't know if I am interpreting Norvig correctly on this one, but for
> > me it seems he mainly sees one advantage of Lisp over Python: speed of
> > execution. Regarding the "power" in programming it seems to me that he
> > sees them both at the top.
> 
> Ah, so they've added macros to Python? Cool. I'm a bit surprised
> though, only a few months ago the folks over at c.l.py were pretty
> adamant that macros offered power which Pythonistas simply did not
> want in their language.
> 
> :-)

And a condition system. And a multiple-dispatch object system. And
proper closures. And ...

:-)


Bj�rn
From: Espen Vestre
Subject: Re: The LOOP macro
Date: 
Message-ID: <kwisgu6y2f.fsf@merced.netfonds.no>
·······@nada.kth.se (Bj�rn Lindberg) writes:

> And a condition system. And a multiple-dispatch object system. And
> proper closures. And ...

And dynamic variables? That's the real test! 

I can't imagine they have added that yet. I mean, they just recently
discovered that you need to worry about scope at all!
-- 
  (espen)
From: André Thieme
Subject: Re: The LOOP macro
Date: 
Message-ID: <c3ssbr$t9v$1@ulric.tng.de>
Bj�rn Lindberg wrote:

> And a condition system. And a multiple-dispatch object system. And
> proper closures. And ...

I am not here to fight for Pyhton, however I would like to mention,
that in complex situations generic methods won't help you and you will
need real pattern matching, so ocaml for example offers here some nice
stuff.

And to closures:
for example in Java you could simulate them with inner classes.
They are not "really" closures, but you don't need them.
It's the same when a Java-guy asks how he can make inner classes in
Lisp, everyone would ask him to use closures instead...
From: Pascal Costanza
Subject: Re: The LOOP macro
Date: 
Message-ID: <c3t0d7$9e4$1@newsreader2.netcologne.de>
Andr� Thieme wrote:

> Bj�rn Lindberg wrote:
> 
>> And a condition system. And a multiple-dispatch object system. And
>> proper closures. And ...
> 
> I am not here to fight for Pyhton, however I would like to mention,
> that in complex situations generic methods won't help you and you will
> need real pattern matching, so ocaml for example offers here some nice
> stuff.

In Lisp, you can build your own pattern matching layer on top of what's 
available, and make it look and behave like it was always part of the 
language. You can do the same for list comprehensions. I recommend this 
as an advanced exercise for learning Lisp: Take one of your favourite 
language features from other languages and reimplement them on top of, 
and integrate them with, Lisp.

See, for example, http://www.cliki.net/fare-matcher and 
http://user.it.uu.se/~svenolof/Collect/. In the beginning, CLOS was also 
nothing than a library of functions and macros built on a much smaller 
Common Lisp dialect. See 
http://www-2.cs.cmu.edu/afs/cs/project/ai-repository/ai/lang/lisp/oop/clos/pcl/0.html

BTW, the beasts are called generic functions, not generic methods.

> And to closures:
> for example in Java you could simulate them with inner classes.
> They are not "really" closures, but you don't need them.
> It's the same when a Java-guy asks how he can make inner classes in
> Lisp, everyone would ask him to use closures instead...

Java's inner classes can only refer to final variables of the 
surrounding lexical environment. This means that you cannot change the 
contents of those variables from within an instance of an inner class. 
That's a serious restriction, and the workarounds are ugly.

Lisp's closures only contain one "method" by default whereas Java's 
inner classes may define several methods. That's not a serious 
restriction of closures, and the workaround, if needed, can be hidden by 
way of abstracting away the details in proper macro definitions. (So, 
no, a Lisper wouldn't tell you to use closures, but first would try to 
make you think about what abstractions you _actually_ need. Closures are 
"only" building material for higher-level abstractions, and not means to 
their own end.)

Always note the most important bit in such discussions: It's not _what_ 
you can do, but _how_ you can do it. You can program everything in 
low-level assembler code, but this doesn't mean that this is an 
appropriate abstraction layer. The power of a language comes from being 
able to abstract away the unimportant details and focus on the things 
that are relevant for the domain at hand. Java only allows you to 
express your abstractions at the level of objects, classes, fields and 
methods. If you want to transcend that level, you need to go outside of 
the language and, for example, use code generators instead. But then you 
are in fact not programming in Java anymore.

In Lisp you can always build the abstraction that you need right into 
Lisp itself. This allows you, in principle, to always stay in the 
language. But I am going to stop here. Since you have started to read 
PAIP, I am pretty sure you will get it soon... ;)

Pascal

-- 
1st European Lisp and Scheme Workshop
June 13 - Oslo, Norway - co-located with ECOOP 2004
http://www.cs.uni-bonn.de/~costanza/lisp-ecoop/
From: André Thieme
Subject: Re: The LOOP macro
Date: 
Message-ID: <c3t3qt$2re$1@ulric.tng.de>
Pascal Costanza wrote:

> 
> Andr� Thieme wrote:
> 
>> Bj�rn Lindberg wrote:
>>
>>> And a condition system. And a multiple-dispatch object system. And
>>> proper closures. And ...
>>
>>
>> I am not here to fight for Pyhton, however I would like to mention,
>> that in complex situations generic methods won't help you and you will
>> need real pattern matching, so ocaml for example offers here some nice
>> stuff.
> 
> 
> In Lisp, you can build your own pattern matching layer on top of what's 
> available, and make it look and behave like it was always part of the 
> language. You can do the same for list comprehensions.

Of course this is a great thing.
But to be fair, when a language X does not support a feature the users
of X can always say that you can simply implement this feature. In the
same time the users of language Y think: oh, we already have this and
this looks like an advantage.
So when we can say: "Ok, Lisp cannot do it but we can always program it
in a way so it gets this feature", then we can also use the same
argument for another language which does not directly support a feature
which Lisp supports.

One factor is very important and you also mention it a bit later in your
post, and that's the fact that it is important how easy it is to bring
some new features into a language. And here is a point where even some
complex behaviour can be implemented pretty easy into Lisp.


 > I recommend this  as an advanced exercise for learning Lisp:
 > ke one of your favourite language features from other languages and
> reimplement them on top of, and integrate them with, Lisp.

I will do and I already have some few ideas. In a few months I should
be ready to do this.. my main problem is the coming semester which will
be very demanding on me, not to forget my work in the company.
All this costs also some time.


>> And to closures:
>> for example in Java you could simulate them with inner classes.
>> They are not "really" closures, but you don't need them.
>> It's the same when a Java-guy asks how he can make inner classes in
>> Lisp, everyone would ask him to use closures instead...
> 
> Java's inner classes can only refer to final variables of the 
> surrounding lexical environment. This means that you cannot change the 
> contents of those variables from within an instance of an inner class. 
> That's a serious restriction, and the workarounds are ugly.

Inner classes have some restrictions... however, they also offer some
advantages, for example they are extendable while closures are not.
In Lisp I might start with a closure for a problem while in Java I would
have to do some extra keystrokes for inner classes because I am limited
to solve my problem this way. But when I discover later that I need to
extend my code then I have to rewrite the Lisp solution while in Java I
could go directly to continue coding on the extension, because I was
limited to one solution.

Again, I am not trying to defend other languages like hell here. I have
already decided to become a Lisper. I am even getting problems reading
Java oder C code and it feels nicer to see Lisp code again.
Anyways, I also want to express that I am not a blind follower. Lisp is
not perfect and not the best solution in every case for every problem.
Some of the Lisp lovers are blind for anything else but Lisp.
Other languages also have now some great features, most "stolen" from
Lisp. However, even if they were stolen - they do exist now and make
even other languages effective.


> Lisp's closures only contain one "method" by default whereas Java's 
> inner classes may define several methods. That's not a serious 
> restriction of closures, and the workaround, if needed, can be hidden by 
> way of abstracting away the details in proper macro definitions. (So, 
> no, a Lisper wouldn't tell you to use closures, but first would try to 
> make you think about what abstractions you _actually_ need. Closures are 
> "only" building material for higher-level abstractions, and not means to 
> their own end.)

Thanks for pointing that out.


> Always note the most important bit in such discussions: It's not _what_ 
> you can do, but _how_ you can do it.

Yes right, this is a very important point.
The tools should make the work easier (although it will cost some people
their jobs because more powerfull tools remove the need for some work to
be done, but this is another topic). Turing completness grants that no
programming language is more powerfull than another one if both are
turing complete.



> You can program everything in 
> low-level assembler code, but this doesn't mean that this is an 
> appropriate abstraction layer. The power of a language comes from being 
> able to abstract away the unimportant details and focus on the things 
> that are relevant for the domain at hand. Java only allows you to 
> express your abstractions at the level of objects, classes, fields and 
> methods. If you want to transcend that level, you need to go outside of 
> the language and, for example, use code generators instead. But then you 
> are in fact not programming in Java anymore.

This is a psychological argument.. some people will maybe not feel good
anymore if they are not programming in their language.
 From a companies POV it is not so important anymore. When there are code
generators who support the work of the masses of the Java coders they
can be used, not regarding the interests of some "fans" of "clean" 
programming.


> In Lisp you can always build the abstraction that you need right into 
> Lisp itself. This allows you, in principle, to always stay in the 
> language. But I am going to stop here. Since you have started to read 
> PAIP, I am pretty sure you will get it soon... ;)

I agree, the book really looks great and because of its general structure
it can be usefull for many coming years. Even when Grahams Arc is out I
think that some techniques which the books presents can still be used.

Going back to read in it...


Andr�
--
From: Pascal Costanza
Subject: Re: The LOOP macro
Date: 
Message-ID: <c3t6ir$jr4$1@newsreader2.netcologne.de>
Andr� Thieme wrote:

> But to be fair, when a language X does not support a feature the users
> of X can always say that you can simply implement this feature. In the
> same time the users of language Y think: oh, we already have this and
> this looks like an advantage.
> So when we can say: "Ok, Lisp cannot do it but we can always program it
> in a way so it gets this feature", then we can also use the same
> argument for another language which does not directly support a feature
> which Lisp supports.

No, we really can't use the same argument. It's possible to seamlessly 
add inner classes to CLOS by way of the MOP. How do you seamlessly add 
access to non-final variables in the lexical environment of an inner 
class in Java?


Pascal

-- 
1st European Lisp and Scheme Workshop
June 13 - Oslo, Norway - co-located with ECOOP 2004
http://www.cs.uni-bonn.de/~costanza/lisp-ecoop/
From: Edi Weitz
Subject: Re: The LOOP macro
Date: 
Message-ID: <m3n065ybut.fsf@bird.agharta.de>
On Wed, 24 Mar 2004 23:59:39 +0100, Andr� Thieme <······································@justmail.de> wrote:

> But to be fair, when a language X does not support a feature the
> users of X can always say that you can simply implement this
> feature. In the same time the users of language Y think: oh, we
> already have this and this looks like an advantage.  So when we can
> say: "Ok, Lisp cannot do it but we can always program it in a way so
> it gets this feature", then we can also use the same argument for
> another language which does not directly support a feature which
> Lisp supports.

No, generally you can't. You are comparing apples to oranges.

Granted, we are all Lisp zealots and we think that all other languages
are junk but take a look at this nevertheless:

1. IIRC, some (all?) Schemes have an extension to COND where you can
   write '=>' after a test form such that if the test form evaluates
   to a true value the function behind the '=>' is applied to the
   result of the test form. You want that in Common Lisp? Wait...

     * (defmacro cond* (&rest conditions)
         (let ((=var= (gensym)))
           `(let (,=var=)
             (cond
               ,@(loop for condition in conditions
                       when (and (symbolp (second condition))
                                 (string= (symbol-name (second condition))
                                          "=>"))
                       collect (list `(setq ,=var= ,(first condition))
                                     `(funcall ,(third condition) ,=var=))
                       else
                       collect condition)))))

     COND*
     * (defun foo (x)
           (cond* ((eq 3 4) "Really?")
                  (x => (lambda (z) (format nil "Yes, ~A is it!" z)))
                  (t "Nothing found")))

     FOO
     * (foo nil)

     "Nothing found"
     * (foo 42)

     "Yes, 42 is it!"

2. Your code is full of dates and you'd really like to have a shortcut
   like !2001-11-09 instead of

     (ENCODE-UNIVERSAL-TIME 0 0 0 9 11 2001)

   Well, ok...

     * (defun date-reader (stream char)
         (declare (ignore char))
         (let ((exp (read stream t nil t)))
           (when (symbolp exp)
             (let ((y-m-d (nth-value 1
                            (cl-ppcre:scan-to-strings "^(\\d{4})-(\\d{2})-(\\d{2})"
                                                      (symbol-name exp)))))
               (return-from date-reader
                 (apply #'encode-universal-time 0 0 0
                        (nreverse (map 'list #'parse-integer y-m-d))))))
           (error "Ooops...")))

     DATE-READER
     * (set-macro-character #\! #'date-reader)

     T
     * !2004-03-25

     3289158000
     * (decode-universal-time *)

     0
     0
     0
     25
     3
     2004
     3
     NIL
     -1

   (Of course, these values are inserted into your code at read time,
   not at run time.)

So, OK, these are silly and probably buggy examples but I hope you get
the idea: Can you add new control structures to Java and Python or
change their read syntax without mucking with the
compiler/interpreter?  Compared to most other languages Lisp is almost
infinitely extendable.

Edi.
From: Joe Marshall
Subject: Re: The LOOP macro
Date: 
Message-ID: <hdwdd8yg.fsf@comcast.net>
Edi Weitz <···@agharta.de> writes:

> 1. IIRC, some (all?) Schemes have an extension to COND where you can
>    write '=>' after a test form such that if the test form evaluates
>    to a true value the function behind the '=>' is applied to the
>    result of the test form. You want that in Common Lisp? Wait...
>
>      * (defmacro cond* (&rest conditions)
>          (let ((=var= (gensym)))
>            `(let (,=var=)
>              (cond
>                ,@(loop for condition in conditions
>                        when (and (symbolp (second condition))
>                                  (string= (symbol-name (second condition))
>                                           "=>"))
>                        collect (list `(setq ,=var= ,(first condition))
>                                      `(funcall ,(third condition) ,=var=))
>                        else
>                        collect condition)))))
>
>      COND*
>      * (defun foo (x)
>            (cond* ((eq 3 4) "Really?")
>                   (x => (lambda (z) (format nil "Yes, ~A is it!" z)))
>                   (t "Nothing found")))
>
>      FOO
>      * (foo nil)
>
>      "Nothing found"
>      * (foo 42)
>
>      "Yes, 42 is it!"

(defun expand-cond (clause-list)
  (labels ((make-if (test consequence alternative)
             (if (eq test 't)
                 consequence
                 (if (eq test 'nil)
                     alternative
                     (if (and (consp test)
                              (eq (car test) 'NOT)
                              (consp (cdr test))
                              (not (consp (cddr test))))
                         (make-if (cadr test)
                                  alternative
                                  consequence)
                         `(IF ,test ,consequence ,alternative)))))

           (make-locally (decls body)
             (if (null decls)
                 (make-progn body)
                 `(LOCALLY ,@decls ,@body)))

           (make-progn (body)
             (if (null (cdr body))
                 (car body)
                 `(PROGN ,@body))))

    (if (consp clause-list)
        (let ((first-clause (car clause-list))
              (more-clauses (cdr clause-list)))
          (if (consp first-clause)
              (let ((test (car first-clause))
                    (consequence (cdr first-clause)))
                (if (null more-clauses)
                    (if (not (eq test 't))
                        (warn "No default clause for COND.")))
                (if (eq test 't)
                    (if more-clauses
                        (warn "Unreachable clauses in COND.")))
                (if (null consequence)
                    (let ((cv (gensym "COND-VALUE-")))
                      `(LET ((,cv ,test))
                            ,(make-if cv cv (if (null more-clauses)
                                                'NIL
                                                (expand-cond (cdr clause-list))))))
                    (if (and (symbolp (car consequence))
                             (string-equal (symbol-name (car consequence)) "=>"))
                        (if (consp (cdr consequence))
                            (if (consp (cddr consequence))
                                (error "Only one thing may follow => in COND clause")
                                (destructure-function-lambda 1 (cadr consequence)
                                  (lambda (bvl docstring declarations body)
                                    (declare (ignore docstring))
                                    (if (null more-clauses)
                                        `(LET ((,(car bvl) ,test))
                                           ,(make-if (car bvl)
                                                     (make-locally declarations body)
                                                     NIL))
                                        `(FUNCALL (OR (LET ((,(car bvl) ,test))
                                                        ,(make-if (car bvl)
                                                                  `(LAMBDA () ,@declarations ,@body)
                                                                  NIL))
                                                      (LAMBDA () ,(expand-cond (cdr clause-list)))))))
                                  (lambda () (error "Non function follows => in COND clause"
                                                    (car consequence)))))
                            (error "Nothing follows => in COND clause"))
                        (MAKE-IF test
                                 (make-progn consequence)
                                 (if (null more-clauses)
                                     'NIL
                                     (expand-cond (cdr clause-list)))))))
              (error "Illegal COND clause ~s" first-clause)))
        (if (null clause-list)
            (error "Empty COND clause.")
            (error "Improper tail ~s found in COND clauses." clause-list)))))

(defmacro cond (&rest more-clauses)
  (expand-cond more-clauses))

-- 
~jrm
From: Edi Weitz
Subject: Re: The LOOP macro
Date: 
Message-ID: <m3ekrhxoz7.fsf@bird.agharta.de>
On Thu, 25 Mar 2004 01:14:16 GMT, Joe Marshall <·············@comcast.net> wrote:

> (defun expand-cond (clause-list)
>   (labels ((make-if (test consequence alternative)
>              (if (eq test 't)
>                  consequence
>                  (if (eq test 'nil)
>                      alternative
>                      (if (and (consp test)
>                               (eq (car test) 'NOT)
>                               (consp (cdr test))
>                               (not (consp (cddr test))))
>                          (make-if (cadr test)
>                                   alternative
>                                   consequence)
>                          `(IF ,test ,consequence ,alternative)))))
>
>            (make-locally (decls body)
>              (if (null decls)
>                  (make-progn body)
>                  `(LOCALLY ,@decls ,@body)))
>
>            (make-progn (body)
>              (if (null (cdr body))
>                  (car body)
>                  `(PROGN ,@body))))
>
>     (if (consp clause-list)
>         (let ((first-clause (car clause-list))
>               (more-clauses (cdr clause-list)))
>           (if (consp first-clause)
>               (let ((test (car first-clause))
>                     (consequence (cdr first-clause)))
>                 (if (null more-clauses)
>                     (if (not (eq test 't))
>                         (warn "No default clause for COND.")))
>                 (if (eq test 't)
>                     (if more-clauses
>                         (warn "Unreachable clauses in COND.")))
>                 (if (null consequence)
>                     (let ((cv (gensym "COND-VALUE-")))
>                       `(LET ((,cv ,test))
>                             ,(make-if cv cv (if (null more-clauses)
>                                                 'NIL
>                                                 (expand-cond (cdr clause-list))))))
>                     (if (and (symbolp (car consequence))
>                              (string-equal (symbol-name (car consequence)) "=>"))
>                         (if (consp (cdr consequence))
>                             (if (consp (cddr consequence))
>                                 (error "Only one thing may follow => in COND clause")
>                                 (destructure-function-lambda 1 (cadr consequence)
>                                   (lambda (bvl docstring declarations body)
>                                     (declare (ignore docstring))
>                                     (if (null more-clauses)
>                                         `(LET ((,(car bvl) ,test))
>                                            ,(make-if (car bvl)
>                                                      (make-locally declarations body)
>                                                      NIL))
>                                         `(FUNCALL (OR (LET ((,(car bvl) ,test))
>                                                         ,(make-if (car bvl)
>                                                                   `(LAMBDA () ,@declarations ,@body)
>                                                                   NIL))
>                                                       (LAMBDA () ,(expand-cond (cdr clause-list)))))))
>                                   (lambda () (error "Non function follows => in COND clause"
>                                                     (car consequence)))))
>                             (error "Nothing follows => in COND clause"))
>                         (MAKE-IF test
>                                  (make-progn consequence)
>                                  (if (null more-clauses)
>                                      'NIL
>                                      (expand-cond (cdr clause-list)))))))
>               (error "Illegal COND clause ~s" first-clause)))
>         (if (null clause-list)
>             (error "Empty COND clause.")
>             (error "Improper tail ~s found in COND clauses." clause-list)))))
>
> (defmacro cond (&rest more-clauses)
>   (expand-cond more-clauses))

OK, I already admitted that my examples were silly and buggy - they
were hacked together in ten minutes.

But what exactly does DESTRUCTURE-FUNCTION-LAMBDA do?

Cheers,
Edi.
From: Joe Marshall
Subject: Re: The LOOP macro
Date: 
Message-ID: <ad25chjc.fsf@comcast.net>
Edi Weitz <···@agharta.de> writes:

>
> OK, I already admitted that my examples were silly and buggy - they
> were hacked together in ten minutes.
>
> But what exactly does DESTRUCTURE-FUNCTION-LAMBDA do?

Wow!  You actually read the code?

;; Tear apart a closure so that we can beta-reduce it.
(defun destructure-function-lambda (arity fl receiver if-not-function)
  "If fl is of the form (FUNCTION (LAMBDA (bound-variable-list) docstring decls body))
   invoke receiver on the bound-variable-list, docstring, decls, and the body.

   If fl is of the form (FUNCTION name), invoke receiver on a
   fake eta-expanded form.

   If fl is of the form NAME, invoke receiver on a
   fake eta-expanded form.

   Otherwise invoke if-not-function."
  (macrolet ((list-length-equals-one (list)
               `(AND (CONSP ,list)
                     (NULL (CDR ,list))))

             (list-length-greater-than-one (list)
               `(AND (CONSP ,list)
                     (CONSP (CDR ,list))))

             (is-function-form (form)
               `(AND (CONSP ,form)
                     (EQ (CAR ,form) 'FUNCTION)
                     (LIST-LENGTH-EQUALS-ONE (CDR ,form))))

             (function-form-body (function-form)
               `(CADR ,function-form))

             (is-lambda-form (form)
               `(AND (CONSP ,form)
                     (EQ (CAR ,form) 'LAMBDA)
                     (LIST-LENGTH-GREATER-THAN-ONE (CDR ,form))))

             (lambda-form-arguments (lambda-form)
               `(CADR ,lambda-form))

             (lambda-form-body (lambda-form)
               `(CDDR ,lambda-form)))

    (cl:cond ((is-function-form fl)
           (let ((pl (function-form-body fl)))
             ;; Look for `(LAMBDA ...)
             (cl:cond ((is-lambda-form pl)
                    (multiple-value-bind (docstring declarations body)
                        (split-declarations (lambda-form-body pl))
                      (funcall receiver (lambda-form-arguments pl) docstring declarations body)))

                   ;; can't fake eta expand if arity is unknown
                   ((null arity) (funcall if-not-function))

                   ((symbolp pl)                ; is something like (function foo)
                    ;; perform eta expansion
                    (let ((arglist nil))
                      (dotimes (i arity)
                        (push (gensym "ARG-") arglist))
                      (funcall receiver arglist nil nil `((,pl ,@arglist)))))

                   (t (funcall if-not-function)))))

          ;; Look for naked '(lambda ...)
          ;; treat as if it were '(function (lambda ...))
          ((is-lambda-form fl)
           (multiple-value-bind (docstring declarations body)
               (split-declarations (lambda-form-body fl))
             (funcall receiver (lambda-form-arguments fl) docstring declarations body)))

          ;; Can't fake an eta expansion if we don't know the arity.
          ((null arity) (funcall if-not-function))

          ;; Perform an ETA expansion
          ((symbolp fl)
           (let ((arglist nil))
             (dotimes (i arity)
               (push (gensym "ARG-") arglist))
             (funcall receiver arglist nil nil `((FUNCALL ,fl ,@arglist)))))

          (t (funcall if-not-function)))))

#| Example:

(defmacro my-mapc (func list)
  (destructure-function-lambda 1 func
    (lambda (bvl docstr decls body)
      (declare (ignore docstr))
      `(DOLIST (,(car bvl) ,list)
         ,@decls
         ,@body))
    (lambda ()
      (error "~s cannot be destructured." func))))

(macroexpand-1 '(my-mapc #'(lambda (x) (+ x 2)) some-list))
  =>  (DOLIST (X SOME-LIST) (+ X 2))

(macroexpand-1 '(my-mapc (lambda (x) (+ x 2)) some-list))
  =>  (DOLIST (X SOME-LIST) (+ X 2))

(macroexpand-1 '(my-mapc #'print some-list)
  =>  (DOLIST (#:ARG-9909 SOME-LIST) (PRINT #:ARG-9909))

|#

-- 
~jrm
From: André Thieme
Subject: Re: The LOOP macro
Date: 
Message-ID: <c3vguu$na2$1@ulric.tng.de>
Hallo Edi,

thanks for your nice examples.
It is very impressive how easy you can add complex behaviour to Cl which
looks to a newcomer as if it always have been there.


> So, OK, these are silly and probably buggy examples but I hope you get
> the idea: Can you add new control structures to Java and Python or
> change their read syntax without mucking with the
> compiler/interpreter?  Compared to most other languages Lisp is almost
> infinitely extendable.

To introduce new features in other languages you sometimes need very ugly
code which can become complicated. And, depending on the operation it
will not be tighly integrated into the language. For that you need Sun
or Guido. This is one of the reasons why I am here. And noone needs to
convince me, because even if other languages also allow productive
programming I already decided four months ago to become a member of the
CL world, or its followers.
However, obviously not everyone is so much fascinated of Lisp. There are 
  people who argue, that it is not good to give the developer so much
freedom. They see the Java way as the winning way, because it is always
clear that you will solve a problem by applying oop to it. Although this 
might be sometimes a little bit harder, it is not a difference of factor 
5 or even 10 and the advantage is, that your code will be compatible.
They argue, that in Lisp some people wrote a library based on functional 
programming while you are involved in an oop clos project which makes
you incompatible and you always have to rewrite already solved problems.

During reading so much about Lisp I often found this factor of 5 compared
to Java or some other languages. I thought it would be easier to find it
but now I will just dive into Norvigs PAIP and see myself.

And thanks also to Joe for providing code corrections.


Andr�
--
From: Kenny Tilton
Subject: Re: The LOOP macro
Date: 
Message-ID: <mDu8c.7302$DV6.6854@twister.nyc.rr.com>
Andr� Thieme wrote:

> Pascal Costanza wrote:
> 
>> In Lisp, you can build your own pattern matching layer on top of 
>> what's available, and make it look and behave like it was always part 
>> of the language. You can do the same for list comprehensions.
> 
> 
> Of course this is a great thing.
> But to be fair, when a language X does not support a feature the users
> of X can always say that you can simply implement this feature. 

The phrase that sailed over your newbie head by a country mile is:

    "..and make it look...like it was always part of the language"

Language X can do that for all values of (eql x 'Lisp). Which feature of 
Lisp makes that possible? You tell me, Mr. Wizard.

kt

-- 
Home? http://tilton-technology.com
Cells? http://www.common-lisp.net/project/cells/
Cello? http://www.common-lisp.net/project/cello/
From: André Thieme
Subject: Re: The LOOP macro
Date: 
Message-ID: <c3vh2s$na2$2@ulric.tng.de>
Kenny Tilton wrote:

> 
> 
> Andr� Thieme wrote:
> 
>> Pascal Costanza wrote:
>>
>>> In Lisp, you can build your own pattern matching layer on top of 
>>> what's available, and make it look and behave like it was always part 
>>> of the language. You can do the same for list comprehensions.
>>
>>
>>
>> Of course this is a great thing.
>> But to be fair, when a language X does not support a feature the users
>> of X can always say that you can simply implement this feature. 
> 
> 
> The phrase that sailed over your newbie head by a country mile is:
> 
>    "..and make it look...like it was always part of the language"
> 
> Language X can do that for all values of (eql x 'Lisp). Which feature of 
> Lisp makes that possible? You tell me, Mr. Wizard.

This is true Kenny, in other languages you can get all features but you
have not always the chance to integrate it so perfectly into the language
like you can do with Lisp. Fot that you would need the help of Sun or
Guido (for Java/Python).


Andr�
--
From: Frode Vatvedt Fjeld
Subject: Re: The LOOP macro
Date: 
Message-ID: <2hbrmm53p7.fsf@vserver.cs.uit.no>
·······@nada.kth.se (Bj�rn Lindberg) writes:

> And a condition system. And a multiple-dispatch object system. And
> proper closures. And ...

..a remotely decent number system would be a good start.

I've lately been puzzling over how the pyhtonistas are planning to
explain to "everybody" (i.e. programming neophytes that Python seems
to also target) that Python's "very high level dynamic data types"�
results in this behavior:

>>> 1/2 + 1/2              
0


� According to www.python.org. But then again, according to "How to
  Think Like a Computer Scientist: Python Version" the term "high
  level" means "not assembly language", so I guess it's consistent, in
  its own twisted way.

-- 
Frode Vatvedt Fjeld
From: Einar Fløystad Dørum
Subject: Re: The LOOP macro
Date: 
Message-ID: <87oeqlucm5.fsf@tihlde.org>
--=-=-=
Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: quoted-printable

Frode Vatvedt Fjeld <······@cs.uit.no> writes:

> ·······@nada.kth.se (Bj=F6rn Lindberg) writes:
>
>> And a condition system. And a multiple-dispatch object system. And
>> proper closures. And ...
>
> ..a remotely decent number system would be a good start.
>
> I've lately been puzzling over how the pyhtonistas are planning to
> explain to "everybody" (i.e. programming neophytes that Python seems
> to also target) that Python's "very high level dynamic data types"=B9
> results in this behavior:
>
>>>> 1/2 + 1/2=20=20=20=20=20=20=20=20=20=20=20=20=20=20
> 0
>
>
> =B9 According to www.python.org. But then again, according to "How to
>   Think Like a Computer Scientist: Python Version" the term "high
>   level" means "not assembly language", so I guess it's consistent, in
>   its own twisted way.

Well to be fair, they have decide that this is a problem, and are
planning to fix this in Python 3.0. In the meantime you can do:

>>> from __future__ import division=20=20
>>> 1/2 + 1/2
1.0

=2D-=20
Einar Fl=F8ystad D=F8rum

--=-=-=
Content-Type: application/pgp-signature

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (GNU/Linux)

iD8DBQBAYgWn7m01kHKLrOkRAjM0AJ0eLJKM/tpC5/70lolUeFPxj+flgACfQwep
G12qTWYKpmKNwuq8rxaL6XM=
=TcW2
-----END PGP SIGNATURE-----
--=-=-=--
From: Pascal Costanza
Subject: Re: The LOOP macro
Date: 
Message-ID: <c3t0rr$abs$1@newsreader2.netcologne.de>
Einar Fl�ystad D�rum wrote:

> Well to be fair, they have decide that this is a problem, and are
> planning to fix this in Python 3.0. In the meantime you can do:
> 
> 
>>>>from __future__ import division  
>>>>1/2 + 1/2
> 
> 1.0

Nope:

 >>> 1/3 + 1/3
0.66666666666666663

Even the __future__ isn't correct.

For comparison, the following is ANSI Common Lisp:

? (+ 1/3 1/3)
2/3


Pascal

-- 
1st European Lisp and Scheme Workshop
June 13 - Oslo, Norway - co-located with ECOOP 2004
http://www.cs.uni-bonn.de/~costanza/lisp-ecoop/
From: André Thieme
Subject: Re: The LOOP macro
Date: 
Message-ID: <c3t45p$314$1@ulric.tng.de>
Pascal Costanza wrote:

> 
> Einar Fl�ystad D�rum wrote:
> 
>> Well to be fair, they have decide that this is a problem, and are
>> planning to fix this in Python 3.0. In the meantime you can do:
>>
>>
>>>>> from __future__ import division  1/2 + 1/2
>>
>>
>> 1.0
> 
> 
> Nope:
> 
>  >>> 1/3 + 1/3
> 0.66666666666666663
> 
> Even the __future__ isn't correct.
> 
> For comparison, the following is ANSI Common Lisp:
> 
> ? (+ 1/3 1/3)
> 2/3
> 
> 
> Pascal
> 

This comes because you are making use of other functions which are
very easy accessible in Lisp. In Python it is a conversion to a float
and I think also the Lisp system will answer similar:
(+ (float 1/3) (float 1/3))

However, I prefer the Lisp way in this case. It has a built in support
for rational numbers and does not implicitely casts them to floats.


Andr�
--
From: Joel Ray Holveck
Subject: Re: The LOOP macro
Date: 
Message-ID: <87u1045x0d.fsf@thor.piquan.org>
> Even the __future__ isn't correct.

Yeah, but everybody's who's seen Spaceballs already knew that.  :-)

joelh
From: Frode Vatvedt Fjeld
Subject: Re: The LOOP macro
Date: 
Message-ID: <2h65ct6e48.fsf@vserver.cs.uit.no>
·······@tihlde.org (Einar Fl�ystad D�rum) writes:

>>>> from __future__ import division  
>>>> 1/2 + 1/2
> 1.0

Fascinating. This is the same behavior as Perl. Very incorrect, and I
was hoping, better described as the past rather than the future. Oh
well, I'll try to refrain from more Python-bashing in this
forum. Google even tells me they're considering some exact rational
representation. Who knows, maybe in fifteen years Python will be where
Common Lisp was fifteen years ago.

-- 
Frode Vatvedt Fjeld
From: Jacek Generowicz
Subject: Re: The LOOP macro
Date: 
Message-ID: <tyfhdwd2pbs.fsf@pcepsft001.cern.ch>
Frode Vatvedt Fjeld <······@cs.uit.no> writes:

> ·······@tihlde.org (Einar Fl�ystad D�rum) writes:
> 
> >>>> from __future__ import division  
> >>>> 1/2 + 1/2
> > 1.0
> 
> Fascinating. This is the same behavior as Perl. Very incorrect, and I
> was hoping, better described as the past rather than the future.

Well, most languages future contains a lot of Lisp's past.

> Who knows, maybe in fifteen years Python will be where Common Lisp
> was fifteen years ago.

Exactly.
From: Marco Antoniotti
Subject: Re: The LOOP macro
Date: 
Message-ID: <V3X9c.130$IJ5.115159@typhoon.nyu.edu>
Jacek Generowicz wrote:

> Frode Vatvedt Fjeld <······@cs.uit.no> writes:
> 
> 
>>·······@tihlde.org (Einar Fl�ystad D�rum) writes:
>>
>>
>>>>>>from __future__ import division  
>>>>>>1/2 + 1/2
>>>
>>>1.0
>>
>>Fascinating. This is the same behavior as Perl. Very incorrect, and I
>>was hoping, better described as the past rather than the future.
> 
> 
> Well, most languages future contains a lot of Lisp's past.
> 
> 
>>Who knows, maybe in fifteen years Python will be where Common Lisp
>>was fifteen years ago.
> 
> 
> Exactly.

Which brings up the Fundamental Theorem of Programming Language 
Evolution. :)

Given a language L, time t and epsilon > 0

       lim             L(t) = Common Lisp(1992) + {type inference}
t -> today + epsilon


Cheers
--
marco
From: John Thingstad
Subject: Re: The LOOP macro
Date: 
Message-ID: <opr5m2ebf1xfnb1n@news.chello.no>
Funny I thought it was:

'Estimated time' * 2 * (inexperinced? 2.17 1)

;)

On Mon, 29 Mar 2004 10:15:02 -0500, Marco Antoniotti <·······@cs.nyu.edu> 
wrote:

> Which brings up the Fundamental Theorem of Programming Language 
> Evolution. :)
>
> Given a language L, time t and epsilon > 0
>
>        lim             L(t) = Common Lisp(1992) + {type inference}
> t -> today + epsilon
>
>
> Cheers
> --
> marco
>



-- 
Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
From: Jacek Generowicz
Subject: Re: The LOOP macro
Date: 
Message-ID: <tyflllp2pfw.fsf@pcepsft001.cern.ch>
Frode Vatvedt Fjeld <······@cs.uit.no> writes:

> I've lately been puzzling over how the pyhtonistas are planning to
> explain to "everybody" (i.e. programming neophytes that Python seems
> to also target) that Python's "very high level dynamic data types"�
> results in this behavior:
> 
> >>> 1/2 + 1/2              
> 0

They are planning on making that behaviour go away:

Python 2.2.2 (#1, Feb  8 2003, 12:11:31) 
[GCC 3.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 1/2 + 1/2
0
>>> from __future__ import division
>>> 1/2 + 1/2
1.0
>>> 
From: André Thieme
Subject: Re: The LOOP macro
Date: 
Message-ID: <c3sr90$sgo$1@ulric.tng.de>
Jacek Generowicz wrote:

> Andr� Thieme  <······································@justmail.de> writes:
> 
> 
>>Karl Pfl�sterer wrote:
>>
>>I don't know if I am interpreting Norvig correctly on this one, but for
>>me it seems he mainly sees one advantage of Lisp over Python: speed of
>>execution. Regarding the "power" in programming it seems to me that he
>>sees them both at the top.
> 
> 
> Ah, so they've added macros to Python? Cool. I'm a bit surprised
> though, only a few months ago the folks over at c.l.py were pretty
> adamant that macros offered power which Pythonistas simply did not
> want in their language.
> 
> :-)

I was talking about what Peter Norvig said about it. On his page he said
for example:

"One message on comp.lang.python said "I never understood why LISP was a
good idea until I started playing with python." Python supports all of
Lisp's essential features except macros, and you don't miss macros all
that much because it does have eval, and operator overloading, and
regular expression parsing, so you can create custom languages that way."

http://www.norvig.com/python-lisp.html


And also interesting this retro of him:
http://www.norvig.com/Lisp-retro.html

Here he is making several concessions. We have no longer 1991, where
Lisp was the only language that supports powerfull concepts. One has to
admit that many languages learned from Lisp over the past decade.
And we should not wonder that it was a Lisper who designed Java. And
that Guido, the creator of Python was heavily inspired by Lisp when he
designed Python.

Btw, I got Norvig's PAIP book today :)
Now I will be busy for one year learning some great concepts about Lisp.


Andre
--
From: Kenny Tilton
Subject: Re: The LOOP macro
Date: 
Message-ID: <vmn8c.6655$DV6.2639@twister.nyc.rr.com>
Andr� Thieme wrote:
> Jacek Generowicz wrote:
> 
>> Andr� Thieme  <······································@justmail.de> 
>> writes:
>>
>>
>>> Karl Pfl�sterer wrote:
>>>
>>> I don't know if I am interpreting Norvig correctly on this one, but for
>>> me it seems he mainly sees one advantage of Lisp over Python: speed of
>>> execution. Regarding the "power" in programming it seems to me that he
>>> sees them both at the top.
>>
>>
>>
>> Ah, so they've added macros to Python? Cool. I'm a bit surprised
>> though, only a few months ago the folks over at c.l.py were pretty
>> adamant that macros offered power which Pythonistas simply did not
>> want in their language.
>>
>> :-)
> 
> 
> I was talking about what Peter Norvig said about it. On his page he said
> for example:
> 
> "One message on comp.lang.python said "I never understood why LISP was a
> good idea until I started playing with python." Python supports all of
> Lisp's essential features except macros, and you don't miss macros all
> that much because it does have eval, and operator overloading, and
> regular expression parsing, so you can create custom languages that way."

Tell us what you think of that "don't miss macros" remark after you are 
comfortable with macros. Norvig was just sucking up to Pythonistas to 
sell his book.

[Yes, I know, I am a mean and evil person. Hey, it's cll we're savages.]

kenneth


-- 
Home? http://tilton-technology.com
Cells? http://www.common-lisp.net/project/cells/
Cello? http://www.common-lisp.net/project/cello/
Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film
Your Project Here! http://alu.cliki.net/Industry%20Application
From: André Thieme
Subject: Re: The LOOP macro
Date: 
Message-ID: <c3t4d8$380$1@ulric.tng.de>
Kenny Tilton wrote:

> 
> 
> Andr� Thieme wrote:
> 
>> Jacek Generowicz wrote:
>>
>>> Andr� Thieme  <······································@justmail.de> 
>>> writes:
>>>
>>>
>>>> Karl Pfl�sterer wrote:
>>>>
>>>> I don't know if I am interpreting Norvig correctly on this one, but for
>>>> me it seems he mainly sees one advantage of Lisp over Python: speed of
>>>> execution. Regarding the "power" in programming it seems to me that he
>>>> sees them both at the top.
>>>
>>>
>>>
>>>
>>> Ah, so they've added macros to Python? Cool. I'm a bit surprised
>>> though, only a few months ago the folks over at c.l.py were pretty
>>> adamant that macros offered power which Pythonistas simply did not
>>> want in their language.
>>>
>>> :-)
>>
>>
>>
>> I was talking about what Peter Norvig said about it. On his page he said
>> for example:
>>
>> "One message on comp.lang.python said "I never understood why LISP was a
>> good idea until I started playing with python." Python supports all of
>> Lisp's essential features except macros, and you don't miss macros all
>> that much because it does have eval, and operator overloading, and
>> regular expression parsing, so you can create custom languages that way."
> 
> 
> Tell us what you think of that "don't miss macros" remark after you are 
> comfortable with macros. Norvig was just sucking up to Pythonistas to 
> sell his book.

Yes, I will do.
I am a bit sorry that it will take several months until I learned enough
about them, but the uni and company are very demanding in the coming months.

Do you think macros will have uses to generate php code from a Lisp program?
Christophe Turle is doing some tricks so that he can use Lisp at work by
using it to generate php code and I would be really interested in that 
too :)



> [Yes, I know, I am a mean and evil person. Hey, it's cll we're savages.]

I do not feel offended in any way by your fresh posts.

Btw, which book did Norvig want to sell to the snakes?


Andr�
--
From: Kenny Tilton
Subject: Re: The LOOP macro
Date: 
Message-ID: <Ksu8c.7301$DV6.357@twister.nyc.rr.com>
Andr� Thieme wrote:

> Kenny Tilton wrote:

> Do you think macros will have uses to generate php code from a Lisp 
> program?

No doubt.

> Christophe Turle is doing some tricks so that he can use Lisp at work by
> using it to generate php code and I would be really interested in that 
> too :)

Last two ILCs we have heard from folks using a Lisp->Java tool to do 
Java contracting.

>> [Yes, I know, I am a mean and evil person. Hey, it's cll we're savages.]
> 
> 
> I do not feel offended in any way by your fresh posts.

It is others that have excoriated me in the past for alleging that 
Norvig would engage in <gasp> marketing.

> 
> Btw, which book did Norvig want to sell to the snakes?

PAIP? I forget. he mentions it on the same page. It was a second edition 
of something originally based on Lisp.

kt

-- 
Home? http://tilton-technology.com
Cells? http://www.common-lisp.net/project/cells/
Cello? http://www.common-lisp.net/project/cello/
Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film
Your Project Here! http://alu.cliki.net/Industry%20Application
From: André Thieme
Subject: Re: The LOOP macro
Date: 
Message-ID: <c3vhpo$o0b$1@ulric.tng.de>
Kenny Tilton wrote:

> 
> 
> Andr� Thieme wrote:
> 
>> Kenny Tilton wrote:
> 
> 
>> Do you think macros will have uses to generate php code from a Lisp 
>> program?
> 
> 
> No doubt.

Great, this gives me my first task :)
I will try to make php generating tools which would enable some thousand
Lispers to make their dynamic webpages in Lis... php.
But first I need to check if productivity stays ca. the same or gets better.


> Last two ILCs we have heard from folks using a Lisp->Java tool to do
> Java contracting.

One advantage of such a generator is, that the result would be in fact
Java code, which can be maintained by the average Java coder.



>> Btw, which book did Norvig want to sell to the snakes?
> 
> PAIP? I forget. he mentions it on the same page. It was a second edition 
> of something originally based on Lisp.

Ah, now I know what you mean, yes, I also have this one:
"Artificial Intelligence: A Modern Approach" (second edition)
(AIMA instead of PAIP (which is what I have (and I like it)))

And it is in fact a great book. He only uses pseudocode in that book,
to allow everyone to read in it and to not discourage people with a lang
they don't know/like.
He reported that some people in his courses had problems to adopt the
pseudo code to Lisp and it was easier for them to understand it when it
was done in Pyhton.

He also let someone work on a Java version on all examples.
I don't know how hard this was for the programmer... I will maybe ask him.
Anyway, the code is not really so much longer than the Lisp equivalents.
Although one could expect that Lisp is much better suited for AI coding
even here its not possible to see the 5 times higher productivity. But
the length of the code does not tell the user how easy it was to write
it, or how much time it cost.


Andr�
--
From: Kenny Tilton
Subject: Re: The LOOP macro
Date: 
Message-ID: <AdK8c.7662$DV6.2160@twister.nyc.rr.com>
Andr� Thieme wrote:

>> Last two ILCs we have heard from folks using a Lisp->Java tool to do
>> Java contracting.
> 
> 
> One advantage of such a generator is, that the result would be in fact
> Java code, which can be maintained by the average Java coder.

Yes, that was a requirement they had to meet. otoh, it probably did not 
add to the challenge, since well-written code should anyway look like it 
was stamped out by a machine.

> Anyway, the code is not really so much longer than the Lisp equivalents.
> Although one could expect that Lisp is much better suited for AI coding
> even here its not possible to see the 5 times higher productivity.


PWUAAHHAHHAHAAHHA! You kill me. OK, this time I am not going to give 
away the answer: why does the length of the finished product not 
correlate with productivity of the language in which the product is 
written? Extra credit for explaining how this being a textbook 
contributes to this effect.

Please put your answer in the form of a question, since all your 
questions are in the form of answers.

k(savage)t
From: André Thieme
Subject: Re: The LOOP macro
Date: 
Message-ID: <c403pf$4hg$1@ulric.tng.de>
Kenny Tilton wrote:

> 
> 
> Andr� Thieme wrote:
> 
>>> Last two ILCs we have heard from folks using a Lisp->Java tool to do
>>> Java contracting.
>>
>>
>>
>> One advantage of such a generator is, that the result would be in fact
>> Java code, which can be maintained by the average Java coder.
> 
> 
> Yes, that was a requirement they had to meet. otoh, it probably did not 
> add to the challenge, since well-written code should anyway look like it 
> was stamped out by a machine.
> 
>> Anyway, the code is not really so much longer than the Lisp equivalents.
>> Although one could expect that Lisp is much better suited for AI coding
>> even here its not possible to see the 5 times higher productivity.
> 
> 
> 
> why does the length of the finished product not 
> correlate with productivity of the language in which the product is 
> written?

Well, from a logical point of view your implied message is not fully
correct, because there is a correlation.


> Please put your answer in the form of a question, since all your 
> questions are in the form of answers.

Also this is logically not correct, because there is at least one
question which I asked which was not masked like an answer.
Of course, your comment was just meant to entertain me, thanks.

But okay, let me answer your question with some questions:
Why is the point of a high level language to make code shorter?

Why didn't I explicitely state that I expected that Java AI code is
exactly 5 times longer than the CL equivalent?

In how many days can we expect that Cello is the standard GUI in most
big Lisps?


Andr�
--
From: Kenny Tilton
Subject: Re: The LOOP macro
Date: 
Message-ID: <rIO8c.7702$DV6.5517@twister.nyc.rr.com>
Andr� Thieme wrote:

> Kenny Tilton wrote:
> 
>>
>>
>> Andr� Thieme wrote:
>>
>>> Anyway, the code is not really so much longer than the Lisp equivalents.
>>> Although one could expect that Lisp is much better suited for AI coding
>>> even here its not possible to see the 5 times higher productivity.
>>
>> why does the length of the finished product not correlate with 
>> productivity of the language in which the product is written?
 >
> Well, from a logical point of view your implied message is not fully
> correct, because there is a correlation.

Is not. Is, too. Is not!

> But okay, let me answer your question with some questions:
> Why is the point of a high level language to make code shorter?

Notwithstanding Tilton's Law, viz. "Shorter is always better.", the 
problem is that you went from "same length" to "same productivity". HLLs 
  shorten code by collapsing what Brooks called accidental complexity 
into forms at the level of abstraction at which we want to work. Adding 
16-bit integers on a 6502 took about seven instructions. But there is 
more than accidental complexity holding down productivity, so you are 
barking up a dead end with this pointed question.

btw, I am not just picking on you. This is the essence of Lisp. This is 
the preface or chapter one of every book on Lisp, where the author gets 
a eulogy to the language off their chest.

> 
> Why didn't I explicitely state that I expected that Java AI code is
> exactly 5 times longer than the CL equivalent?

Please note that I do not want to be thought to be saying anything good 
about Java, but isn't all that fluff just so much boilerplate a Javan 
grinds out without thinking? You know, typing time is /not/ why software 
development is hard.

> In how many days can we expect that Cello is the standard GUI in most
> big Lisps?

I don't know. I have the answer in dog years, but I do not think that is 
what you are looking for.

kt

-- 
Home? http://tilton-technology.com
Cells? http://www.common-lisp.net/project/cells/
Cello? http://www.common-lisp.net/project/cello/
Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film
Your Project Here! http://alu.cliki.net/Industry%20Application
From: Pete Kirkham
Subject: Re: The LOOP macro
Date: 
Message-ID: <406463ea$0$3304$cc9e4d1f@news-text.dial.pipex.com>
Andr� Thieme wrote:
> One advantage of such a generator is, that the result would be in fact
> Java code, which can be maintained by the average Java coder.
One disadvantage of any generator is that modification of the generated 
product breaks the process; anything that has more than one release 
either has to have a clean separation of the generated and non-generated 
code, or a roundtrip facility. Roundtripping is much harder than code 
generation.

Probably not so much an issue for generating PHP, as I'd imagine you'd 
change the input to the generator to modify the PHP rather than editing 
it directly, but in general where you've responsibility for maintenance 
and enhancement you have to teach the maintainer the generator toolset.

Of course, generating a market for 'lisp for Java programmers' courses 
once the pointy haired bosses cotton on to the gains might not be a bad 
thing. There are certainly worse things that can happen to a training 
budget.


Pete
From: Jacek Generowicz
Subject: Re: The LOOP macro
Date: 
Message-ID: <tyfd6712p6y.fsf@pcepsft001.cern.ch>
Andr� Thieme  <······································@justmail.de> writes:

> And that Guido, the creator of Python was heavily inspired by Lisp
> when he designed Python.

My impression is that he denies (or used to deny) this vigorously.
From: André Thieme
Subject: Re: The LOOP macro
Date: 
Message-ID: <c3vh8g$na2$3@ulric.tng.de>
Jacek Generowicz wrote:

> Andr� Thieme  <······································@justmail.de> writes:
> 
> 
>>And that Guido, the creator of Python was heavily inspired by Lisp
>>when he designed Python.
> 
> 
> My impression is that he denies (or used to deny) this vigorously.

This is for example different with "Matz", the creator of Ruby :-)


"Some may say Ruby is a bad rip-off of Lisp or Smalltalk, and I admit 
that. But it is nicer to ordinary people."
- Matz, LL2

( at http://www.paulgraham.com/quotes.html )


Andr�
--
From: Peter Seibel
Subject: Re: The LOOP macro
Date: 
Message-ID: <m3n05yf0rj.fsf@javamonkey.com>
······@12move.de (Karl Pfl�sterer) writes:

> On 22 Mar 2004, Peter Seibel <- ·····@javamonkey.com wrote:
>
>> change. This seems more interesting because the real cost of
>> repetition is the cost of changes--if you you cut-n-paste code reuse
>> then every seemingly small change requires a lot of textual changes
>> compared to better factored code.
>
> I'm far from defending Python against Lisp but before you start
> comparing Python code to Lisp code the code should be written in a
> way which doesn't try to mimic it's written in Lisp; vice versa it
> would also be wrong.
>
>> For instance, consider adding a third predicate baz-p and
>> corresponding list to each version. In the Lisp version, we add two
>> lines and modify two:
>
>>   (loop for x in things
>>         for foo-p = (foo-p x)
>>         for bar-p = (bar-p x)
>>         for baz-p = (baz-p x)                            ; added
>>         when foo-p collect x into foos
>>         when bar-p collect x into bars
>>         when baz-p collect x into bazes                  ; added
>>         when (and foo-p bar-p baz-p) collect x into both ; modified
>>         finally (return (values foos bars bazes both)))  ; modified
>
>> But in the Python version you have to touch *every* line:
>
>>    temp = [(x,foo_p(x),bar_p(x),baz_p(x)) for x in things]
>>    ([x for (x,foo,bar,baz) in temp if foo],
>>     [x for (x,foo,bar,baz) in temp if bar],
>>     [x for (x,foo,bar,baz) in temp if baz],
>>     [x for (x,foo,bar,baz) in temp if foo and bar and baz])
>
> I don't think anyone would really write the code like that; 

Hey, me neither. Someone else had proposed it as I way of doing it. I
was just showing how it would then be affected be the need to make a
change. Just goes to show you that even in Python, There's More Than
One Way to Do It.

-Peter

-- 
Peter Seibel                                      ·····@javamonkey.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp
From: Marco Antoniotti
Subject: Re: The LOOP macro
Date: 
Message-ID: <8JC7c.119$IJ5.108730@typhoon.nyu.edu>
Andr� Thieme wrote:
> Marco Antoniotti wrote:
> 
>>> In Python you would first have to write "count-if" yourself.
>>> Let's say it is given, then I would do something like:
>>>
>>>
>>> x = [count-if(w, widgets) for w in [red-p, blue-p]]
>>> x.append(reduce(add, x))
>>
>>
>>
>> (let ((x
>>        [(count-if w widgets) such-that w in '(red-p blue-p)]))
>>   (append x (reduce '+ x)))
> 
> 
> Hallo Marco!
> 
> As I have seen so far with loop you can sometimes do things that would
> be not so easy and readable if you had used Java. And even in Python it
> can sometimes seem slightly more complicated.
> What I would really like to see if there is an example which would be
> really hard to solve even in Python.
> Maybe you have some ideas for that?

I wouldn't know, although I think something can be cooked up. I guess 
that just because you can express some obscure loop using a peculiar 
combination of features in a language, that does not mean you should use 
that combination of features in the first place.  Correctness and 
readability of code should always be given precedence to efficinecy. 
Efficiency can  be gained in a second stage.  I.e. "first get it right 
and then get it fast".

Cheers

Marco
From: Marco Antoniotti
Subject: Re: The LOOP macro
Date: 
Message-ID: <ZxF6c.112$IJ5.84159@typhoon.nyu.edu>
Andr� Thieme wrote:

> Peter Seibel wrote:
> 
>>> Do you have a good example of LOOP's power / flexibility that doesn't
>>> need much surrounding context to understand?
>>
>>
>>
>> Here are a few:
>>
>>   (loop repeat 100 collect (random 10))
> 
> 
> This first example is not overly impressive for people who work for 
> example with Python (and list comprehension):
> after importing the lib (from random import randint) I can do:
> 
> [randint(0, 10) for x in range(100)]

You mean

[(random 10) :such-that x in (range 0 100)]

after I loaded my SETL package? :)

Of course, I can (in Common Lisp) just hack away the SETL package and have

	[(random #I(x + 3*y))
		such-that (x from 20 below 7) (y from 0 below 100 by 3)]



Cheers

marco
From: Ng Pheng Siong
Subject: Re: The LOOP macro
Date: 
Message-ID: <c3qjql$thk$2@mawar.singnet.com.sg>
According to Andr� Thieme  <······································@justmail.de>:
> This first example yada yada Python yada yada
> [...]
> For the third example in Python yada yada 
> 
> I'm really looking forward for all the other good things Lisp will offer me.

For best results, to borrow a phrase heard here frequently, leave your
Python thinking behind.

To quote Paul Graham,

  But when our hypothetical Blub programmer looks in the other direction,
  up the power continuum, he doesn't realize he's looking up. What he sees
  are merely weird languages. He probably considers them about equivalent
  in power to Blub, but with all this other hairy stuff thrown in as well.
  Blub is good enough for him, because he thinks in Blub.


-- 
Ng Pheng Siong <····@netmemetic.com> 

http://firewall.rulemaker.net -+- Firewall Change Management & Version Control
http://sandbox.rulemaker.net/ngps -+- Open Source Python Crypto & SSL
From: André Thieme
Subject: Re: The LOOP macro
Date: 
Message-ID: <c3qrvi$h7h$1@ulric.tng.de>
Ng Pheng Siong wrote:

> According to Andr� Thieme  <······································@justmail.de>:
> 
>>This first example yada yada Python yada yada
>>[...]
>>For the third example in Python yada yada 
>>
>>I'm really looking forward for all the other good things Lisp will offer me.
> 
> 
> For best results, to borrow a phrase heard here frequently, leave your
> Python thinking behind.
> 
> To quote Paul Graham,
> 
>   But when our hypothetical Blub programmer looks in the other direction,
>   up the power continuum, he doesn't realize he's looking up. What he sees
>   are merely weird languages. He probably considers them about equivalent
>   in power to Blub, but with all this other hairy stuff thrown in as well.
>   Blub is good enough for him, because he thinks in Blub.
> 
> 

I know this quote quite well.
However, you must agree that this specific area that we were looking at,
the "loop" in Lisp is not all what Lisp is about. It does not offer so
substancial features that every programmer in the world will switch over
to Lisp just to get this loop construct.
And I also mentioned in some threads that I see a slight advantage of
loop, cause it is able to create temporary symbols on the fly, where the
Python solution needs the manual help of the programmer. And I pointed
out, that Lisps power is more of an incremental nature. So searching for
some tiny 5-liners will not show much.


Andr�
--
From: Rob Warnock
Subject: Re: The LOOP macro
Date: 
Message-ID: <sPudnTsfA9GRPsHd3czS-g@speakeasy.net>
Joel Ray Holveck  <·····@piquan.org> wrote:
+---------------
| Do you have a good example of LOOP's power / flexibility that doesn't
| need much surrounding context to understand?
+---------------

Not off hand. As Peter Seibel noted in a parallel reply, there's no one
specific point that "blows you away", rather, it's the accumulation of
several sub-features that interact well. But oh, what the heck, here are
a few random LOOPs extracted from some real code I'm currently working on:

    ;;; Like UTILS:JOIN-STRINGS, but specialized for quoting elements
    ;;; of SQL VALUES() subclause.
    (defun join-strings/sql-quoted (strings)
      (apply #'concatenate 'string
	     (loop for tail on strings
	       collect "'"
	       collect (sql-escape-single-quotes (car tail))
	       collect "'"
	       when (cdr tail)
		 collect ", ")))

    (defun sql-escape-single-quotes (string)
      (if (position #\' string)             ; Need to do anything at all?
	(let ((escaped (loop for c across string
			 collect c
			 when (eql c #\')
			   collect c)))
	  (coerce escaped 'string))  
	string))                   

Usage:

    > (let ((x '("Here" "is" "Bob's" "house" "and" "Charles'")))
	   (join-strings/sql-quoted x))

    "'Here', 'is', 'Bob''s', 'house', 'and', 'Charles'''"
    > 

Finally, here's one of the more complicated ones from an SQL-related
web form [just fragments]:

    (let* (...lots of setup stuff, then...
	   (adjusted-selections (join-strings selections ", "))
           (predicates 
             (loop for (key . value) in adjusted-bindings
                   and firstp = t then nil
               unless firstp 
                 collect " AND " end
               collect key
               if (equal value "[null]")
                 collect " IS NULL"
               else
                 collect (if match-ci " ILIKE " " LIKE ")
                 and collect (if match-partial "'%" "'")
                 and collect value
                 and collect (if match-partial "%'" "'")
               end))
           (sql-query (apply #'concatenate 'string
                             "SELECT "
                             (when editing? "seq, vseq, ")
                             adjusted-selections
                             " FROM contact_log WHERE vact AND "
                             predicates)))
      (if predicates
        (multiple-value-bind (query-results error)
            (do-person-query sql-query)
          ...use result...)
        (no-search-terms-error-page self s)))


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Thomas A. Russ
Subject: Re: The LOOP macro
Date: 
Message-ID: <ymiwu5csey3.fsf@sevak.isi.edu>
····@rpw3.org (Rob Warnock) writes:

>     ;;; Like UTILS:JOIN-STRINGS, but specialized for quoting elements
>     ;;; of SQL VALUES() subclause.
>     (defun join-strings/sql-quoted (strings)
>       (apply #'concatenate 'string
> 	     (loop for tail on strings
> 	       collect "'"
> 	       collect (sql-escape-single-quotes (car tail))
> 	       collect "'"
> 	       when (cdr tail)
> 		 collect ", ")))

Using some other interesting loop iteration constructs one
can even get rid of the (cdr tail) test:

(defun join-strings/sql-quoted (strings)
  (apply #'concatenate 'string
 	 (loop for glue = "" then ", "
               for item in strings
               collect glue
 	       collect "'"
 	       collect (sql-escape-single-quotes item)
 	       collect "'")))




-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: Rob Warnock
Subject: Re: The LOOP macro
Date: 
Message-ID: <RXudnYQxeO8O7P3d3czS-g@speakeasy.net>
Thomas A. Russ <···@sevak.isi.edu> wrote:
+---------------
| ····@rpw3.org (Rob Warnock) writes:
| > 	     (loop for tail on strings
...
| > 	       when (cdr tail)
| > 		 collect ", ")))
| 
| Using some other interesting loop iteration constructs one
| can even get rid of the (cdr tail) test:
| 
| (defun join-strings/sql-quoted (strings)
|   (apply #'concatenate 'string
|  	 (loop for glue = "" then ", "
|              for item in strings
|          collect glue
|  	   collect "'"
|  	   collect (sql-escape-single-quotes item)
|  	   collect "'")))
+---------------

Neat! I like it!  In fact, I'm wordering why I didn't see it before,
since I already use the "for first-time = t then nil" idiom routinely.


-Rob

p.s. That could be written just as well as:

   	 (loop for glue = "" then ", "
               AND item in strings
	   ...)

Is there any advantage/disadvantage one way or the other in this case?

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Thomas A. Russ
Subject: Re: The LOOP macro
Date: 
Message-ID: <ymismfzrzlt.fsf@sevak.isi.edu>
····@rpw3.org (Rob Warnock) writes:

> p.s. That could be written just as well as:
> 
>    	 (loop for glue = "" then ", "
>                AND item in strings
> 	   ...)
> 
> Is there any advantage/disadvantage one way or the other in this case?

Not really.  It fundamentally boils down to the LET/LET* distinction,
which only matters if the value in the iteration clauses depend on each
other.

Contrast 

(loop for i in '(a b c d e)
	  and j = i
	  collect (list i j))

  => ((A NIL) (B A) (C B) (D C) (E D))

with 

(loop for i in '(a b c d e)
	  for j = i
	  collect (list i j))

  => ((A A) (B B) (C C) (D D) (E E))


In the first case, I would normally write "and j = nil then i" just
because I don't like to rely on uninitialized values.

-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: T. Ogawa
Subject: Re: The LOOP macro
Date: 
Message-ID: <da01153a.0403221802.56bc8dc2@posting.google.com>
(xposted to c.l.python)

Here is a partial implementation/proof of concept for Python... the
remainder is left as an exercise ;-).  Working examples based on some
of the lisp examples previously posted are below.  It doesn't use
anything particularly tricky (ie: no exec/eval/__metaclass__/__new__).
 Using it is, of course, clumsier than loop for short examples where a
listcomp makes more sense, but apparently not really so for longer
ones...

[Use, share, enjoy - all at your own risk.  Do not run nuclear
reactors or medical equipment using it]

###################################### BEGIN loop.py
class Loop(list):
    class Max(object):
        def __cmp__(self, other):
            return 1

    def fix(self, item, key, default):
        if item is None:
            item = self.curr
        return item, self.d.get(key, default)
        
    def collect(self, *args,**kwds):
        try:
            key = kwds["key"]
            item = self.curr
        except KeyError:
            try:
                key, item = args
            except ValueError:
                key = "_"
                try:
                    item = args[0]
                except IndexError:
                    item = None
            
        item, val = self.fix(item, key, [])
        val.append(item)
        self.d[key] = val
        
    def summing(self, key, item=None):
        item, val = self.fix(item, key, 0)
        self.d[key] = val + item

    def minimizing(self, key, item=None):
        item, val = self.fix(item, key, self.Max())
        self.d[key] = min(val, item)

    def maximizing(self, key, item=None):
        item, val = self.fix(item, key, None)
        self.d[key] = max(val, item)

    def counting(self, key, item=None):
        self.summing(key, 1)

    def final(self):
        key = self.d.keys()[0]
        return self.d[key]

    def __init__(self, mylist):
        self.d = {}
        for elem in mylist:
            self.curr = elem
            self.each()
        final = self.final()
        if isinstance(final, str):
            self.append(final)
        else:
            try:
                self.extend(final)
            except TypeError:
                self.append(final)
    
    def __getattr__(self, attr):
        if attr in self.d:
            return self.d[attr]
        return []
    
###################################### END loop.py

from random import random as rand

# Rob Warnock no.1
#
# def listcomp_js(mystrings):
#     ", ".join(["'%s'"%word.replace("'", "''") for word in
mystrings])

class FixQuotes(Loop):
    class Escape(Loop):
        def each(self):
            self.collect()
            if self.curr == "'":
                self.collect()

        def final(self):
            return "".join(self._)
        
    def each(self):
        self.collect("'%s'" % self.Escape(self.curr)[0])


def join_strings(mystrings):
    return ", ".join(FixQuotes(mystrings))

x = ["Here", "is", "Bob's", "house", "and", "Charles'"]
print join_strings(x)
print


# Peter Siebel no. 1
#
# print [rand() for i in range(10)]

class MyLoop(Loop):
    def each(self):
        self.collect(rand())
print MyLoop(range(10))
print


# Peter Siebel no. 2
class MyLoop(Loop):
    def each(self):
        self.minimizing("mymin")
        self.maximizing("mymax")
        self.summing("mysum")
        self.counting("mylen")

    def final(self):
        return self.mymin, self.mymax, self.mysum/float(self.mylen)
print MyLoop(range(100))
print


# Widget setup for the next examples
class Widget(object):
    def __init__(self):
        if rand() > 0.5:
            self.is_good = True
            self.colour = "red"
            self.is_foo = True
            self.is_bar = False
        else:
            self.is_bar = True
            self.is_good = False
            self.colour = "blue"
            if rand() > 0.5:
                self.is_foo = True
            else:
                self.is_foo = False
widgets = [Widget() for i in range(10)]


# Peter Siebel no. 3
#
# print [w for w in widgets if w.is_good]

class MyLoop(Loop):
    def each(self):
        widget = self.curr
        if widget.is_good:
            self.collect(widget)
print MyLoop(widgets)
print


# Peter Siebel no. 4
class MyLoop(Loop):
    def each(self):
        widget = self.curr
        if widget.colour == "red":
            self.counting("red")
        elif widget.colour == "blue":
            self.counting("blue")
        self.counting("total")

    def final(self):
        return self.red, self.blue, self.total
print MyLoop(widgets)
print


# Peter Siebel no. 5b
class MyLoop(Loop):
    def each(self):
        widget = self.curr
        is_foo = widget.is_foo
        is_bar = widget.is_bar 
        if is_foo:
            self.collect(key="foos")
        if is_bar:
            self.collect(key="bars")
        if is_foo and is_bar:
            self.collect(key="both")

    def final(self):
        return self.foos, self.bars, self.both

for widgetset in MyLoop(widgets):
    print widgetset
From: Marco Antoniotti
Subject: Re: The LOOP macro
Date: 
Message-ID: <4060721E.2030803@cs.nyu.edu>
You GOT to be kidding :)

Cheers


T. Ogawa wrote:

> (xposted to c.l.python)
> 
> Here is a partial implementation/proof of concept for Python... the
> remainder is left as an exercise ;-).  Working examples based on some
> of the lisp examples previously posted are below.  It doesn't use
> anything particularly tricky (ie: no exec/eval/__metaclass__/__new__).
>  Using it is, of course, clumsier than loop for short examples where a
> listcomp makes more sense, but apparently not really so for longer
> ones...
> 
> [Use, share, enjoy - all at your own risk.  Do not run nuclear
> reactors or medical equipment using it]
> 
> ###################################### BEGIN loop.py
> class Loop(list):
>     class Max(object):
>         def __cmp__(self, other):
>             return 1
> 
>     def fix(self, item, key, default):
>         if item is None:
>             item = self.curr
>         return item, self.d.get(key, default)
>         
>     def collect(self, *args,**kwds):
>         try:
>             key = kwds["key"]
>             item = self.curr
>         except KeyError:
>             try:
>                 key, item = args
>             except ValueError:
>                 key = "_"
>                 try:
>                     item = args[0]
>                 except IndexError:
>                     item = None
>             
>         item, val = self.fix(item, key, [])
>         val.append(item)
>         self.d[key] = val
>         
>     def summing(self, key, item=None):
>         item, val = self.fix(item, key, 0)
>         self.d[key] = val + item
> 
>     def minimizing(self, key, item=None):
>         item, val = self.fix(item, key, self.Max())
>         self.d[key] = min(val, item)
> 
>     def maximizing(self, key, item=None):
>         item, val = self.fix(item, key, None)
>         self.d[key] = max(val, item)
> 
>     def counting(self, key, item=None):
>         self.summing(key, 1)
> 
>     def final(self):
>         key = self.d.keys()[0]
>         return self.d[key]
> 
>     def __init__(self, mylist):
>         self.d = {}
>         for elem in mylist:
>             self.curr = elem
>             self.each()
>         final = self.final()
>         if isinstance(final, str):
>             self.append(final)
>         else:
>             try:
>                 self.extend(final)
>             except TypeError:
>                 self.append(final)
>     
>     def __getattr__(self, attr):
>         if attr in self.d:
>             return self.d[attr]
>         return []
>     
> ###################################### END loop.py
> 
> from random import random as rand
> 
> # Rob Warnock no.1
> #
> # def listcomp_js(mystrings):
> #     ", ".join(["'%s'"%word.replace("'", "''") for word in
> mystrings])
> 
> class FixQuotes(Loop):
>     class Escape(Loop):
>         def each(self):
>             self.collect()
>             if self.curr == "'":
>                 self.collect()
> 
>         def final(self):
>             return "".join(self._)
>         
>     def each(self):
>         self.collect("'%s'" % self.Escape(self.curr)[0])
> 
> 
> def join_strings(mystrings):
>     return ", ".join(FixQuotes(mystrings))
> 
> x = ["Here", "is", "Bob's", "house", "and", "Charles'"]
> print join_strings(x)
> print
> 
> 
> # Peter Siebel no. 1
> #
> # print [rand() for i in range(10)]
> 
> class MyLoop(Loop):
>     def each(self):
>         self.collect(rand())
> print MyLoop(range(10))
> print
> 
> 
> # Peter Siebel no. 2
> class MyLoop(Loop):
>     def each(self):
>         self.minimizing("mymin")
>         self.maximizing("mymax")
>         self.summing("mysum")
>         self.counting("mylen")
> 
>     def final(self):
>         return self.mymin, self.mymax, self.mysum/float(self.mylen)
> print MyLoop(range(100))
> print
> 
> 
> # Widget setup for the next examples
> class Widget(object):
>     def __init__(self):
>         if rand() > 0.5:
>             self.is_good = True
>             self.colour = "red"
>             self.is_foo = True
>             self.is_bar = False
>         else:
>             self.is_bar = True
>             self.is_good = False
>             self.colour = "blue"
>             if rand() > 0.5:
>                 self.is_foo = True
>             else:
>                 self.is_foo = False
> widgets = [Widget() for i in range(10)]
> 
> 
> # Peter Siebel no. 3
> #
> # print [w for w in widgets if w.is_good]
> 
> class MyLoop(Loop):
>     def each(self):
>         widget = self.curr
>         if widget.is_good:
>             self.collect(widget)
> print MyLoop(widgets)
> print
> 
> 
> # Peter Siebel no. 4
> class MyLoop(Loop):
>     def each(self):
>         widget = self.curr
>         if widget.colour == "red":
>             self.counting("red")
>         elif widget.colour == "blue":
>             self.counting("blue")
>         self.counting("total")
> 
>     def final(self):
>         return self.red, self.blue, self.total
> print MyLoop(widgets)
> print
> 
> 
> # Peter Siebel no. 5b
> class MyLoop(Loop):
>     def each(self):
>         widget = self.curr
>         is_foo = widget.is_foo
>         is_bar = widget.is_bar 
>         if is_foo:
>             self.collect(key="foos")
>         if is_bar:
>             self.collect(key="bars")
>         if is_foo and is_bar:
>             self.collect(key="both")
> 
>     def final(self):
>         return self.foos, self.bars, self.both
> 
> for widgetset in MyLoop(widgets):
>     print widgetset
From: Ng Pheng Siong
Subject: Re: The LOOP macro
Date: 
Message-ID: <c3qjg6$thk$1@mawar.singnet.com.sg>
According to Joel Ray Holveck  <·····@piquan.org>:
> Whenever I tell my (non-Lisp) friends about LOOP, I find it hard to
> come up with an on-the-spot example that demonstrates its power.  It's
> almost always something that can be written just as easily using
> Perl's "for" (which can behave as our FOR V IN L, or our FOR V = X
> THEN Y WHILE Z, like C's for).

LispWorks' CommonSQL (and UncommonSQL) have LOOP extensions. Following
example cribbed from LW docu:

(loop
  for (name) being each record in [select [ename] :from [emp]]
  as salary = (gethash name *salary-table*)
  initially (format t "~&~20A~10D" 'name 'salary)
  when (and salary (> salary 20000))
   count salary into salaries
   and sum salary into total
   and do (format t "~&~20A~10D" name salary)
  else
   do (format t "~&~20A~10A" name "N/A")
  finally
   (format t "~2&Av Salary: ~10D" (/ total salaries)))


-- 
Ng Pheng Siong <····@netmemetic.com> 

http://firewall.rulemaker.net -+- Firewall Change Management & Version Control
http://sandbox.rulemaker.net/ngps -+- Open Source Python Crypto & SSL
From: Barry Margolin
Subject: Re: The LOOP macro (was Re: Be afraid of XML)
Date: 
Message-ID: <barmar-D825E1.14230313032004@comcast.ash.giganews.com>
In article <·················@david-steuber.com>,
 David Steuber <·············@verizon.net> wrote:

> The C for loop is so much simpler for me to understand.

That's hardly surprising.  It performs a simple task, and has a very 
simple syntax.  LOOP tries to accomplish much more, and needs to be more 
complex as a result.

The thing that has always bugged me about C's for loop is that the order 
of the 2nd and 3rd clauses (the end-test and the variable iteration) 
seemed backward, and there's nothing in the syntax that helps you to 
remember which is which (contrast it with PL/I and Algol's "from ... by 
... to ..." syntax, which was adopted into LOOP).

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
From: David Steuber
Subject: Re: The LOOP macro (was Re: Be afraid of XML)
Date: 
Message-ID: <m21xnw73q6.fsf@david-steuber.com>
Barry Margolin <······@alum.mit.edu> writes:

> The thing that has always bugged me about C's for loop is that the order 
> of the 2nd and 3rd clauses (the end-test and the variable iteration) 
> seemed backward, and there's nothing in the syntax that helps you to 
> remember which is which (contrast it with PL/I and Algol's "from ... by 
> ... to ..." syntax, which was adopted into LOOP).

Interesting.  I always found the order quite natural.  First the
initializers are evaluated, then the while clause is evaluated, and
finally the steppings are evaluated.  It's not unlike how it might be
coded in assembler.

-- 
Those who do not remember the history of Lisp are doomed to repeat it,
badly.

> (dwim x)
NIL
From: ··········@YahooGroups.Com
Subject: Re: The LOOP macro (was Re: Be afraid of XML)
Date: 
Message-ID: <REM-2004mar14-001@Yahoo.Com>
> From: Barry Margolin <······@alum.mit.edu>
> Date: Sat, 13 Mar 2004 14:23:03 -0500
> The thing that has always bugged me about C's for loop is that the
> order of the 2nd and 3rd clauses (the end-test and the variable
> iteration) seemed backward, and there's nothing in the syntax that
> helps you to remember which is which

And one of the standard textbooks doesn't help either. See Forouzan &
Gilberg "A structured programming course using C", second edition
(2001), ISBN 0-534-37482-4, flowcharts on page 240 (with some arrows
added by me to make the flow clearer, and + at each bend in line):

Left diagram:
               |
               V
         -------------
       /      | expr1 \  false
 +--->< expr3 |-------->---->+
 ^     \      | expr2 /      |
 |       -------------       |
 |              | true       |
 |              V            |
 |        +-----------+      |
 |        | statement |      |
 |        +-----------+      |
 |              |            |
 |              V            |
 +<-------------+            |
                             V
                +<-----------+
                |
                V
Bad things about that diagram:
(1) The three expressions aren't physically placed in the same sequence
as in source code, so it's of no use to aid memorizing which is which;
(2) The false clause seems to be coming out from the mess *before*
expr2 is evaluated, when in fact expr2 is the value tested zero/nonzero
(fake boolean) to see whether it's false or true respectively;
(3) The arrows entering the top mess at points expr1 and expr3 do show
which get executed first (initially, and after each loop,
respectively), and the arrow slightly displaced to the right from the
boundary between expr3 and expr2 does show that expr2 is last before
the statement executes, but that still doesn't show clearly that
control then passes from expr1 or expr3 to expr2 *only*, never from
expr1 to expr3 or vice versa;

Right diagram:
           |
           V
       +-------+
       | expr1 |
       +-------+
           |
           V
        /-----\ false
  +--->< expr2 >-->+
  ^     \-----/     |
  |        | true   |
  |        V        |
  |  +-----------+  |
  |  | statement |  |
  |  +-----------+  |
  |        |        |
  |        V        |
  |    +-------+    |
  |    | expr3 |    |
  |    +-------+    |
  |        |        |
  |        V        |
  +<-------+        |
                    V
           +<-------+
           |
           V

At least the flowchart makes the flow clear, and the three expressions
are shown in the correct linear sequence, but:
Bad things about that diagram:
(1) The three expressions are shown vertically, rather thna
horizontally as is usual in the syntax;
(2) There's a big gap between expr2 and expr3, which might mislead the
programmer into remembering the syntax as:
  for (expr1; expr2) statement (expr3)
Or if the syntax is remembered, it's hard to remember where in the
diagram to insert the statement.

When I was taking that class from that book, I had to invent my own
version of that diagram to remember the relation between flowchart and
C syntax:
     |
     V
  +-------+    /---------\    +-------+
  | expr1 |--><   expr2   ><--| expr3 |
  +-------+    \---------/    +-------+
             false |  | true      ^
                   V  |           |
     +<------------+  |           |
     |                V           |
     |          +-----------+     |
     |          | statement |     |
     |          +-----------+     |
     |                |           |
     |                V           |
     |                +---------->+
     |
     V
That's a bit nonstandard, having both branches of the conditional test
coming out the bottom instead of one out the bottom and one out the
side, but otherwise does that help everyone remember how the syntax
fits the flow, in case you ever are required to (yuk) write in C again?

> contrast it with PL/I and Algol's "from ... by ... to ..." syntax,
> which was adopted into LOOP

And LOOP in LISP has the added advantage that the many key words within
the LOOP-macro syntax are *not* reserved words within the entire
language as they presumably are in those other languages, in fact even
within a LOOP expression they aren't even reserved words in the sense
of affecting the parser. They only affect the semantics after the
parser is all done and EVAL or COMPILE is in control.
From: Jens Axel Søgaard
Subject: Re: The LOOP macro (was Re: Be afraid of XML)
Date: 
Message-ID: <4054de01$0$780$edfadb0f@dread11.news.tele.dk>
··········@YahooGroups.Com wrote:

> That's a bit nonstandard, having both branches of the conditional test
> coming out the bottom instead of one out the bottom and one out the
> side, but otherwise does that help everyone remember how the syntax
> fits the flow, in case you ever are required to (yuk) write in C again?

Another is to think of FOR as a WHILE with an initialization expression.

In a similar way I think if DO as DO-UNTIL to remember how the test works.

-- 
Jens Axel S�gaard
From: Pascal Bourguignon
Subject: Re: The LOOP macro (was Re: Be afraid of XML)
Date: 
Message-ID: <87vfl7knwx.fsf@thalassa.informatimago.com>
··········@YahooGroups.Com draw nice diagrams.


And in my case, I learned to build loops starting with the stop
condition, then the increment, then the initialization.

    (loop :stop-when (<= 10 i)
          :increment (incf i)   (print i)
          :initialy  (setq i 0) (terpri))

    (assert
       (and (informally  integers from 1 to 10 have been printed on a new line))
            (<= 10 i))


But I never had any difficulties in writting it in other orders such as:

    (setq i 0) (terpri)
    (while (not (<= 10 i))
        (incf i) (print i))
    
    (assert
       (and (informally  integers from 1 to 10 have been printed on a new line))
            (<= 10 i))


-- 
__Pascal_Bourguignon__                     http://www.informatimago.com/
There is no worse tyranny than to force a man to pay for what he doesn't
want merely because you think it would be good for him.--Robert Heinlein
http://www.theadvocates.org/
From: John Thingstad
Subject: Re: The LOOP macro (was Re: Be afraid of XML)
Date: 
Message-ID: <opr4y33lz1xfnb1n@news.chello.no>
On Sat, 13 Mar 2004 14:23:03 -0500, Barry Margolin <······@alum.mit.edu> 
wrote:

The C loop is more simular to do.
Think a cobol loop to find simular functionality.

> In article <·················@david-steuber.com>,
>  David Steuber <·············@verizon.net> wrote:
>
>> The C for loop is so much simpler for me to understand.
>
> That's hardly surprising.  It performs a simple task, and has a very
> simple syntax.  LOOP tries to accomplish much more, and needs to be more
> complex as a result.
>
> The thing that has always bugged me about C's for loop is that the order
> of the 2nd and 3rd clauses (the end-test and the variable iteration)
> seemed backward, and there's nothing in the syntax that helps you to
> remember which is which (contrast it with PL/I and Algol's "from ... by
> ... to ..." syntax, which was adopted into LOOP).
>



-- 
Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
From: jan
Subject: Re: Be afraid of XML
Date: 
Message-ID: <uy8q4laws.fsf@iprimus.com.au>
Espen Vestre <·····@*do-not-spam-me*.vestre.net> writes:

> Still, there seems to be a common conception that "lisp is rocket
> science", i.e. not possible to even learn for the foot soldier
> programmer.

That reminded me of this quote by John Carmack:

 "When I started reading about aerospace, I realized there was an
incredible level of things to learn. ... There's this mytholigization
of aerospace that it's the hardest thing you can do. That's just not
true. In terms of actual difficulty, it's not that hard. Aerospace is
plumbing with the volume turned up."

-- 
jan
From: Joe Marshall
Subject: Lisp is hard.  Let's go shopping!
Date: 
Message-ID: <ad2jyr5i.fsf_-_@comcast.net>
Espen Vestre <·····@*do-not-spam-me*.vestre.net> writes:

> Still, there seems to be a common conception that "lisp is rocket
> science", i.e. not possible to even learn for the foot soldier
> programmer. 

There seems to be a common conception that `programming is easy,
anyone can do it'.  But programming is an art and the problem isn't
`doing it', but `doing it well'.  Some of the smartest people I know
are computer hackers and none of them --- not a single one --- can
reliably write more than a page of code without making an error.
Software projects are usually very late, extremely expensive, and full
of bugs.

The fact is, programming a computer well is *damn hard* and probably
*is* beyond the capabilities of the `foot soldier' programmer.

Languages such as Java provide a rigid framework to help you program.
Languages such as Lisp interfere with the user as little as possible.
`Object oriented programming', `UML', `patterns of design', etc. are
the `paint by number' of programming.  Lisp is the blank canvas.  A
blank canvas is much harder to paint, but that's not the fault of the
canvas.

-- 
~jrm
From: Rob Warnock
Subject: Re: Lisp is hard.  Let's go shopping!
Date: 
Message-ID: <zUOdnUY4n9lCL8jd3czS-g@speakeasy.net>
Joe Marshall  <·············@comcast.net> wrote:
+---------------
| There seems to be a common conception that `programming is easy,
| anyone can do it'.  But programming is an art and the problem isn't
| `doing it', but `doing it well'.
...
| The fact is, programming a computer well is *damn hard* and probably
| *is* beyond the capabilities of the `foot soldier' programmer.
+---------------

I hate to sound like a broken record by dragging out Dijkstra quotes
again so soon [barely two months ago, oddly enough in response to
something else you wrote], but as he said[1]:

        "Programming is one of the most difficult branches of applied
        mathematics; the poorer mathematicians had better remain pure
        mathematicians."


-Rob

[1] Edsger W. Dijkstra, "How do we tell truths that might hurt?" (1975)
    <URL:http://www.cs.utexas.edu/users/EWD/ewd04xx/EWD498.PDF>
    <URL:http://www.cs.virginia.edu/~evans/cs655/readings/ewd498.html>

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Jens Axel Søgaard
Subject: Re: Lisp is hard.  Let's go shopping!
Date: 
Message-ID: <4055b74f$0$745$edfadb0f@dread11.news.tele.dk>
Rob Warnock wrote:

>         "Programming is one of the most difficult branches of applied
>         mathematics; the poorer mathematicians had better remain pure
>         mathematicians."

As long as the poorer computer scientists doesn't do mathematics,
no harm is done.

-- 
Jens Axel S�gaard
From: Will Hartung
Subject: Re: Lisp is hard.  Let's go shopping!
Date: 
Message-ID: <c352qd$240v6v$1@ID-197644.news.uni-berlin.de>
"Joe Marshall" <·············@comcast.net> wrote in message
····················@comcast.net...
> Espen Vestre <·····@*do-not-spam-me*.vestre.net> writes:
>
> > Still, there seems to be a common conception that "lisp is rocket
> > science", i.e. not possible to even learn for the foot soldier
> > programmer.
>
> There seems to be a common conception that `programming is easy,
> anyone can do it'.  But programming is an art and the problem isn't
> `doing it', but `doing it well'.  Some of the smartest people I know
> are computer hackers and none of them --- not a single one --- can
> reliably write more than a page of code without making an error.
> Software projects are usually very late, extremely expensive, and full
> of bugs.
>
> The fact is, programming a computer well is *damn hard* and probably
> *is* beyond the capabilities of the `foot soldier' programmer.
>
> Languages such as Java provide a rigid framework to help you program.
> Languages such as Lisp interfere with the user as little as possible.
> `Object oriented programming', `UML', `patterns of design', etc. are
> the `paint by number' of programming.  Lisp is the blank canvas.  A
> blank canvas is much harder to paint, but that's not the fault of the
> canvas.

That's the difference between Programmers (IMHO) and Scripters. Scripters
glue the blocks together. The better ones can worth with less coarse blocks,
but are knitting blocks together nonetheless.

Scipters can do amazing things today. As long as the gross mechanations of
the blocks they're sticking together work, they can be productive for
business today. But when things go awry, they're doomed.

For good or ill, a vast majority of the computing needs in many of today
businesses can ALMOST be handled entirely by Scripters. The large platforms
have enough material to assemble most anything.

.NET exemplifies this to the utmost today, as it makes assembling disparate
components written in different languages that much easier. So, you can take
C++ and C# bricks and use VB as mortar more easily than you could before.
Even before interfacing VB to a COM object wasn't a painless experience.

Java with tools is Scripter friendly, yet still flexible enough to be
Programmer friendly (though the modern App servers are plain hostile to
everyone). But Java isn't as Scripter friendly as .NET.

Regards,

Will Hartung
(·····@msoft.com)
From: Tayssir John Gabbour
Subject: Re: Lisp is hard.  Let's go shopping!
Date: 
Message-ID: <866764be.0403151457.18386028@posting.google.com>
Joe Marshall <·············@comcast.net> wrote in message news:<···············@comcast.net>...
> Languages such as Java provide a rigid framework to help you program.
> Languages such as Lisp interfere with the user as little as possible.
> `Object oriented programming', `UML', `patterns of design', etc. are
> the `paint by number' of programming.  Lisp is the blank canvas.  

I have an economic view of programming.

The reason for programming languages was to increase the supply of
programmers.  Decreasing dependence on a few skilled mathematicians. 
So languages tend to look like what a high-schooler might have seen.

Similar to Microsoft increasing the number of computer users with
Windows.

As programming becomes more complicated however, two things may
happen:
- Graphic tools evolve so coding to a lisp datastructure no longer
involves parens or special chars.
- Programmers will give up on the incredible complexity of unnatural
syntax, as app size increases.  They become bold enough to define
appropriate notation.  Compsci will leave the shadow of mathematics.
From: Will Hartung
Subject: Re: Lisp is hard.  Let's go shopping!
Date: 
Message-ID: <c35k2e$24c1ra$1@ID-197644.news.uni-berlin.de>
"Tayssir John Gabbour" <···········@yahoo.com> wrote in message
·································@posting.google.com...
> Joe Marshall <·············@comcast.net> wrote in message
news:<···············@comcast.net>...

> As programming becomes more complicated however, two things may
> happen:
> - Graphic tools evolve so coding to a lisp datastructure no longer
> involves parens or special chars.

This assumes ye olde classic "It's the Syntax Stupid" argument about many
languages, not just Lisp. For each of those complaining about special
chracters, there are those who loathe the wordiness of COBOL. STUFF THIS IN
YOUR PIPE AND SMOKE IT vs pipe->stuff(this), smoke;

GUI coding will never happen on a wide scale. It's simply inefficient.
Unless They ever come up with a more efficient device than the keyboard,
GUIs will never enter this domain and be mainstream. Dragging IFs around
would be pure Hell. We can stare in awe at the interfaces in 'Minority
Report', but I tell you that if it were me, I'd get pretty tired standing
there and holding my arms unsupported in the air for hours.

> - Programmers will give up on the incredible complexity of unnatural
> syntax, as app size increases.  They become bold enough to define
> appropriate notation.  Compsci will leave the shadow of mathematics.

But none of these modern notations offer enough detail to actually get the
job done, otherwise we'd be "coding in UML", and it ain't happening. The
granularity of these diagrams doesn't come anywhere near what is necessary
for modern systems. There's a lot of hand waving and "something magic
happens" bubbles on these diagrams.

Application Generators, CASE Tools, "DWIM" systems, Large Application
"frameworks" all seem to do amazing things during demos but then simply fail
when they're deployed, because they can not capture the intricacies of
modern business. And its the intricacies of modern business that makes
modern systems difficult, not programming per se.

The tools most certainly help. I'm a big fan of them. When you need to write
generic maintenance programs for 100 DB tables, I'm all for "wizards",
"reflection", etc. But they only solve the easy parts of the problem because
that's all they CAN solve. They can't "intuit" the "hard parts". It's hard
enough to get the problem specs in ENGLISH much less translate them to
something else and have it "figure" them out.

The eternal "what I asked for and not what I wanted" cycle of refinement is
done with fine hand tools, not sledgehammers and bulldozers.

Those diagrams and tools are "easy" specifically BECAUSE they lack detail.
"Here's our system" laid out in 10 blocks with arrows. How hard can it be?"
Well, when one of the boxes is labeled "pricing module", you don't want to
know how hard it can be. Ever see offers with "Free Shipping*"? That '*' is
what smashes these kinds of tools to flinders. "Free shipping EVERYWHERE!
(well, not Alaska, Hawaii. And not Canada. We don't ship to Mexico)".

Programming is not getting "more complicated". Get data, change data, store
data. Von Neuman. Some environments do it better than others. Those
environments that promote more abstraction do it better than those that do
not, IMHO. As the architectures get more complicated, the libraries catch
up. What was once a difficult CGI or Apache module is now a simple Servlet
or .NET module.

But getting the brain of "Marge, who's been in accounting for the past 20
years and remembers customer invoices from 15 years ago, and knows the Chart
like the back of her hand (including those one off accounts that Bob The
Controller likes to stick things into...sometimes)" stuffed into a computer.
THAT is hard.

And it always will be. NSB.

Regards,

Will Hartung
(·····@msoft.com)
From: Tayssir John Gabbour
Subject: Re: Lisp is hard.  Let's go shopping!
Date: 
Message-ID: <866764be.0403160251.775ffde4@posting.google.com>
"Will Hartung" <·····@msoft.com> wrote in message news:<···············@ID-197644.news.uni-berlin.de>...
> GUI coding will never happen on a wide scale. It's simply inefficient.
> Unless They ever come up with a more efficient device than the keyboard,
> GUIs will never enter this domain and be mainstream. Dragging IFs around
> would be pure Hell. We can stare in awe at the interfaces in 'Minority
> Report', but I tell you that if it were me, I'd get pretty tired standing
> there and holding my arms unsupported in the air for hours.

We already are.  These little glyphs we program with today... we imbue
them with a lot of meaning.  Our distinction between text and graphics
is mainly arbitrary and I'm sure we'll see the effect of this.

We often use invisible function stacks; most languages are just
reinventing dynamic vars and the Conditions System, and I strongly
think programming is limited because most people can't visualize the
stack.


> But none of these modern notations offer enough detail to actually get the
> job done, otherwise we'd be "coding in UML", and it ain't happening. The
> granularity of these diagrams doesn't come anywhere near what is necessary
> for modern systems. There's a lot of hand waving and "something magic
> happens" bubbles on these diagrams.

When I'm talking about "modern notations," I'm talking about lisp. ;)

More generally, the fact that our current, beautifully parens-laden
text interface is just the tip of the iceberg.  I love the parens, I
like the fact I can create highly aesthetic code when using certain
techniques (like data-directed) -- but it is just one among the
infinite number of graphic representations of a lisp.

And so you understand, I no longer distinguish between text and
graphics, because I can essentially create ascii art with my code
text.


> Application Generators, CASE Tools, "DWIM" systems, Large Application
> "frameworks" all seem to do amazing things during demos but then simply fail
> when they're deployed, because they can not capture the intricacies of
> modern business. And its the intricacies of modern business that makes
> modern systems difficult, not programming per se.

I don't like UML.  You also assumed I liked the Minority Report
interface.  I never knew I liked these strawmen. ;)
From: Joel Ray Holveck
Subject: Re: Lisp is hard.  Let's go shopping!
Date: 
Message-ID: <87fzc56fbx.fsf@thor.piquan.org>
> We often use invisible function stacks; most languages are just
> reinventing dynamic vars and the Conditions System,

Oh, somebody else is finally picking up on conditions?  It's about
time!  Who is it?

> More generally, the fact that our current, beautifully parens-laden
> text interface is just the tip of the iceberg.

So if you had an M-exp reader, and knew how it works, you'd still
adamantly write in S-exps?  Not just write in them because you're
used to them, but *adamantly*[1] write in them?

joelh

[1] As the *...* indicates, also globally and/or specially adamant.
And you thought I was just using bold.
From: Joe Marshall
Subject: Re: Lisp is hard.  Let's go shopping!
Date: 
Message-ID: <hdwlx1dj.fsf@ccs.neu.edu>
Joel Ray Holveck <·····@piquan.org> writes:

>> We often use invisible function stacks; most languages are just
>> reinventing dynamic vars and the Conditions System,
>
> Oh, somebody else is finally picking up on conditions?  It's about
> time!  Who is it?
>
>> More generally, the fact that our current, beautifully parens-laden
>> text interface is just the tip of the iceberg.
>
> So if you had an M-exp reader, and knew how it works, you'd still
> adamantly write in S-exps?  Not just write in them because you're
> used to them, but *adamantly*[1] write in them?

I would.
From: Tim Bradshaw
Subject: Re: Lisp is hard.  Let's go shopping!
Date: 
Message-ID: <fbc0f5d1.0403190259.6f0229c3@posting.google.com>
Joel Ray Holveck <·····@piquan.org> wrote in message news:<··············@thor.piquan.org>...

> So if you had an M-exp reader, and knew how it works, you'd still
> adamantly write in S-exps?  Not just write in them because you're
> used to them, but *adamantly*[1] write in them?

I think there are commonly-available infix (maybe not m-exp in some
technical sense) readers for Lisp.  I've played with them, but the
awful truth is that I just prefer sexps.

--tim
From: Jacek Generowicz
Subject: Re: Lisp is hard.  Let's go shopping!
Date: 
Message-ID: <tyfvfl16n98.fsf@pcepsft001.cern.ch>
··········@tfeb.org (Tim Bradshaw) writes:

> Joel Ray Holveck <·····@piquan.org> wrote in message news:<··············@thor.piquan.org>...
> 
> > So if you had an M-exp reader, and knew how it works, you'd still
> > adamantly write in S-exps?  Not just write in them because you're
> > used to them, but *adamantly*[1] write in them?
> 
> I think there are commonly-available infix (maybe not m-exp in some
> technical sense) readers for Lisp.  I've played with them, but the
> awful truth is that I just prefer sexps.

Depends on what you are doing, surely ?

For hairy mathematical expressions, I certainly make use of infix
package. I shudder at the thought of not having it available for that
purpose. At the same time I am extremely grateful for the fact that
the infix package translates my source code (which looks just like my
hand-written notes, or just like Fortan, C, Python, whatever source
code[*]) into sexprs which I can manipulate with Lisp macros.

(On one occasion, it was very pleasing to copy and paste a bunch of
mathematical functions from another language, then improve the
performance of the whole lot by a factor of almost 20, by wrapping
them in a macro which replaced function calls within the original
expressions by references to their recently-calculated values[+].)

However, I've never felt the urge to use the infix package for
anything other than mathematical formulae.


[*] On occasion I have to tweak the infix package, for example some
    languages spell exponentiation thus: x^y, while others spell it
    so: "x**y".

[+] Yes, I am aware of memoization; no it isn't really appropriate in
    this case.
From: Tayssir John Gabbour
Subject: Re: Lisp is hard.  Let's go shopping!
Date: 
Message-ID: <866764be.0403191117.7a02cc95@posting.google.com>
Joel Ray Holveck <·····@piquan.org> wrote in message news:<··············@thor.piquan.org>...
> > More generally, the fact that our current, beautifully parens-laden
> > text interface is just the tip of the iceberg.
> 
> So if you had an M-exp reader, and knew how it works, you'd still
> adamantly write in S-exps?  Not just write in them because you're
> used to them, but *adamantly*[1] write in them?

Depends on who my code-reading audience is.  Programmers often create
interfaces that look nothing like the language they program in, and I
can see that extending to the sourcecode interface as well.

It might be like the tension between using a WYSIWYG tool and coding
to the bare language.  There are people in both camps, and some lone
wolves who choose based on the situation.

Still I think lisp contains a great formalism, that had not been
invented before because people didn't find a great use for
mechanically translating notation.

But do not try and hide the parens.  That's impossible.  Instead only
try to realize the truth.  There are no parens.
From: Pascal Bourguignon
Subject: Re: Lisp is hard.  Let's go shopping!
Date: 
Message-ID: <87y8pwfvvo.fsf@thalassa.informatimago.com>
···········@yahoo.com (Tayssir John Gabbour) writes:
> Depends on who my code-reading audience is.  Programmers often create
> interfaces that look nothing like the language they program in, and I
> can see that extending to the sourcecode interface as well.
> 
> It might be like the tension between using a WYSIWYG tool and coding
> to the bare language.  There are people in both camps, and some lone
> wolves who choose based on the situation.
> 
> Still I think lisp contains a great formalism, that had not been
> invented before because people didn't find a great use for
> mechanically translating notation.
> 
> But do not try and hide the parens.  That's impossible.  Instead only
> try to realize the truth.  There are no parens.

Indeed.  Let's imagine that instead of parenthesis, you'd have an
editor that would draw fine lines above the token to show the
syntactic tree.  That would take much more real estate than the
parenthesis, and editing would not be easier.

-- 
__Pascal_Bourguignon__                     http://www.informatimago.com/
There is no worse tyranny than to force a man to pay for what he doesn't
want merely because you think it would be good for him.--Robert Heinlein
http://www.theadvocates.org/
From: Tayssir John Gabbour
Subject: Re: Lisp is hard.  Let's go shopping!
Date: 
Message-ID: <866764be.0403191118.6e243659@posting.google.com>
Joel Ray Holveck <·····@piquan.org> wrote in message news:<··············@thor.piquan.org>...
> > We often use invisible function stacks; most languages are just
> > reinventing dynamic vars and the Conditions System,
> 
> Oh, somebody else is finally picking up on conditions?  It's about
> time!  Who is it?

Not great news, the dynamic var situation is better.  Apparently in
Windows Forms you can register one default errorhandler per thread, so
at least errorhandlers can be distant from where errors occur.

Combined with finally (unwind-protect) clauses, I suppose one can
create the illusion of dynamic binding.  Multithread safe since you
get one handler/thread.  And maybe you can create this monstrous
system where the errorhandler can dispatch to other "handlers."  An
ad-hoc, informally-specified bug-ridden slow implementation of half
of...

- - - -

But I love this -- people endlessly debate exceptions vs. everything
else.  So someone always pops up saying, "Hey there's this thing in
lisp..."
http://c2.com/cgi/wiki?YouDontWantAnExceptionYouWantaTimeMachine
and is promptly ignored.

No, we don't want solutions, we just love complaining!  All we really
want are multiple return values for errorcodes, which of course is a
Python Innovation.
From: Pascal Bourguignon
Subject: Re: Lisp is hard.  Let's go shopping!
Date: 
Message-ID: <87k71llcr8.fsf@thalassa.informatimago.com>
                                    :-)

"Will Hartung" <·····@msoft.com> writes:
> This assumes ye olde classic "It's the Syntax Stupid" argument about many
> languages, not just Lisp. For each of those complaining about special
> chracters, there are those who loathe the wordiness of COBOL. STUFF THIS IN
> YOUR PIPE AND SMOKE IT vs pipe->stuff(this), smoke;

I don't think that you can send several messages like this in C++, (as
you could in Smalltalk).
 

> GUI coding will never happen on a wide scale. It's simply inefficient.
> Unless They ever come up with a more efficient device than the keyboard,
> GUIs will never enter this domain and be mainstream. Dragging IFs around
> would be pure Hell. We can stare in awe at the interfaces in 'Minority
> Report', but I tell you that if it were me, I'd get pretty tired standing
> there and holding my arms unsupported in the air for hours.

On the other hand, for actors  who're used to stand holding their arms
unsupported in the air for  hours, with weights in their hands because
they've got nothing better to do,  and because that will allow them to
cash a lot more on the next  movie if they have nice biceps, it may be
quite easy to do it.  And since they've got the money, we could design
them such a user interface.

 
> Those diagrams and tools are "easy" specifically BECAUSE they lack detail.

To concur, would  you like me to show you the  class and state diagram
of  a nand  gate,  and the  object  diagram that  will implement  your
"pricing module"  with nand gate objects?  It's  perfectly possible to
do, in all detail, in UML.  With 10 million boxes in an object diagram
and the N-bazillion links.  I wonder why we don't see more UML diagram
with millions+ of classes or object boxes, though...

> Programming is not getting "more complicated". Get data, change data, store
> data. Von Neuman. Some environments do it better than others. Those
> environments that promote more abstraction do it better than those that do
> not, IMHO. As the architectures get more complicated, the libraries catch
> up. What was once a difficult CGI or Apache module is now a simple Servlet
> or .NET module.
> 
> But getting the brain of "Marge, who's been in accounting for the past 20
> years and remembers customer invoices from 15 years ago, and knows the Chart
> like the back of her hand (including those one off accounts that Bob The
> Controller likes to stick things into...sometimes)" stuffed into a computer.
> THAT is hard.
> 
> And it always will be. NSB.
> 
> Regards,
> 
> Will Hartung

-- 
__Pascal_Bourguignon__                     http://www.informatimago.com/
There is no worse tyranny than to force a man to pay for what he doesn't
want merely because you think it would be good for him.--Robert Heinlein
http://www.theadvocates.org/
From: Raymond Wiker
Subject: Re: Lisp is hard.  Let's go shopping!
Date: 
Message-ID: <86n06he1jh.fsf@raw.grenland.fast.no>
Pascal Bourguignon <····@thalassa.informatimago.com> writes:

> To concur, would  you like me to show you the  class and state diagram
> of  a nand  gate,  and the  object  diagram that  will implement  your
> "pricing module"  with nand gate objects?  It's  perfectly possible to
> do, in all detail, in UML.  With 10 million boxes in an object diagram
> and the N-bazillion links.  I wonder why we don't see more UML diagram
> with millions+ of classes or object boxes, though...

        A recent issue of one of the ACM publications has an article
called "Death by UML fever", which looks interesting. It also looks
like it might be transferable to a few other "silver bullets" :-)

-- 
Raymond Wiker                        Mail:  ·············@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/
From: Dave Benjamin
Subject: Re: Lisp is hard.  Let's go shopping!
Date: 
Message-ID: <slrnc5f7rm.909.ramen@lackingtalent.com>
In article <···············@ID-197644.news.uni-berlin.de>, Will Hartung wrote:
> 
> GUI coding will never happen on a wide scale. It's simply inefficient.
> Unless They ever come up with a more efficient device than the keyboard,
> GUIs will never enter this domain and be mainstream. Dragging IFs around
> would be pure Hell. We can stare in awe at the interfaces in 'Minority
> Report', but I tell you that if it were me, I'd get pretty tired standing
> there and holding my arms unsupported in the air for hours.

LOL!
From: Alain Picard
Subject: Re: Lisp is hard.  Let's go shopping!
Date: 
Message-ID: <87oeqyfv59.fsf@memetrics.com>
Joe Marshall <·············@comcast.net> writes:

> `Object oriented programming', `UML', `patterns of design', etc. are
> the `paint by number' of programming.  Lisp is the blank canvas. 

That is a beautiful quote.  How many Vermeers and Rembrandts were
done using "paint by number", I wonder?
From: ··@sanmartino.it.invalid
Subject: Re: Lisp is hard.  Let's go shopping!
Date: 
Message-ID: <n9my8q2e2zf.fsf@polimi.it>
Alain Picard <············@memetrics.com> writes:

> Joe Marshall <·············@comcast.net> writes:
>
>> `Object oriented programming', `UML', `patterns of design', etc. are
>> the `paint by number' of programming.  Lisp is the blank canvas. 
>
> That is a beautiful quote.  How many Vermeers and Rembrandts were
> done using "paint by number", I wonder?

<couldn't resist>
i have one such Rembrandt on my wall.  i did it myself!
<couldn't resist/>

-- 
BOMBED BY SMALL GNATS. CAPTAIN INTOXICATED. EXPLODING. U-264.
From: Rob Warnock
Subject: Re: Be afraid of XML
Date: 
Message-ID: <XOGdnYoKKbtWnc7d3czS-g@speakeasy.net>
Tim Bradshaw <··········@tfeb.org> wrote:
+---------------
| John Thingstad <··············@chello.no> wrote:
| > Java is in it own right a champion here.
| 
| I think this is to misunderstand the problem.  I have always thought
| (and I still think) that Java is an engineering masterpiece: ...
| *it's simple enough for average programmers to use*, and we know
| about average programmers.  ...you can produce substantial systems
| which sort-of run, without a functioning brain at all.
...
| Interestingly the same is historically true for Lisp: because Lisp
| implementations generally protect you against the low-level issues
| which blight C/C++ systems, average programmers can get further.
| And so `lisp is big and slow'.
+---------------

This is exactly what prompted me, circa 1972 or so[1], to coin my one
(and so far, only) "law", namely:

	Warnock's Law for Why BLISS[2] Programs are Big:

	BLISS programs are big because most space optimization is done
	as a side-effect of debugging[3], and BLISS programs tend to
	work "the first time"[3] much more often[5], so they don't
	get debugged as much, so the potential space-saving algorithm
	changes[6] that tend to be noticed during debugging... aren't.

I wasn't exposed to C until much later, but at least compared to assembler
the Law seems to apply to C as well. Not to mention Java and Lisp...  ;-}

In fact, this syndrome seem to have only gotten worse: IME it is very
rare these days for programmers -- or *anyone* -- to read "working" code.
Unless there is a bug requiring the code to be opened up, most code is
"write-only". But since is my claim that it is in the *reading* (and
understanding) of code that opportunities for significant major algorithm
or data structure changes are noticed, we find ourselves in a Catch-22:
the more productive you are in a given language and the less debugging
you do, the bigger & slower the code you deliver. (*sigh*)

Is any good news here for Lispers? Could it be that the inherent
polymorphism of dynamic typing means that the original code tends
to be smaller in the first place? Does ease of refactoring make a
subsequent space optimization pass possibly cheap enough that it
gets done? I dunno. My own code certainly seems to accrete bunches
of "prototype" code that ends up being "good enough" that it never
gets changed...


-Rob

Notes:
[1] Probably the reason no one here ever heard of it before is that it
    was just something I sometimes quipped to others at PDP-10 DECUS
    meetings, especially SIGIL sessions (Special Interest Group on
    Implementation Languages, which at the time was pretty much mostly
    BLISS users). [Ob. disclosure: I was the chairman of SIGIL for a
    couple of years, not that it matters.]

[2] BLISS (Basic Language for the Implementation of Systems Software)
    is roughly at the level of C, but with *much* better macros and data
    structures [in fact, the latter are a kind of user-defined macro, too],
    and better lower-level control of the code generated for subroutine
    linkages. It was developed by Bill Wulf & his grad students at CMU,
    initially for the PDP-10 only, then for the PDP-11 (though BLISS-11
    was a cross-compiler only, written in BLISS-10). BLISS-10 was a simple
    "min-delay/max-doer" compiler, but BLISS-11 featured *extensive*
    data- and control-flow optmization, which is covered in great detail
    in the book "The Design of an Optimizing Compiler" (Wulf, et al).
    [Note that the syntax analyzer gets only a brief mention in the book,
    since BLISS is nearly LL(1) and is thus *very* easy to parse with a
    hybrid of top-down recursive descent (for control constructs) and
    simple operator precedence (for infix expressions).]  Like Lisp,
    BLISS is an expression language; every executable statement has
    a defined value.

    DEC soon picked it up, and used it for a number of projects (the
    first was the "FORTRAN-10" compiler that replaced the previous "F40"),
    and extended it into a "Common BLISS" for the VAX (BLISS-32), PDP-10
    (BLISS-36), and the PDP-11 (BLISS-16, still only as a cross-compiler).

    The users were outraged that FORTRAN-10 was *huge* compared to F40
    (though it *did* provide massively-better optimization), and complained
    to DEC about the increased memory requirement for running the compiler
    (and other BLISS code).
    
[3] At least as programming was practiced in the 1970's, though I dare
    say that phrase is still true today.

[4] Or at least with very much less debugging.

[5] ...than the alternative languages being used for comparable tasks.
    BLISS tended to be used for large projects, such as compilers and
    large "system utilities" (e.g., batch systems), and later, for large
    portions of operating systems -- things for which, up until then,
    had tended to be written entirely in assembler langauge. [To be sure,
    the MACRO-10 assembler had a *marvelous* macro system that could do
    significant amounts of computation at compile time. It was very easy
    to write well-structured code in MACRO-10.]

[6] As we all know, major optimizations -- whether space or time --
    don't usually come from tweaking the code at the level of individual
    statements (or expressions), but usually from major algorithm or data
    structure changes.

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Pete Kirkham
Subject: Re: Be afraid of XML
Date: 
Message-ID: <405104a7$0$3311$cc9e4d1f@news-text.dial.pipex.com>
It takes a particular kind of paranoia that you think someone's ironic 
response to a mis-application of a technology is an application of said 
technology (the point of the article was it's a stupid idea to put JVM 
stack traces into XML syntax, so exaggerate the concept and put the 
whole of the JVM into XML). But then someone here believed the spoof XML 
encoding of bits as well.

Please try and remember
- not everyone who uses lingua-franca technologies is an idiot
- not everyone on the planet writes in languages that can be encoded in 
  the ASCII charset, so delimited Unicode for marking up text is hardly evil
- if using a tree structure represented by delimited text for data is 
bad, why are you using lisp?
- it is possible to map s-expressions to a subset of the XML infoset, so 
anything you do with s-expr is just XML with minor syntactic differences 
(around 5% smaller size for a loss of some syntactic redundancy for 
textual applications, data-intensive are better done in binary anyway 
once debugged in a textual format). This also means that there is 50 
years prior art for any patent for XAML or XUL as programming language 
(or at least as far back as the first lisp WIMP GUI).
- XML is a general tree syntax suitable for world-wide use. XML is a 
pruned scion of SGML so it has angle brackets and closing tags (if you 
are marking up text, then you don't want to escape every parenthesis).
Is <para id="foo">Hello World</para> so much worse than (para :id "foo" 
:text "Hello World")? Is the idea of using an application independent 
reader so bad (SAX)? or allowing arbitrary declarative transformations 
of the resulting parse tree (XSLT) expressed in the same syntax, so the 
code and the data are one? Yes, XML's ended up doing most the same 
things as s-expr, the lisp reader and macros did, but on the web, in the 
same syntax family as an enormously popular document markup language.

If s-expr are so much better as an interchange language, then make apps 
that integrate with the existing infrastructure and have improved 
capabilities over their XML counterparts.

It is easier to write '(apply #'+ '(1 2 3)) than the math-ml equivalent, 
but there isn't a standard for integrating that as a display language in 
a browser, nor standard s-expr symbols for most of the symbols in 
math-ml. So why isn't s-expr being used as a human interface language 
for math on the web? If the syntax mattered, and the symbolic algebra 
community are aware of lisp, then shouldn't there already be s-expr 
interfaces for math-ml. Instead, each math package exports to a common 
standard, and as the need for integrating with html (otherwise export to 
TeX) is important, the syntax of this common standard is in the same family.

Why is OWL being used when it's not as capable as KIF*? KIF is s-expr, 
and designed for interchange. Neither have to be directly displayed in a 
browser. But KIF doesn't fit in with the existing web toolset, and 
people seem willing to add to the SG/HT/X-ML syntax family rather than 
integrate different ones- even though much of semweb is coded from 
scratch, and in lisp as often as not. But to use KIF on the web, you 
have to munge all case-sensitive URIs and escape Unicode; so it has 
"does not play well with others" on its report card. As with the main 
declarative XML languages (XHTML, XSD, XSLT, MathML, SVG, XForms), 
having the programming language in the same syntax as the data is seen 
as an advantage, just as in lisp.

In terms of technology, syntax doesn't matter; in terms of how easily a 
user can interact with a language, it does. The current crop of code 
cutters grew up with HTML. People can relearn given incentives, but some 
of the postings here are bugs caused by parenthesis nesting.

I think that selling a 21st century lisp which uses s-expr as an 
abbreviated XML has mileage. Or a direct XML encoding of lisp s-expr as 
a 'web programming language'. Allow the same abstract tree to be encoded 
as s-expr, XML, ASN.1, RDBMS tables for coding, browser integration, 
data exchange and persistence. Let the web monkeys use XML until they 
know how to match the parentheses. Map the object system to and from UML 
in an explicit manner, and provide model-driven, pattern based and 
aspect oriented programming as language level facilities. In a couple of 
years, almost everyone will be using a single dispatch bytecode 
environment (CLR, if not Java). Make a lisp that accepts that limitation.

Sometimes the people here (and in the XML world) sound like it actually 
matters how pointy the delimiters in the syntax are. Get over it, and 
work the technology at the abstract level, not the text. S-expr are a 
syntax that represents an abstract tree. So is XML. Use the acceptance 
of standard readers and macro languages to take lisp further. Use the 
experience of the lisp community to not reinvent technologies, with only 
a syntax change.


Pete

* actually the use cases for the semantic web indicate that OWL is 
closer to being in the same niche as EXPRESS rather than KIF, though it 
never seems to be compared to it; possibly because getting applications 
to exchange information reliably using a common information model isn't 
as sexy as a world-wide ontology based artificial intelligence.
From: Tim Bradshaw
Subject: Re: Be afraid of XML
Date: 
Message-ID: <fbc0f5d1.0403120639.315074f9@posting.google.com>
Pete Kirkham <·················@cafemosaic.co.uk> wrote in message news:<························@news-text.dial.pipex.com>...

> Sometimes the people here (and in the XML world) sound like it actually 
> matters how pointy the delimiters in the syntax are. Get over it, and 
> work the technology at the abstract level, not the text. S-expr are a 
> syntax that represents an abstract tree. So is XML. Use the acceptance 
> of standard readers and macro languages to take lisp further. Use the 
> experience of the lisp community to not reinvent technologies, with only 
> a syntax change.

Ah, but Lisp people could never do that, because it would destroy the
whole remantic myth of Lisp as a lost-cause which could have changed
the world if it wasn't for the hordes of barbarian Java/XML
programmers with their clubs with nails in, leather armour and
powerful smell.  It's very important for most Lisp people (Kenny
Tilton being an honourable exception, although I suspect he does wear
leather armour) that Lisp *not* succeed.
From: Kenny Tilton
Subject: Re: Be afraid of XML
Date: 
Message-ID: <2pl4c.15843$c73.5154620@twister.nyc.rr.com>
Tim Bradshaw wrote:

> Ah, but Lisp people could never do that, because it would destroy the
> whole remantic myth of Lisp as a lost-cause which could have changed
> the world if it wasn't for the hordes of barbarian Java/XML
> programmers with their clubs with nails in, leather armour and
> powerful smell.  It's very important for most Lisp people (Kenny
> Tilton being an honourable exception, although I suspect he does wear
> leather armour) that Lisp *not* succeed.

Yes, a belching, smelly armpit-scratching, beer-guzzling American 
application programmer will succeed where all the pointy-headed, 
abstract-formulizing, non-existent office-houring, Ivory tower academic 
geniuses failed. Down here in the sewer I hammer out more code in a 
month with my club than most Comp Sci professors write in a year in the 
little time they have left over from torturing grad students on the 
rack. It was the Romans who spread Christianity, then the barbarians, 
then the English (the upgraded barabrians) with their lovely Crusades, 
and now Mel Gibson, America's answer to Shakespeare. Hmmm, come to think 
of it, the Sermon on the Mount does seem to have been reduced along the 
way to fine print. Point taken.

As for the smell over here, one shower means a hundred less lines of 
code for Cello. And why bother? Nothing will get out the smell of all 
these monkeys.

Eeep!

kt

ps. Omigod! GL_SPHERE_MAP! Y'all gonna flip.

-- 
http://tilton-technology.com

Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film

Your Project Here! http://alu.cliki.net/Industry%20Application
From: Pete Kirkham
Subject: Re: Be afraid of XML
Date: 
Message-ID: <40530c95$0$3308$cc9e4d1f@news-text.dial.pipex.com>
Tim Bradshaw wrote:
> Ah, but Lisp people could never do that, because it would destroy the
> whole remantic myth of Lisp as a lost-cause which could have changed
> the world if it wasn't for the hordes of barbarian Java/XML
> programmers with their clubs with nails in, leather armour and
> powerful smell.
Given that a lot of the SGML and XML community includes people who, if 
not zealots, are lisp programmers, and that Java was invented by the guy 
whose previous projects were Sun's emacs and a semi-declarative macro 
engine for auto generation of gui toolkits, I have a sneaking suspicion 
that lisp _has_ changed the world, and Java/XML is the result.


Pete
From: Kenny Tilton
Subject: Re: Be afraid of XML
Date: 
Message-ID: <AWG4c.16024$c73.5682929@twister.nyc.rr.com>
Pete Kirkham wrote:

> Tim Bradshaw wrote:
> 
>> Ah, but Lisp people could never do that, because it would destroy the
>> whole remantic myth of Lisp as a lost-cause which could have changed
>> the world if it wasn't for the hordes of barbarian Java/XML
>> programmers with their clubs with nails in, leather armour and
>> powerful smell.
> 
> Given that a lot of the SGML and XML community includes people who, if 
> not zealots, are lisp programmers, and that Java was invented by the guy 
> whose previous projects were Sun's emacs and a semi-declarative macro 
> engine for auto generation of gui toolkits, I have a sneaking suspicion 
> that lisp _has_ changed the world, and Java/XML is the result.

"It's a fine line between stupid and clever." -- Spinal Tap


-- 
http://tilton-technology.com

Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film

Your Project Here! http://alu.cliki.net/Industry%20Application
From: Jeff Dalton
Subject: Re: Be afraid of XML
Date: 
Message-ID: <fx4d66xk5uo.fsf@todday.inf.ed.ac.uk>
··········@tfeb.org (Tim Bradshaw) writes:

> Pete Kirkham <·················@cafemosaic.co.uk> wrote in message
> news:<························@news-text.dial.pipex.com>...

> > work the technology at the abstract level, not the text. S-expr are a 
> > syntax that represents an abstract tree. So is XML. Use the acceptance 
> > of standard readers and macro languages to take lisp further. Use the 
> > experience of the lisp community to not reinvent technologies, with only 
> > a syntax change.

> Ah, but Lisp people could never do that, because it would destroy the
> whole remantic myth of Lisp as a lost-cause which could have changed
> the world if it wasn't for the hordes of barbarian Java/XML
> programmers with their clubs with nails in, leather armour and
> powerful smell.  It's very important for most Lisp people (Kenny
> Tilton being an honourable exception, although I suspect he does wear
> leather armour) that Lisp *not* succeed.

Is that some sort of ironic comment, or do you really mean it?

Who are these people for whom it is very important that Lisp
*not* succeed?

So far as I know, I have never encountered anyone like that
within the Lisp community, though there are for sure many
outside.

-- jd
From: Tim Bradshaw
Subject: Re: Be afraid of XML
Date: 
Message-ID: <fbc0f5d1.0403290229.79ed25ff@posting.google.com>
Jeff Dalton <····@todday.inf.ed.ac.uk> wrote in message news:<···············@todday.inf.ed.ac.uk>...
> 
> Who are these people for whom it is very important that Lisp
> *not* succeed?

Many posters to cll give the strong impression that they'd rather sit
there and complain than actually do something.  There are just endless
`I can't use Lisp because ...' threads (`there's no standard interface
to x', `pathnames have some theoretical deficiency', `it was all
better on the lisp machines' `vendor x charges too much', `cmucl
doesn't run on windows, we need to spend lots of money to make it do
so rather than use one of the several offerings that do, because
they're commercial (hiss) / ideologically unsound (hiss hiss)').

I don't understand these people.  My current theory is that they
actually don't *want* lisp to succeed, because it gives them an excuse
not to do anything: if lisp was successful then they'd have to face
the awful fact that they *have no ideas*.  Maybe this theory is wrong,
but it's the best I have.

(My theory comes partly from my experience writing relatively large
Lisp programs - a few 10s of thousands of lines, so not huge, but not
tiny - which did all sorts of OS-type stuff (talk down sockets, parse
XML, build makefiles, run make &c &c). The lisp-doesn't-have-x
problems were total non issues: what stopped me getting rich from this
thing was that it didn't do stuff that enough people wanted.)

--tim
From: Pascal Bourguignon
Subject: Re: Be afraid of XML
Date: 
Message-ID: <8765cn2942.fsf@thalassa.informatimago.com>
··········@tfeb.org (Tim Bradshaw) writes:

> Jeff Dalton <····@todday.inf.ed.ac.uk> wrote in message news:<···············@todday.inf.ed.ac.uk>...
> > 
> > Who are these people for whom it is very important that Lisp
> > *not* succeed?
> 
> Many posters to cll give the strong impression that they'd rather sit
> there and complain than actually do something.  There are just endless
> `I can't use Lisp because ...' threads (`there's no standard interface
> to x', `pathnames have some theoretical deficiency', `it was all
> better on the lisp machines' `vendor x charges too much', `cmucl
> doesn't run on windows, we need to spend lots of money to make it do
> so rather than use one of the several offerings that do, because
> they're commercial (hiss) / ideologically unsound (hiss hiss)').
> 
> I don't understand these people.  My current theory is that they
> actually don't *want* lisp to succeed, because it gives them an excuse
> not to do anything: if lisp was successful then they'd have to face
> the awful fact that they *have no ideas*.  Maybe this theory is wrong,
> but it's the best I have.

No. You don't see the point of these posts.  At least in my case, the
point is to know what you cannot do in COMMON-LISP, what you must do
outside of COMMON-LISP.  Sometimes COMMON-LISP is deceptive because it
seems to promise functionality when in fact it just presents a nice
window and leaves the shop to the implementations.  Unfortunately, the
quality of the goods depends on the shop. You've got a nice box with a
beautiful label named DIRECTORY, but when you open the box you've got
a toy that break in this case or in that case just depending on the
shop where you bought it.  On the other hand, it gives you other toys,
such as CONS and CAR that work the same even if bought in other towns.
 

> (My theory comes partly from my experience writing relatively large
> Lisp programs - a few 10s of thousands of lines, so not huge, but not
> tiny - which did all sorts of OS-type stuff (talk down sockets, parse
> XML, build makefiles, run make &c &c). The lisp-doesn't-have-x
> problems were total non issues: what stopped me getting rich from this
> thing was that it didn't do stuff that enough people wanted.)

Actually, I would be happier if COMMON-LISP had less features, and if
it only had features 100% formally specified that always behave
identically in all  implementations.


Common-Lisp-2010 could be a subset of COMMON-LISP augmented with a
standard FFI.


-- 
__Pascal_Bourguignon__                     http://www.informatimago.com/
There is no worse tyranny than to force a man to pay for what he doesn't
want merely because you think it would be good for him.--Robert Heinlein
http://www.theadvocates.org/
From: Tim Bradshaw
Subject: Re: Be afraid of XML
Date: 
Message-ID: <fbc0f5d1.0403290801.5797e2fe@posting.google.com>
Pascal Bourguignon <····@thalassa.informatimago.com> wrote in message news:<··············@thalassa.informatimago.com>...

> 
> No. You don't see the point of these posts.  At least in my case, the
> point is to know what you cannot do in COMMON-LISP, what you must do
> outside of COMMON-LISP.  Sometimes COMMON-LISP is deceptive because it
> seems to promise functionality when in fact it just presents a nice
> window and leaves the shop to the implementations.  Unfortunately, the
> quality of the goods depends on the shop. You've got a nice box with a
> beautiful label named DIRECTORY, but when you open the box you've got
> a toy that break in this case or in that case just depending on the
> shop where you bought it.  On the other hand, it gives you other toys,
> such as CONS and CAR that work the same even if bought in other towns.

Right.  So you post endless whining messages to cll, while I and
others define the functionality our applications need, and write some
possibly implementation-dependent wrappers which provide it for our
application.  In the specific case of directory-manipulation stuff, I
think this was several 10s of lines (including verbose comments
specifying the intended semantics) out of sreveral 10s of thousands of
lines of code for me.  If I had to port the application to another
Lisp, it would presumably be another few 10s of lines.

You have made my point better than I ever could have, thank you.
From: John Thingstad
Subject: Re: Be afraid of XML
Date: 
Message-ID: <opr5m4a1usxfnb1n@news.chello.no>
Let's put it this way.

   (let* ((dir-string (namestring (current-directory)))
	 (search-string (concatenate 'string dir-string  "/*"))
	 (files (directory (truename search-string))))
     (dolist (file files)
       (fresh-line)
       (princ (concatenate 'string (pathname-name file) "." (pathname-type 
file))))
     (terpri)
     (values)))

(defun pwd ()
   (write-line (namestring (current-directory)))
   (values))

(defun up-dir-p (dir) (and (>= (length dir) 2) (string= (subseq dir 0 2) 
"..")))

(defun count-up-dirs (dir)
   (let ((count 0))
     (loop while (up-dir-p dir) do
	  (incf count)
	  (if  (> (length dir) 2)
	      (setf dir (subseq dir 3))
	    (return-from count-up-dirs (values count nil))))
     (values count dir)))

(defun move-up-dirs (count)
   (let ((current-dir (namestring (current-directory))))
     (dotimes (i count)
       (setf current-dir (subseq current-dir 0
				(position #\\ current-dir
					  :end (- (length current-dir) 2)
					  :from-end t))))
     current-dir))

(defun cd (dir)
   (check-type dir string)
   (when (up-dir-p dir)
     (multiple-value-bind (count new-dir) (count-up-dirs dir)
       (setf (current-directory) (move-up-dirs count))
       (setf dir new-dir)))
   (when dir (setf (current-directory) (truename dir)))
   (values))

(defun del (file)
   (check-type file string)
   (delete-file (truename file))
   (values))

(defun ren (file1 file2)
   (check-type file1 string)
   (check-type file2 string)
   (rename-file (truename file1) (truename file2))
   (values))


On 29 Mar 2004 08:01:50 -0800, Tim Bradshaw <··········@tfeb.org> wrote:

> Pascal Bourguignon <····@thalassa.informatimago.com> wrote in message 
> news:<··············@thalassa.informatimago.com>...
>
  > Right.  So you post endless whining messages to cll, while I and
> others define the functionality our applications need, and write some
> possibly implementation-dependent wrappers which provide it for our
> application.  In the specific case of directory-manipulation stuff, I
> think this was several 10s of lines (including verbose comments
> specifying the intended semantics) out of sreveral 10s of thousands of
> lines of code for me.  If I had to port the application to another
> Lisp, it would presumably be another few 10s of lines.
>
> You have made my point better than I ever could have, thank you.
-- 
Using M2, Opera's revolutiona

ry e-mail client: http://www.opera.com/m2/
From: Christian Lynbech
Subject: Re: Be afraid of XML
Date: 
Message-ID: <ofu107zucp.fsf@situla.ted.dk.eu.ericsson.se>
>>>>> "Pascal" == Pascal Bourguignon <····@thalassa.informatimago.com> writes:

Pascal> At least in my case, the point is to know what you cannot do
Pascal> in COMMON-LISP, what you must do outside of COMMON-LISP.

Does this mean COMMON-LISP the language or COMMON-LISP the package?

Pascal> You've got a nice box with a beautiful label named DIRECTORY,
Pascal> but when you open the box you've got a toy that break in this
Pascal> case or in that case just depending on the shop where you
Pascal> bought it.

Can you be a bit more specific? What makes DIRECTORY so fragile that
it deserves to be the canonical example?



------------------------+-----------------------------------------------------
Christian Lynbech       | christian ··@ defun #\. dk
------------------------+-----------------------------------------------------
Hit the philistines three times over the head with the Elisp reference manual.
                                        - ·······@hal.com (Michael A. Petonic)
From: Pascal Bourguignon
Subject: Re: Be afraid of XML
Date: 
Message-ID: <87oeqfzsgn.fsf@thalassa.informatimago.com>
Christian Lynbech <·················@ericsson.com> writes:

> >>>>> "Pascal" == Pascal Bourguignon <····@thalassa.informatimago.com> writes:
> 
> Pascal> At least in my case, the point is to know what you cannot do
> Pascal> in COMMON-LISP, what you must do outside of COMMON-LISP.
> 
> Does this mean COMMON-LISP the language or COMMON-LISP the package?
> 
> Pascal> You've got a nice box with a beautiful label named DIRECTORY,
> Pascal> but when you open the box you've got a toy that break in this
> Pascal> case or in that case just depending on the shop where you
> Pascal> bought it.
> 
> Can you be a bit more specific? What makes DIRECTORY so fragile that
> it deserves to be the canonical example?


http://www.lisp.org/HyperSpec/Body/fun_directory.html
CLHS says that:

    If the attempt to obtain a directory listing is not successful,
    an error of type file-error is signaled.


But it does not specify what should happen if only a part of the
directory listing can be retrieved. Some implementations may return
the partial list, some may raise an error.

For example, clisp returns an error:

[12]> (directory "/tmp/**/*")
*** - UNIX error 13 (EACCES): Permission denied


Only because 3 directories can't be read among 9705 files and
directories:

$ find /tmp/|wc -l
find: /tmp/essai: Permission denied
   7701

Needless to say that I won't be running my programs under root
just because of a sloppy standard definition...

So, DIRECTORY is useless (with "**"), and we have to implement our own
directory walking.



Also, note that for the "*", sbcl returns a list of directory and
files without "type", while clisp returns all files:

* (length (directory "/tmp/**/*"))

541

* (directory "/tmp/**/*")

(#P"/tmp/.ICE-unix/" #P"/tmp/.X0-lock" #P"/tmp/.X11-unix/"
 #P"/tmp/.X11-unix/X0" #P"/tmp/AcroujVnEv" #P"/tmp/Acrox6AM3i"
 #P"/tmp/XMMSpjb/" #P"/tmp/XMMSuSE/" #P"/tmp/a" #P"/tmp/acl62_trial/"
 #P"/tmp/acl62_trial/alisp" #P"/tmp/acl62_trial/ansicl/"
 #P"/tmp/acl62_trial/ansicl/chapter/" #P"/tmp/acl62_trial/ansicl/dictentr/"
 #P"/tmp/acl62_trial/ansicl/glossary/" #P"/tmp/acl62_trial/ansicl/images/"
 #P"/tmp/acl62_trial/ansicl/indexcha/" #P"/tmp/acl62_trial/ansicl/meta/"
...)


[21]> (length (directory "/tmp/**/*"))
7406

[22]> (directory "/tmp/**/*")
(#P"/tmp/acl62_trial/examples/checklinks/checklinks.cl"
 #P"/tmp/acl62_trial/examples/checklinks/deliver.cl"
 #P"/tmp/acl62_trial/examples/checklinks/Makefile"
 #P"/tmp/acl62_trial/examples/streams/rot13b.cl"
...)




-- 
__Pascal_Bourguignon__                     http://www.informatimago.com/
There is no worse tyranny than to force a man to pay for what he doesn't
want merely because you think it would be good for him.--Robert Heinlein
http://www.theadvocates.org/
From: Tim Bradshaw
Subject: Re: Be afraid of XML
Date: 
Message-ID: <ey3wu5370dt.fsf@cley.com>
* Pascal Bourguignon wrote:

> But it does not specify what should happen if only a part of the
> directory listing can be retrieved. Some implementations may return
> the partial list, some may raise an error.

Come on, it's just bloody obvious that some kind of error must be
signalled. Do you *seriously* want directory enumeration to return
partial results with no way of telling that they're partial?

> So, DIRECTORY is useless (with "**"), and we have to implement our own
> directory walking.

Right.  That's Unix for you.

Look.  No one is claiming that CL's approach to enumerating
directories is perfect.  Why don't you either propose a better
interface, or *go away*.

--tim
From: Pascal Bourguignon
Subject: Re: Be afraid of XML
Date: 
Message-ID: <87vfkmxnp7.fsf@thalassa.informatimago.com>
Tim Bradshaw <···@cley.com> writes:

> * Pascal Bourguignon wrote:
> 
> > But it does not specify what should happen if only a part of the
> > directory listing can be retrieved. Some implementations may return
> > the partial list, some may raise an error.
> 
> Come on, it's just bloody obvious that some kind of error must be
> signalled. Do you *seriously* want directory enumeration to return
> partial results with no way of telling that they're partial?
> 
> > So, DIRECTORY is useless (with "**"), and we have to implement our own
> > directory walking.
> 
> Right.  That's Unix for you.
> 
> Look.  No one is claiming that CL's approach to enumerating
> directories is perfect.  Why don't you either propose a better
> interface, or *go away*.

The interface is ok. 
It's the semantics specifications that are lacking!

I don't *go away*, I just record some notes for COMMON-LISP-2010.



-- 
__Pascal_Bourguignon__                     http://www.informatimago.com/
There is no worse tyranny than to force a man to pay for what he doesn't
want merely because you think it would be good for him.--Robert Heinlein
http://www.theadvocates.org/
From: Christian Lynbech
Subject: Re: Be afraid of XML
Date: 
Message-ID: <87oeqe9m1s.fsf@baguette.defun.dk>
>>>>> "Pascal" == Pascal Bourguignon <····@thalassa.informatimago.com> writes:

>> Come on, it's just bloody obvious that some kind of error must be
>> signalled. Do you *seriously* want directory enumeration to return
>> partial results with no way of telling that they're partial?

Pascal> The interface is ok. 
Pascal> It's the semantics specifications that are lacking!

I still don't udnerstand, where is the problem with the semantics?

If something goes wrong, directory will signal an error. The
definition of "something" will necessary vary as this is depending on
the outside of lisp, ie. the OS.

CLs DIRECTORY is no worse of than UNIXs READDIR since this does not
try to work recursively and if you restrict your usage of DIRECTORY to
that, the problems go away, no?

If UNIX semantics is what you want, you can always appeal to the UNIX
routines, it should be a very small problem to tie in READDIR into
Lisp. CMUCL presumably has it already and UFFI allows you to do a
cross-implementation library.

After all, CLs pathname abstraction tries to be something to everybody
across a vast stretch of different OSs instead of working by the much
more common all-directory-components-are-separated-by-backslashes kind
of thinking prevailing in many applications.

I think it would be quite a challenge to come with a firm semantic
specification that captures that without effectively reducing it to
a-pathanme-is-a-sequence-of-characters which is not going improve the
karma of common-lisp 2010 applications (the semantics may be
welldefined but it just moves the problem over to the programmers).

------------------------+-----------------------------------------------------
Christian Lynbech       | christian ··@ defun #\. dk
------------------------+-----------------------------------------------------
Hit the philistines three times over the head with the Elisp reference manual.
                                        - ·······@hal.com (Michael A. Petonic)
From: Jeff Dalton
Subject: Re: Be afraid of XML
Date: 
Message-ID: <fx44qs73e4m.fsf@todday.inf.ed.ac.uk>
··········@tfeb.org (Tim Bradshaw) writes:

> Jeff Dalton <····@todday.inf.ed.ac.uk> wrote in message
> news:<···············@todday.inf.ed.ac.uk>...
> > 
> > Who are these people for whom it is very important that Lisp
> > *not* succeed?
> 
> Many posters to cll give the strong impression that they'd rather sit
> there and complain than actually do something.  There are just endless
> `I can't use Lisp because ...' threads (`there's no standard interface
> to x', `pathnames have some theoretical deficiency', `it was all
> better on the lisp machines' `vendor x charges too much', `cmucl
> doesn't run on windows, we need to spend lots of money to make it do
> so rather than use one of the several offerings that do, because
> they're commercial (hiss) / ideologically unsound (hiss hiss)').

Sounds like normal usenet behaviour to me.  :)

Or :(

Also, some of those sound like legitimate complaints.

There are a lot of things I can do in Java that I can't do
in Lisp without going to particular implementations or writing
a lot of code that is just to build infrastructure: that isn't
really part of what I'm trying to do.

For example, you mentioned parsing XML.  I couldn't justify
spending my time on writing an XML parser.  Perhaps there's an
XML parser out there that I could use, though the last time
I looked there wasn't one that had licensing terms I could
work with.

And even if I got all that straightened out, I might have
trouble getting it to work on Windows; and on all "platforms"
I might have to tell people wanting to use it that they would
have to get and install the relevant Lisp.

You said "lisp-doesn't-have-x problems were total non issues"
for you; but they are very far from non-issues for me and
presumably for quite a few other people.

They weren't a serious obstacle for me back when I was using
Lisp all the time.  When I wanted an HTTP server, I wrote one.
When I needed to generate HTML, I wrote something for that.
(Even then, if I'd needed a GUI, I'd have been in trouble.)

There are many reasons why these problems affect me more now than they
used to, and it might be useful to try to work out what those reasons
are and how they work -- but right now my point is a different one.

It's this: people who are able to use Lisp, for whatever reasons --
people in that furtunate situation -- will naturally tend to feel that
the obstacles to using Lisp are minor.

But people who are not able to get into that fortunate situation
will naturally tend to see the obstacles as significant, because for
them, they were.

-- jd
From: Luke Gorrie
Subject: Re: Be afraid of XML
Date: 
Message-ID: <lhr7vbk12m.fsf@dodo.bluetail.com>
Jeff Dalton <····@todday.inf.ed.ac.uk> writes:

> It's this: people who are able to use Lisp, for whatever reasons --
> people in that furtunate situation -- will naturally tend to feel that
> the obstacles to using Lisp are minor.
>
> But people who are not able to get into that fortunate situation
> will naturally tend to see the obstacles as significant, because for
> them, they were.

The two groups are probably often looking at different obstacles,
too. I suspect that the people who have succeeded in using Lisp have
tended to choose their obstacles wisely, as well as having good
fortune.

In particular I think it's more strategic to work hard at getting
involved with the Lisp that's already around than to work hard at
changing the world so that Lisp head-hunters will be banging at your
door to fill new demand. Look for people who already use Lisp and
applications that Lisp is already good for.

There is quite a bit of Lisp about, so how can one get a slice? It
could help to try getting to know the Lispers in your area and
outside, to be willing to move where the Lisp'ing is good, or to
develop and display some skills by writing free software(*). Whichever
things like this your circumstances permit seem likely to help, to me.

Much harder obstacles would be to try and find your dream Lisp job out
of the blue on hotjobs.com, or introduce Lisp into your large and
bureaucratic corporation. For this to happen would probably require
Lisp to compete in popularity with C# and Java, which is a long way
from the state of things today. Even in that world, with Lispers in
hot demand throughout the globe, it might be harder still to find a
job where you have fun and work with the sort of hackers who're doing
Lisp today.

I say this based on my experience as one of the lucky ones, with a
great job using my Lisp-like language of choice. For me it was a
combination of reasonably extreme persuit, good fortune, and the
generosity of other people (*all* were necessary). I do have friends
better qualified who aren't so fortunate, and others who have walked
right into similar jobs -- or even declined the offers. Nothing is
certain, but luck favours the prepared mind, as they say.

Just my opinion.

Cheers,
Luke

(*): I don't recall seeing hardly any prominent Lisp hackers showing
     any enthusiasm for free software, so possibly hacking away at it
     would actually be a hinderance to joining the established Lisp
     world. If that is so then I think it would be peculiar to Lisp.
From: Tim Bradshaw
Subject: Re: Be afraid of XML
Date: 
Message-ID: <ey31xnb8f7n.fsf@cley.com>
* Jeff Dalton wrote:

> There are a lot of things I can do in Java that I can't do
> in Lisp without going to particular implementations or writing
> a lot of code that is just to build infrastructure: that isn't
> really part of what I'm trying to do.

Sure, that's because a *huge* amount of effort has been poured into
the Java standard library.  I'm trying to understand why so many
so-called Lisp people (not including you) spend so much time
complaining that Lisp doesn't have these things. It's not realistic, I
think, to create a library the size of Java's in a reasonable amount
of time, but that doesn't mean progress is impossible.

It seems to me there are three reasonable approaches to problems like
this:

1. Get up and do something.

2. Decide that designing and implementing standard libraries is really
   a lot of work (which it is), and that it's generally possible to
   get close enough with application- and/or implementation-specific
   code, and just do that.  That's what I've generally done.

3. Decide that Lisp isn't the tool you need and use something else
   (this may be what you've done: it's more-or-less what I'm doing at
   present)

What I think is *not* reasonable is the fourth option of just sitting
around and complaining.  The reasons for these interface problems are
quite simple to understand, after all (basically: lack of money), and
there is something the matter with people who can't or won't
understand this and choose one of the options above.  My current
theory as to what is wrong with these people is what I described
earlier.

> For example, you mentioned parsing XML.  I couldn't justify
> spending my time on writing an XML parser.  Perhaps there's an
> XML parser out there that I could use, though the last time
> I looked there wasn't one that had licensing terms I could
> work with.

> And even if I got all that straightened out, I might have
> trouble getting it to work on Windows; and on all "platforms"
> I might have to tell people wanting to use it that they would
> have to get and install the relevant Lisp.

I agree.  When I tried to do this it didn't take me very long to get
expat working (which I think is OK license-wise), albeit with my
specific lisp implementation.  But then I realised that in order to
actually `do' XML I'd have to spend the rest of my life implementing
schemas or something, and that was just going to be a huge amount of
work.

--tim
From: Jeff Dalton
Subject: Re: Be afraid of XML
Date: 
Message-ID: <fx4ptavp5ah.fsf@todday.inf.ed.ac.uk>
Tim Bradshaw <···@cley.com> writes:

> * Jeff Dalton wrote:
> 
> > There are a lot of things I can do in Java that I can't do
> > in Lisp without going to particular implementations or writing
> > a lot of code that is just to build infrastructure: that isn't
> > really part of what I'm trying to do.
> 
> Sure, that's because a *huge* amount of effort has been poured into
> the Java standard library.

Yes, and I think Sun had to do that; but now everyone has to pay
a price, because of that, and because people are elaborating
everywhere.  Learning enough about all the things you're supposed
to use with Java is pretty much a full time job all on its own.

> I'm trying to understand why so many
> so-called Lisp people (not including you) spend so much time
> complaining that Lisp doesn't have these things.

Because it doesn't?  Because for many people that now matters?
Because discussing why Lisp is less successful or useful than
we'd like, and what might make a difference, is natural in a
Lisp newsgroup?

Perhaps I haven't followed c.l.l closely enough, but I don't
think we're forced to entertain explanations such as: people
want Lisp to lose.  Except of course for the anti-Lisp types
who want to talk it down.  (They are always with us.)

> It's not realistic, I
> think, to create a library the size of Java's in a reasonable amount
> of time, but that doesn't mean progress is impossible.

It is possible to develop useful things, and probably people
are developing them; but there don't seem to be readily available
libraries that are easy enough to use.  Perhaps I'm wrong.
(I hope I am.)  Perhaps there's a web site that has it all
organized.

But the problem goes back even to before Java.  For example,
it used to be possible to get a GUI by combining CLX with some
other things.  But getting versions of those things, and a
version of your Lisp, that all worked together, was tricky,
and fragile: if you had to move to a new version of any of
them, all bets were off.

If you're doing something that has to work in a reasonable
amount of time, you can't bet the project on something like
that.

That's one reason I wrote an HTTP server rather than use CL-HTTP.
I knew I could write one that would work well enough using KCL's
very nice C interface, and that I could call on local Unix and C
experts if things turned weird.  But if I used CL-HTTP, for all
I knew I'd end up with some horrendous debugging task.

-- jd
From: Tim Bradshaw
Subject: Re: Be afraid of XML
Date: 
Message-ID: <ey3n05yiy0m.fsf@cley.com>
* Jeff Dalton wrote:

> Yes, and I think Sun had to do that; but now everyone has to pay
> a price, because of that, and because people are elaborating
> everywhere.  Learning enough about all the things you're supposed
> to use with Java is pretty much a full time job all on its own.

If it's not it will be soon.  This is pretty much the complexity event
horizon: when it becomes a full-time job to track the system you're
trying to use, you've passed the horizon...

> Because it doesn't?  Because for many people that now matters?
> Because discussing why Lisp is less successful or useful than
> we'd like, and what might make a difference, is natural in a
> Lisp newsgroup?

Yes, all these things are true.  However for a significant number of
people it seems that the aim is simply to complain.  Yes, I know,
that's what newsgroups are like.

--tim
From: Jeff Dalton
Subject: Re: Be afraid of XML
Date: 
Message-ID: <fx4llljp58s.fsf@todday.inf.ed.ac.uk>
Tim Bradshaw <···@cley.com> writes:

> Sure, that's because a *huge* amount of effort has been poured into
> the Java standard library.

BTW, I wouldn't want Lisp to have libraries like the Java ones.

The Java ones are much too complicated.

-- jd
From: Tim Bradshaw
Subject: Re: Be afraid of XML
Date: 
Message-ID: <ey3isgmdcsx.fsf@cley.com>
* Jeff Dalton wrote:

> BTW, I wouldn't want Lisp to have libraries like the Java ones.

> The Java ones are much too complicated.

I agree.  People are getting burned so badly by Java libs (or at least
by poor implementations of them, which are probably inevitable given
how hairy they are) that they're migrating to cobol (well, almost).

--tm
From: Jeff Dalton
Subject: Re: Be afraid of XML
Date: 
Message-ID: <fx43c7ntxrx.fsf@todday.inf.ed.ac.uk>
Tim Bradshaw <···@cley.com> writes:

> * Jeff Dalton wrote:
> 
> > BTW, I wouldn't want Lisp to have libraries like the Java ones.
> 
> > The Java ones are much too complicated.
> 
> I agree.  People are getting burned so badly by Java libs (or at least
> by poor implementations of them, which are probably inevitable given
> how hairy they are) that they're migrating to cobol (well, almost).

I don't think Java libraries have to be bad.

JDOM is a good tree representation for XML, for example.  When I
needed to get some XML processing going quickly, I looked at
SAX (you get parsing events -- too low-level) and DOM.  The DOM
stuff was way too complicated.  It would take more time than
I had just to start using it.  JDOM OTOH was simple and
straightforward.

-- jd
From: Tim Bradshaw
Subject: Re: Be afraid of XML
Date: 
Message-ID: <ey3ekr78fy2.fsf@cley.com>
* Jeff Dalton wrote:

> I don't think Java libraries have to be bad.

Sorry if I gave the impression that I thought they did: I don't
either.  I think some *are* bad, and some implementations of sets of
libraries (JBOSS) are appalling, but I didn't mean to imply that this
was anything fundamental.  Indeed I'm currently gently campaigning
that people should use Java, even after terrible experiences with
various (implementations of) libraries, because you don't have to get
caught up in them, and it has to be faster than python...

--tim
From: Jeff Dalton
Subject: Java, was Re: Be afraid of XML
Date: 
Message-ID: <fx43c7mjs8d.fsf_-_@todday.inf.ed.ac.uk>
Tim Bradshaw <···@cley.com> writes:

> * Jeff Dalton wrote:
> 
> > I don't think Java libraries have to be bad.
> 
> Sorry if I gave the impression that I thought they did:

Sorry if I gave the impression that I was disagreeing with you.

I was saying something on the other side mostly because I'd been
one-sided in my earlier message (and to advance the conversation).

> I don't
> either.  I think some *are* bad, and some implementations of sets of
> libraries (JBOSS) are appalling, but I didn't mean to imply that this
> was anything fundamental.  Indeed I'm currently gently campaigning
> that people should use Java, even after terrible experiences with
> various (implementations of) libraries, because you don't have to get
> caught up in them, and it has to be faster than python...

I think the Java language is not too bad as a language.

Inner classes made a big difference for me, because they
can be used in closure-like ways; and indeed my code is
full of inner classes of various sorts.

If they add parameterized types, e.g. List<Integer>, that
will be another big step forward.  (That was supposedly
going to happen in 1.5.)

Java is too verbose.  They may also fix one of the chief
irritations there: the amount you have to write to iterate
over the elements of a collection.

It would be nice if the field-getmethod-setmethod combination
could be defined less verbosely.  I have even resorted to
simple Lisp programs that write that stuff for me.

Java also tends to make things larger and more complex, for
other reasons that are not yet completely clear to me.

I have recently been doing in Java some things I did in Lisp,
and it has been *MUCH* more work.

Java encourages over-engineering.  That might be one slogan.

I'll bring some threads together by noting that one big -- and
often underappreciated -- win for Java was Unicode.  The Common Lisp
designers had the right thought (multi-byte char sets) but did it
slightly too soon.

Unicode in turn positioned Java very nicely for XML.

-- jd
From: André Thieme
Subject: Re: Java, was Re: Be afraid of XML
Date: 
Message-ID: <c4l79m$m7i$1@ulric.tng.de>
Jeff Dalton wrote:

> I have recently been doing in Java some things I did in Lisp,
> and it has been *MUCH* more work.

Could you please tell more about this?
Do you maybe even have some specific problems which you solved in Java
where you know that it would have been muss less work with Lisp?


Andr�
--
From: Peter Seibel
Subject: Re: Java, was Re: Be afraid of XML
Date: 
Message-ID: <m38yhdbn68.fsf@javamonkey.com>
Andr� Thieme <······································@justmail.de> writes:

> Jeff Dalton wrote:
>
>> I have recently been doing in Java some things I did in Lisp, and
>> it has been *MUCH* more work.
>
> Could you please tell more about this? Do you maybe even have some
> specific problems which you solved in Java where you know that it
> would have been muss less work with Lisp?

I'm not Jeff but I recently had the experience of writing in a single
day code to take apart and put together Java class files. Including a
generic tool for writing marshallers/unmarshallers for more-or-less
arbitrary binary formats.[1]

Compare that to my experience writing the same code in Java: Once,
long ago, I implemented such a thing in Java. Took me several weeks
but that's not really a fair comparison because I was a much less
experienced programmer then and also it was the first time I had dealt
with the problem. As it turned out I wrote that library for a company
so it belonged to them. Consequently several times since then I've had
occasion to try to write such a libary again in Java and each time
have basically given up when the code has gotten so ugly that I
couldn't stand it. (Admittedly I never really *needed* the library or
I probably would have show more perseverance.) I've been programming
Java since 1997 and have taught Java classes at Berkely Extension so I
don't think my problem was that I didn't know Java well enough.

The advantages of Lisp were the ease with which I could create a
mostly declarative form to describe the on-disk format I wanted to
read and write and then use that to generate code. After I wrote my
generic binary-io library (half a day's work and less than two-hundred
lines of code) it was a simple matter of transliterating the
descriptions of the .class file data structures from the Java VM spec
into my essentially isomorphic notation. I was done with that and had
code that could read and write back out an identical version of every
.class file in the JDK with time to spare to get started writing a
parser for ID3 tags. (Again, a simple matter of transliteration of the
spec.)

-Peter


[1] Similar to the BINARY-TYPES library on Cliki but different in ways
that suited my needs better. And it only took a half-day to write.
Providing another data point for Thomas Burdick's contention that the
reason there aren't many fully polished libraries in Common Lisp is
because it's so easy (and fun) to reivent the wheel for oneself.

-- 
Peter Seibel                                      ·····@javamonkey.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp
From: Pascal Costanza
Subject: Re: Java, was Re: Be afraid of XML
Date: 
Message-ID: <c4m3a8$bhg$1@newsreader2.netcologne.de>
Andr� Thieme wrote:

> Jeff Dalton wrote:
> 
>> I have recently been doing in Java some things I did in Lisp,
>> and it has been *MUCH* more work.
> 
> Could you please tell more about this?
> Do you maybe even have some specific problems which you solved in Java
> where you know that it would have been muss less work with Lisp?

My standard example is this. In Java, you have to say the following to 
open a file, read from it and make sure that it is properly closed:

FileInputStream in = null;
try {
   in = new FileInputStream("name");
   ...
   in.read(...);
   ...
} catch (FileNotFoundException e) {
   ...
} catch (IOException e) {
   ...
} finally {
   if (in != null) in.close();
}


In Common Lisp, the equivalent code is this:

(with-open-file (in "name")
   ...
   (read in ...)
   ...)

It's interesting to look at the expansion of that macro:

? (macroexpand '(with-open-file (in "name")
                   ...
                   (read in ...)
                   ...))
(LET (#:G429 #:G430)
   (UNWIND-PROTECT
       (MULTIPLE-VALUE-PROG1
         (LET ((IN (SETQ #:G429 (OPEN "name"))))
           ...
           (READ IN ...)
           ...)
         (SETQ #:G430 T))
     (WHEN #:G429 (CLOSE #:G429 :ABORT (NULL #:G430)))))

Here are some hints to read that code:

- #:G429 is a variable to hold a copy of the reference to the input stream.
- #:G430 is a variable that indicates whether the body of the 
WITH-OPEN-FILE macro has successfully executed.
- UNWIND-PROTECT is Common Lisp's version of try-finally
- MULTIPLE-VALUE-PROG1 says: Execute a number of expressions and return 
the value of the first expression.

This all means that you basically get more or less the same code in 
Common Lisp as in Java: Both variants declare variables before the 
try-finally statement / UNWIND-PROTECT form; opening the file and 
reading from it is done in the try-block / protected form; closing the 
file is done in the finally-block / cleanup form.

The difference is that in Java, you have to keep all the details in your 
head and write this idiom again and again and again, everywhere you need 
accesses to files. In Common Lisp, the macro takes care of these details 
and lets you focus on what's essential: You want to read from a file.


Pascal

-- 
1st European Lisp and Scheme Workshop
June 13 - Oslo, Norway - co-located with ECOOP 2004
http://www.cs.uni-bonn.de/~costanza/lisp-ecoop/
From: Tim Bradshaw
Subject: Re: Java, was Re: Be afraid of XML
Date: 
Message-ID: <fbc0f5d1.0404050224.6ff5871c@posting.google.com>
Pascal Costanza <········@web.de> wrote in message 
> 
> My standard example is this. In Java, you have to say the following to 
> open a file, read from it and make sure that it is properly closed:
> 

I think this isn't really a java issue, it's a
languages-without-macros issue.  My python is not idiomatic, but I
think that you need to do something like this there:

in = None
try:
    in = open(...)
    
    ...
finally:
    if in:
       in.close()

And that is pretty naive compared to what you actually want (for
instance, assignment to in will cause file-handle leakage).

So I think it's slightly unfair to Java to complain about the lack of
WITH-OPEN-FILE.  There are, I think, other ways that Java is more
verbose than it should be.

(Of course, the result of the lack of WITH-OPEN-FILE is that almost no
python code probably deals with file handles safely, I suspect)
From: Tayssir John Gabbour
Subject: Re: Java, was Re: Be afraid of XML
Date: 
Message-ID: <866764be.0404050840.71240a30@posting.google.com>
Pascal Costanza <········@web.de> wrote in message news:<············@newsreader2.netcologne.de>...
> My standard example is this. In Java, you have to say the following to 
> open a file, read from it and make sure that it is properly closed:
> 
> FileInputStream in = null;
> try {
>    in = new FileInputStream("name");
>    ...
>    in.read(...);
>    ...
> } catch (FileNotFoundException e) {
>  ...
> } catch (IOException e) {
>  ...
> } finally {
>  if (in != null) in.close();
> }

Even worse than that.  in.close() throws IOException.  So you need
another try/catch in your finally clause or it won't compile.

But on the upside, Java feels like real work.  I can type "public
static void main( String[] args ) {" really fast too.


Re: Tim Bradshaw's point about Python not having with-open-file... I
recently learned Ruby does, with its "blocks" -- syntactic sugar for
implicitly passing a closure to a function.  So both Java and Python
need to get with the program in creatively reinventing lisp. ;)

Incidentally, some flaming Rubes might claim with-open-file exists to
make up for the "horrible lambda syntax."  They either think the Ruby
way translates straight into lisp, or don't know about let.
From: Hannah Schroeter
Subject: Re: Java, was Re: Be afraid of XML
Date: 
Message-ID: <c4rhkr$nib$1@c3po.use.schlund.de>
Hello!

Tim Bradshaw <··········@tfeb.org> wrote:
>[... lack of with-open-file in macro-less languages ...]

But of course, you can define something like

(defun run-with-open-file (spec body-function)
  (let ((stream nil))
    (unwind-protect
      (progn
        (setf stream (apply #'open spec))
        (multiple-value-prog1
          (funcall body-function)
          (when stream (close stream) (setf stream nil))))
      (when stream (close stream :abort t)))))

And you can define equivalents of that in Java (using some object/
inner class/... mockery instead of the Lisp function object) or
Python (which has lambda and function objects).

So lack of macros isn't a real excuse for unsafe file handling.

Kind regards,

Hannah.
From: =?utf-8?b?QmrDtnJuIExpbmRiZXJn?=
Subject: Re: Java, was Re: Be afraid of XML
Date: 
Message-ID: <hcsu0zya823.fsf@fnatte.nada.kth.se>
······@schlund.de (Hannah Schroeter) writes:

> Hello!
> 
> Tim Bradshaw <··········@tfeb.org> wrote:
> >[... lack of with-open-file in macro-less languages ...]
> 
> But of course, you can define something like
> 
> (defun run-with-open-file (spec body-function)
>   (let ((stream nil))
>     (unwind-protect
>       (progn
>         (setf stream (apply #'open spec))
>         (multiple-value-prog1
>           (funcall body-function)
>           (when stream (close stream) (setf stream nil))))
>       (when stream (close stream :abort t)))))
> 
> And you can define equivalents of that in Java (using some object/
> inner class/... mockery instead of the Lisp function object) or
> Python (which has lambda and function objects).
> 
> So lack of macros isn't a real excuse for unsafe file handling.

In Python you can do something like

  def with_open_file(file, fun):
      stream = None
      try:
          stream = open(file)
          fun(stream)
      finally:
          stream and stream.close()

and then

  # Have to use a named function because of Pythons crippled anonymous
  # functions.
  def printlines(stream):
      line = stream.readline()
      while line:
          print line,
          line = stream.readline()

  with_open_file("foo.py", printlines)


Björn
From: Pascal Costanza
Subject: Re: Java, was Re: Be afraid of XML
Date: 
Message-ID: <c4rsls$qtm$1@f1node01.rhrz.uni-bonn.de>
Hannah Schroeter wrote:

> Hello!
> 
> Tim Bradshaw <··········@tfeb.org> wrote:
> 
>>[... lack of with-open-file in macro-less languages ...]
> 
> But of course, you can define something like
> 
> (defun run-with-open-file (spec body-function)
>   (let ((stream nil))
>     (unwind-protect
>       (progn
>         (setf stream (apply #'open spec))
>         (multiple-value-prog1
>           (funcall body-function)
>           (when stream (close stream) (setf stream nil))))
>       (when stream (close stream :abort t)))))
> 
> And you can define equivalents of that in Java (using some object/
> inner class/... mockery instead of the Lisp function object) or
> Python (which has lambda and function objects).

You're not passing the stream to BODY-FUNCTION. You have to require a 
function with one argument and have to document that the stream is 
passed as that argument. In other words, you have to define a protocol 
how these two functions interact with each other.

> So lack of macros isn't a real excuse for unsafe file handling.

That's right. However, the macro allows you to abstract away the 
protocol. I would like to access a file - that's the "domain" I am 
interested in. Why should I care about whether I need to pass a function 
and what parameters it takes? That's outside of the domain I am 
interested in. In other words, the pure higher-order function solution 
leads to a leaking abstraction. The macro allows you to abstract away 
all the unnecessary bits.


Pascal

-- 
ECOOP 2004 Workshops - Oslo, Norway
*1st European Lisp and Scheme Workshop, June 13*
http://www.cs.uni-bonn.de/~costanza/lisp-ecoop/
*2nd Post-Java Workshop, June 14*
http://prog.vub.ac.be/~wdmeuter/PostJava04/
From: Hannah Schroeter
Subject: Re: Java, was Re: Be afraid of XML
Date: 
Message-ID: <c4s1fl$mes$1@c3po.use.schlund.de>
Hello!

Pascal Costanza  <········@web.de> wrote:
>Hannah Schroeter wrote:

>> Tim Bradshaw <··········@tfeb.org> wrote:

>>>[... lack of with-open-file in macro-less languages ...]

>> But of course, you can define something like

>> (defun run-with-open-file (spec body-function)
>>   (let ((stream nil))
>>     (unwind-protect
>>       (progn
>>         (setf stream (apply #'open spec))
>>         (multiple-value-prog1
>>           (funcall body-function)
>>           (when stream (close stream) (setf stream nil))))
>>       (when stream (close stream :abort t)))))

>> And you can define equivalents of that in Java (using some object/
>> inner class/... mockery instead of the Lisp function object) or
>> Python (which has lambda and function objects).

>You're not passing the stream to BODY-FUNCTION.

Which is simple to fix, as you say yourself.

>You have to require a 
>function with one argument and have to document that the stream is 
>passed as that argument. In other words, you have to define a protocol 
>how these two functions interact with each other.

Yes, but what the heck? It's a simple transformation that doesn't
add much verbosity.

(with-open-file (stream options...)
  body)
=>
(call-with-open-file (options...)
  (lambda (stream)
    body))

It's just the "lambda" which is needed when you don't have macros.

>> So lack of macros isn't a real excuse for unsafe file handling.

>That's right. However, the macro allows you to abstract away the 
>protocol. I would like to access a file - that's the "domain" I am 
>interested in. Why should I care about whether I need to pass a function 
>and what parameters it takes? That's outside of the domain I am 
>interested in. In other words, the pure higher-order function solution 
>leads to a leaking abstraction. The macro allows you to abstract away 
>all the unnecessary bits.

Of course, macros are nice. But the loss isn't too high in *this*
particular case, as shown above. Try more complex "loop" invocations
instead.

Kind regards,

Hannah.
From: Pascal Costanza
Subject: Re: Java, was Re: Be afraid of XML
Date: 
Message-ID: <c4s24o$pii$1@f1node01.rhrz.uni-bonn.de>
Hannah Schroeter wrote:

> Of course, macros are nice. But the loss isn't too high in *this*
> particular case, as shown above. Try more complex "loop" invocations
> instead.

You're right in that macros really start to pay off in more complex 
scenarios than the example I have given. I still think it's a nice 
example that demonstrates what you can do with macros.


Pascal

-- 
ECOOP 2004 Workshops - Oslo, Norway
*1st European Lisp and Scheme Workshop, June 13*
http://www.cs.uni-bonn.de/~costanza/lisp-ecoop/
*2nd Post-Java Workshop, June 14*
http://prog.vub.ac.be/~wdmeuter/PostJava04/
From: Tim Bradshaw
Subject: Re: Java, was Re: Be afraid of XML
Date: 
Message-ID: <ey365cda27q.fsf@cley.com>
* Hannah Schroeter wrote:

> And you can define equivalents of that in Java (using some object/
> inner class/... mockery instead of the Lisp function object) or
> Python (which has lambda and function objects).

> So lack of macros isn't a real excuse for unsafe file handling.

Nothing is.  But without proper anonymous functions this is an
extraordinarily painful thing to use, because you have to define
(possibly locally) some thing which you then call, once. Which is
hateful, and makes native users of the language thing you're an alien.

--tim
From: Marcin 'Qrczak' Kowalczyk
Subject: Re: Java, was Re: Be afraid of XML
Date: 
Message-ID: <pan.2004.04.05.17.09.31.445606@knm.org.pl>
On Mon, 05 Apr 2004 03:24:03 -0700, Tim Bradshaw wrote:

>> My standard example is this. In Java, you have to say the following to 
>> open a file, read from it and make sure that it is properly closed:
> 
> I think this isn't really a java issue, it's a
> languages-without-macros issue.

This is not true. In Ruby, which doesn't have macros, you write

   open filename do |file|
      ...
   end

which is as concise and convenient as using a macro.


Pascal Costanza writes:

> However, the macro allows you to abstract away the protocol. I would
> like to access a file - that's the "domain" I am interested in. Why
> should I care about whether I need to pass a function and what
> parameters it takes?

No matter whether you are using a function or a macro, you must know what
arguments it takes and it what order - know the protocol. As long as the
protocol is not overly complex, everything is all right.

There are cases when macros are easier to use than higher order functions.
Safe opening a file definitely isn't one of them. Passing a one-argument
function as an argument in addition to filename is as good as passing the
name of a variable with a filename, parenthesized, in one argument, and
the body as the rest of arguments. The complexity of both is similar.
Both styles are idiomatic in their respective languages.

-- 
   __("<         Marcin Kowalczyk
   \__/       ······@knm.org.pl
    ^^     http://qrnik.knm.org.pl/~qrczak/
From: Gareth McCaughan
Subject: Re: Java, was Re: Be afraid of XML
Date: 
Message-ID: <87fzbix9z0.fsf@g.mccaughan.ntlworld.com>
Tim Bradshaw wrote:

> Pascal Costanza <········@web.de> wrote in message 
> > 
> > My standard example is this. In Java, you have to say the following to 
> > open a file, read from it and make sure that it is properly closed:
> > 
> 
> I think this isn't really a java issue, it's a
> languages-without-macros issue.  My python is not idiomatic, but I
> think that you need to do something like this there:
> 
> in = None
> try:
>     in = open(...)
>     
>     ...
> finally:
>     if in:
>        in.close()
> 
> And that is pretty naive compared to what you actually want (for
> instance, assignment to in will cause file-handle leakage).
> 
> So I think it's slightly unfair to Java to complain about the lack of
> WITH-OPEN-FILE.  There are, I think, other ways that Java is more
> verbose than it should be.
> 
> (Of course, the result of the lack of WITH-OPEN-FILE is that almost no
> python code probably deals with file handles safely, I suspect)

Python closes files when their objects get GCed. It uses
reference counting[1] (plus some real GC so that cycles
don't kill it), so generally that happens just about as
soon as the file's no longer in active use.

    [1] Boo! Hiss!

-- 
Gareth McCaughan
.sig under construc
From: Tim Bradshaw
Subject: Re: Java, was Re: Be afraid of XML
Date: 
Message-ID: <ey31xn1a1wy.fsf@cley.com>
* Gareth McCaughan wrote:

> Python closes files when their objects get GCed. It uses
> reference counting[1] (plus some real GC so that cycles
> don't kill it), so generally that happens just about as
> soon as the file's no longer in active use.

Well, `just about as soon' is not nearly the same as `now', for
instance if you want to know when the data is on the disk. I guess you
could use del everywhere. But it kind of feels bad, in a
devils-prodding-you-with-burning-forks sort of way, to rely in
horrible implementation details quite *that* much.  I for one live in
hope that Python might one day have a real GC (but not that much hope,
given the multitudinous other gratuitous cretinisms: Python seems to
be completely unique in that its designer seems to be aware of the
issues while still consciously making the worst choice everywhere he
can).

--tim
From: Michael Hudson
Subject: Re: Java, was Re: Be afraid of XML
Date: 
Message-ID: <m3ekr1tp5a.fsf@pc150.maths.bris.ac.uk>
Tim Bradshaw <···@cley.com> writes:

> * Gareth McCaughan wrote:
> 
> > Python closes files when their objects get GCed. It uses
> > reference counting[1] (plus some real GC so that cycles
> > don't kill it), so generally that happens just about as
> > soon as the file's no longer in active use.
> 
> Well, `just about as soon' is not nearly the same as `now', for
> instance if you want to know when the data is on the disk. I guess you
> could use del everywhere. But it kind of feels bad, in a
> devils-prodding-you-with-burning-forks sort of way, to rely in
> horrible implementation details quite *that* much.  I for one live in
> hope that Python might one day have a real GC (but not that much hope,
> given the multitudinous other gratuitous cretinisms: Python seems to
> be completely unique in that its designer seems to be aware of the
> issues while still consciously making the worst choice everywhere he
> can).

Go on then: suggest a GC implementation strategy for Python.

Cheers,
mwh

-- 
  But since I'm not trying to impress  anybody in The Software Big
  Top, I'd rather walk the wire using a big pole, a safety harness,
  a net, and with the wire not more than 3 feet off the ground.
                                   -- Grant Griffin, comp.lang.python
From: John Thingstad
Subject: Re: Java, was Re: Be afraid of XML
Date: 
Message-ID: <opr51itvk8xfnb1n@news.chello.no>
On Tue, 6 Apr 2004 09:46:26 GMT, Michael Hudson <···@python.net> wrote:

> Tim Bradshaw <···@cley.com> writes:
>
>> * Gareth McCaughan wrote:
>>
>> > Python closes files when their objects get GCed. It uses
>> > reference counting[1] (plus some real GC so that cycles
>> > don't kill it), so generally that happens just about as
>> > soon as the file's no longer in active use.
>>
>> Well, `just about as soon' is not nearly the same as `now', for
>> instance if you want to know when the data is on the disk. I guess you
>> could use del everywhere. But it kind of feels bad, in a
>> devils-prodding-you-with-burning-forks sort of way, to rely in
>> horrible implementation details quite *that* much.  I for one live in
>> hope that Python might one day have a real GC (but not that much hope,
>> given the multitudinous other gratuitous cretinisms: Python seems to
>> be completely unique in that its designer seems to be aware of the
>> issues while still consciously making the worst choice everywhere he
>> can).
>
> Go on then: suggest a GC implementation strategy for Python.
>
> Cheers,
> mwh
>

Python uses garbage collection for circular lists.
(Normally reference counting.)
(is this what you were asking?)


-- 
Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
From: Tim Bradshaw
Subject: Re: Java, was Re: Be afraid of XML
Date: 
Message-ID: <ey365ccg52c.fsf@cley.com>
* Michael Hudson wrote:

> Go on then: suggest a GC implementation strategy for Python.

Can't it just do the ordinary `things get GCd when they are
inaccessible' thing?

--tim
From: Michael Hudson
Subject: Re: Java, was Re: Be afraid of XML
Date: 
Message-ID: <m3ad1nu01i.fsf@pc150.maths.bris.ac.uk>
Tim Bradshaw <···@cley.com> writes:

> * Michael Hudson wrote:
> 
> > Go on then: suggest a GC implementation strategy for Python.
> 
> Can't it just do the ordinary `things get GCd when they are
> inaccessible' thing?

And how does it notice that they are inaccessible?

This is a game I've played on usenet for a while: whenever someone
says "refcounting sucks, Python should use a real GC", I press them
for details.  I don't usually get them.

To begin with, this really was a game; I thought that given the
constraints, refcounting+smarts probably was the best choice for
Python.  Now I'm not so sure, so I really would like to know of a
better way of doing things!

Points to note: any kind of copying collector seems likely to break
every C extension ever written, not a step to take lightly, and people
have tried plugging Boehm's GC-for-C in, and found that performance
got *worse* (Python is extraordinarily malloc-happy -- much more so
than most Lisp code, I'd guess -- and likely gets some mileage out of
the common case instant deallocation of refcounting).

So, refcounting isn't the worst choice: it seems Boehm's GC is
inferior.

Cheers,
mwh

-- 
  MARVIN:  What a depressingly stupid machine.
                    -- The Hitch-Hikers Guide to the Galaxy, Episode 7
From: Jeff Dalton
Subject: Re: Java, was Re: Be afraid of XML
Date: 
Message-ID: <fx4wu4r4hhu.fsf@todday.inf.ed.ac.uk>
Michael Hudson <···@python.net> writes:

> Tim Bradshaw <···@cley.com> writes:
> 
> > * Michael Hudson wrote:
> > 
> > > Go on then: suggest a GC implementation strategy for Python.
> > 
> > Can't it just do the ordinary `things get GCd when they are
> > inaccessible' thing?
> 
> And how does it notice that they are inaccessible?

Why people don't just *say* what they think the problem is,
rather than indulging in Socratic questions?

I've seen this a lot lately, for some reason.

> This is a game I've played on usenet for a while: whenever someone
> says "refcounting sucks, Python should use a real GC", I press them
> for details.  I don't usually get them.

What is the problem in Python that doesn't occur in the languages
that have implementations with garbage collectors?

> To begin with, this really was a game; I thought that given the
> constraints, refcounting+smarts probably was the best choice for
> Python.  Now I'm not so sure, so I really would like to know of a
> better way of doing things!

Ref counting isn't a bad idea; it's even been used for Lisp.
But GC technology has advanced tremendously in recent decades.
It would require a GC expert to properly assess how GC might
fit with Python (and I'm not one).

> Points to note: any kind of copying collector seems likely to break
> every C extension ever written, not a step to take lightly,

Also, if ref counting makes it much easier to write C
extensions, that could be a strong reason.

> (Python is extraordinarily malloc-happy -- much more so
> than most Lisp code, I'd guess -- and likely gets some mileage out of
> the common case instant deallocation of refcounting).

I think most Lisps written in C that aim for high performance
don't malloc individual objects.  They grab big chunks and
do their own allocation within them.  (I haven't looked into
this for years though.)

Lisp code deals with lots of little objects (such as cons
cells); I'd have expected Python programs to create fewer,
larger ones.

-- jd
From: Michael Hudson
Subject: Re: Java, was Re: Be afraid of XML
Date: 
Message-ID: <m3wu4qsne4.fsf@pc150.maths.bris.ac.uk>
Jeff Dalton <····@todday.inf.ed.ac.uk> writes:

> Michael Hudson <···@python.net> writes:
> 
> > Tim Bradshaw <···@cley.com> writes:
> > 
> > > * Michael Hudson wrote:
> > > 
> > > > Go on then: suggest a GC implementation strategy for Python.
> > > 
> > > Can't it just do the ordinary `things get GCd when they are
> > > inaccessible' thing?
> > 
> > And how does it notice that they are inaccessible?
> 
> Why people don't just *say* what they think the problem is,
> rather than indulging in Socratic questions?
> 
> I've seen this a lot lately, for some reason.

Tim started it :-)

> > This is a game I've played on usenet for a while: whenever someone
> > says "refcounting sucks, Python should use a real GC", I press them
> > for details.  I don't usually get them.
> 
> What is the problem in Python that doesn't occur in the languages
> that have implementations with garbage collectors?

Well, the reasons I have become less happy with refcounting in Python
is that (a) it wastes a word per object (b) it's pretty slow (I
recently spent time sitting in a profiler watching how much time
Python spent in functions that did nothing but decrement the refcounts
of subsidiary objects) and (c) it's error prone.  Refcounting has a
certain simplicity to it, but is does distribute a tedious level of
diffculty all over the codebase, and in practice people don't get this
right all the time.  A few months back I spent a week or so finding
and fixing this sort of bug in Python (most of them weren't very
serious -- leaking a refcount on a string on an error return path,
that sort of thing -- but there were more than I expected to find).

> > To begin with, this really was a game; I thought that given the
> > constraints, refcounting+smarts probably was the best choice for
> > Python.  Now I'm not so sure, so I really would like to know of a
> > better way of doing things!
> 
> Ref counting isn't a bad idea; it's even been used for Lisp.
> But GC technology has advanced tremendously in recent decades.
> It would require a GC expert to properly assess how GC might
> fit with Python (and I'm not one).

Oh well, maybe one will pipe up.  Perhaps here isn't the best place
for this discussion, though...

> > (Python is extraordinarily malloc-happy -- much more so
> > than most Lisp code, I'd guess -- and likely gets some mileage out of
> > the common case instant deallocation of refcounting).
> 
> I think most Lisps written in C that aim for high performance
> don't malloc individual objects.  They grab big chunks and
> do their own allocation within them.  (I haven't looked into
> this for years though.)

Python does something like this.

> Lisp code deals with lots of little objects (such as cons
> cells); I'd have expected Python programs to create fewer,
> larger ones.

I don't believe that to be the case, in practice.  I think it's
possible Python creates more, larger objects... but I haven't written
much CL of late.

Cheers,
mwh

-- 
  #ifndef P_tmpdir
  printf( "Go buy a better computer" );
  exit( ETHESKYISFALLINGANDIWANTMYMAMA );
                         -- Dimitri Maziuk on writing secure code, asr
From: Paul Dietz
Subject: Re: Java, was Re: Be afraid of XML
Date: 
Message-ID: <40755973.88685E6F@motorola.com>
Michael Hudson wrote:
> 
> Jeff Dalton <····@todday.inf.ed.ac.uk> writes:

> > I think most Lisps written in C that aim for high performance
> > don't malloc individual objects.  They grab big chunks and
> > do their own allocation within them.  (I haven't looked into
> > this for years though.)
> 
> Python does something like this.

If your program is multithreaded, the standard libc malloc
can be unpleasantly slow, since it (and free) have to lock/unlock
on each call.

	Paul
From: Tim Bradshaw
Subject: Re: Java, was Re: Be afraid of XML
Date: 
Message-ID: <ey31xmrhefy.fsf@cley.com>
* Jeff Dalton wrote:

> Ref counting isn't a bad idea; it's even been used for Lisp.
> But GC technology has advanced tremendously in recent decades.
> It would require a GC expert to properly assess how GC might
> fit with Python (and I'm not one).

Well, I think I'd beg to differ.  Reference counting isn't a bad idea
if you're living in the 70s (and on fairly small machines), when
memory was fast compared and it was no problem to increase the number
of writes to memory dramatically.  It may be that some clever version
of reference counting (probably something like keeping a single-bit
count for everything in some special area, and then falling back to a
fully-fledged counter in the (you hope) rare case of reference counts
being more than one) can be fast on modern machines.  But it may be
I'm wrong - perhaps reference counting even naively is OK for some
reason that's not apparent. (If the count is kept with the object,
perhaps it is often the case that it changes when the object changes,
and both end up in the same cache line?)

--tim
From: Tim Bradshaw
Subject: Re: Java, was Re: Be afraid of XML
Date: 
Message-ID: <fbc0f5d1.0404080742.797867ae@posting.google.com>
Michael Hudson <···@python.net> wrote in message news:<··············@pc150.maths.bris.ac.uk>...

> And how does it notice that they are inaccessible?

The normal way: it traces live data, either marking it or copying it
(or some combination), and then (first case) chucks everything
unmarked onto the free list, or (second case) notes the whole old
space is free.

Of course, because python is an implementation, not a language, there
are - as you say - a million shittily-written and
implementation-dependent extensions in C which will probably not work
with a copying collector.  It's a shame that they didn't think about
these kind of problems when doing the design.  I suspect a good
mark-sweep collector would still perform better than what it does at
present (and `good' means something that is python-data-type aware,
not some heroic C-level thing).
From: Hans-J. Boehm
Subject: Re: Java, was Re: Be afraid of XML
Date: 
Message-ID: <1178a29f.0404081527.180dfa82@posting.google.com>
Michael Hudson <···@python.net> wrote in message news:<··············@pc150.maths.bris.ac.uk>...

> Points to note: any kind of copying collector seems likely to break
> every C extension ever written, not a step to take lightly, and people
> have tried plugging Boehm's GC-for-C in, and found that performance
> got *worse* (Python is extraordinarily malloc-happy -- much more so
> than most Lisp code, I'd guess -- and likely gets some mileage out of
> the common case instant deallocation of refcounting).
> 
> So, refcounting isn't the worst choice: it seems Boehm's GC is
> inferior.
> 
I'm no doubt a little biased, but I was never convinced of that :-) 

Last I looked at this, many years ago, some other parts of Python's
runtime were pretty thoroughly convinced that there was reference
counting underneath, and it was fairly difficult to rip that out.

And the performance comparisons left me suspicious that there were at
least pieces of that left, and something wasn't working optimally.

Having said that, my understanding is that the standard Python
implementation uses a global lock to prevent multiple threads
executing Python code concurrently?  Although that has some negative
performance implications as well, it clearly does make classical
reference counting much more viable.  The tradeoffs look very
different for single- and fully-multi-threaded executables.  (See
http://www.hpl.hp.com/personal/Hans_Boehm/gc/nonmoving/ .)

Hans
From: Michael Hudson
Subject: Re: Java, was Re: Be afraid of XML
Date: 
Message-ID: <m3r7ukqlis.fsf@pc150.maths.bris.ac.uk>
··········@hp.com (Hans-J. Boehm) writes:

> Michael Hudson <···@python.net> wrote in message news:<··············@pc150.maths.bris.ac.uk>...
> 
> > Points to note: any kind of copying collector seems likely to break
> > every C extension ever written, not a step to take lightly, and people
> > have tried plugging Boehm's GC-for-C in, and found that performance
> > got *worse* (Python is extraordinarily malloc-happy -- much more so
> > than most Lisp code, I'd guess -- and likely gets some mileage out of
> > the common case instant deallocation of refcounting).
> > 
> > So, refcounting isn't the worst choice: it seems Boehm's GC is
> > inferior.
> > 
> I'm no doubt a little biased, but I was never convinced of that :-) 

Well, it wasn't me who tried it, and it doesn't seem I'm going to get
around to doing the work myself any time soon...

> Last I looked at this, many years ago, some other parts of Python's
> runtime were pretty thoroughly convinced that there was reference
> counting underneath, and it was fairly difficult to rip that out.

I'm not sure what you mean here.

> And the performance comparisons left me suspicious that there were at
> least pieces of that left, and something wasn't working optimally.

It's possible.  I would also guess that both your GC and Python's
implementation have changed a bit in the intervening years...

> Having said that, my understanding is that the standard Python
> implementation uses a global lock to prevent multiple threads
> executing Python code concurrently?  Although that has some negative
> performance implications as well, it clearly does make classical
> reference counting much more viable.

Oh good grief yes.

> The tradeoffs look very different for single- and
> fully-multi-threaded executables.  (See
> http://www.hpl.hp.com/personal/Hans_Boehm/gc/nonmoving/ .)

Interesting, to say the least.

Cheers,
mwh

-- 
  I can't see a conspicuous evolutionary advantage in being good
  at higher mathematics.                           -- James Riden, asr
From: Hans-J. Boehm
Subject: Re: Java, was Re: Be afraid of XML
Date: 
Message-ID: <1178a29f.0404191235.61a8b174@posting.google.com>
Michael Hudson <···@python.net> wrote in message news:<··············@pc150.maths.bris.ac.uk>...
> ··········@hp.com (Hans-J. Boehm) writes:
> 
> > Last I looked at this, many years ago, some other parts of Python's
> > runtime were pretty thoroughly convinced that there was reference
> > counting underneath, and it was fairly difficult to rip that out.
> 
> I'm not sure what you mean here.
> 
Unfortunately, this was long ago, and I don't remember the exact
issues either.  And they probably changed in the meantime.

As an example, of what I mean, a fairly common technique that works
with manual memory management, and can probably often be made to work
with reference counting, is to keep per-class or per-type free lists. 
This may save some overhead in reinitializing headers, etc.  (Applying
this "optimization" everywhere is almost certainly a bad idea,
though.)  Unless you are careful about clearing pointer fields, this
can be a huge pessimization if

a) You switch to a tracing collector, and
b) The tracing collector doesn't understand that the free lists are
special.

In that case, the collector would trace the free lists, and follow all
the (dead) pointer fields in objects on the free list, potentially
adding substantial tracing overhead and not reclaiming much of
anything.

I have a dim recollection that Python strings did something along
these lines a long time ago.

Occasionally, reference counts also allow you to win substantially by
performing some updates in-place.  In that case it probably makes
sense to also use them for memory reclammation.  I don't recall
whether Python ever takes advantage of that.

Hans
From: Michael Hudson
Subject: Re: Java, was Re: Be afraid of XML
Date: 
Message-ID: <m3isfvq64m.fsf@pc150.maths.bris.ac.uk>
··········@hp.com (Hans-J. Boehm) writes:

> Michael Hudson <···@python.net> wrote in message news:<··············@pc150.maths.bris.ac.uk>...
> > ··········@hp.com (Hans-J. Boehm) writes:
> > 
> > > Last I looked at this, many years ago, some other parts of Python's
> > > runtime were pretty thoroughly convinced that there was reference
> > > counting underneath, and it was fairly difficult to rip that out.
> > 
> > I'm not sure what you mean here.
> > 
> Unfortunately, this was long ago, and I don't remember the exact
> issues either.  And they probably changed in the meantime.
> 
> As an example, of what I mean, a fairly common technique that works
> with manual memory management, and can probably often be made to work
> with reference counting, is to keep per-class or per-type free lists. 
> This may save some overhead in reinitializing headers, etc.  (Applying
> this "optimization" everywhere is almost certainly a bad idea,
> though.)  Unless you are careful about clearing pointer fields, this
> can be a huge pessimization if
> 
> a) You switch to a tracing collector, and
> b) The tracing collector doesn't understand that the free lists are
> special.
> 
> In that case, the collector would trace the free lists, and follow all
> the (dead) pointer fields in objects on the free list, potentially
> adding substantial tracing overhead and not reclaiming much of
> anything.
> 
> I have a dim recollection that Python strings did something along
> these lines a long time ago.

OK, that makes sense.  It's not so much Python's internals being
convinced that there was refcounting underneath, just that there's
something a great deal like refcounting underneath...

Python does use such freelists for a few types, but (a) most of them
aren't "container" types (b) the ones that are do zero out the various
fields before putting them on the freelist (I think) (c) the freelists
are hardly difficult to disable.

I don't know if the last time people played with the BDW GC they did
disable the freelists or not.

> Occasionally, reference counts also allow you to win substantially by
> performing some updates in-place.  In that case it probably makes
> sense to also use them for memory reclammation.  I don't recall
> whether Python ever takes advantage of that.

Nope, or at least not very often.

Cheers,
mwh

-- 
  Well, you pretty much need Microsoft stuff to get misbehaviours
  bad enough to actually tear the time-space continuum.  Luckily 
  for you, MS Internet Explorer is available for Solaris.
                              -- Calle Dybedahl, alt.sysadmin.recovery
From: Jeff Dalton
Subject: Re: Java, was Re: Be afraid of XML
Date: 
Message-ID: <fx47jwtw4w5.fsf@todday.inf.ed.ac.uk>
Tim Bradshaw <···@cley.com> writes:

> I for one live in
> hope that Python might one day have a real GC (but not that much hope,
> given the multitudinous other gratuitous cretinisms: Python seems to
> be completely unique in that its designer seems to be aware of the
> issues while still consciously making the worst choice everywhere he
> can).

Is there an ideological objection, in the Python world, to 
being too much like Lisp?

For example, Python has something like cons-based lists,
but in an awkward-to-use way, while the "lists" with a nice
syntax etc are more like stretchy vectors.

Re GC, Python was presumably desinged while GC was considered
bad.

-- jd
From: Paul Dietz
Subject: Lispy Python (was Re: Java, was Re: Be afraid of XML)
Date: 
Message-ID: <4072DA22.D5118D9D@motorola.com>
Jeff Dalton wrote:

> For example, Python has something like cons-based lists,
> but in an awkward-to-use way, while the "lists" with a nice
> syntax etc are more like stretchy vectors.

There's an efficiency argument for vectors these days
(better cache behavior, more pipeline friendly.)  I'd be
interested in seeing a more Lispy Python that retained
the vector orientation.

	Paul
From: Erann Gat
Subject: Re: Lispy Python (was Re: Java, was Re: Be afraid of XML)
Date: 
Message-ID: <gNOSPAMat-0604041021250001@k-137-79-50-101.jpl.nasa.gov>
In article <·················@motorola.com>, Paul Dietz
<············@motorola.com> wrote:

> Jeff Dalton wrote:
> 
> > For example, Python has something like cons-based lists,
> > but in an awkward-to-use way, while the "lists" with a nice
> > syntax etc are more like stretchy vectors.
> 
> There's an efficiency argument for vectors these days
> (better cache behavior, more pipeline friendly.)  I'd be
> interested in seeing a more Lispy Python that retained
> the vector orientation.

I've done quite a bit of thinking about this, as it's one if the ideas
underlying the current design of Ciel.  It turns out that there are
problems using vectors as the underlying data structure.  Not
insurmountable problems, but problems nonetheless.

The main one is that vectors are incompatible with certain very common
(lower-case c) Lisp idioms, like iterating over lists using recursion and
CDR.  When lists are implemented as vectors intead of cons cells, CDR
conses.  :-)  This leads to all sorts of pretty horrible inefficiencies if
one tries to program in a traditional Lispy style.

The reason that CDR-based recursion works so well in Lisp is that all the
CDRs are in some sense "precomputed" when your representation is a linked
list.  You can sort of do the same thing using displaced vectors, but it
is not possible to represent a displaced vector as immediate data on a
32-bit machine.  So even if you don't have to copy the whole vector to do
a CDR you still have to cons up a pointer and an offset.  And then you
have the problem that the natural way to add data to a vector - via
vector-push-extend - is destructive.

CONS-cell-based lists really have a lot of awfully nice properties. 
Trying to base a language on vectors seems to result in a pretty awful
hairball, which might explain why no one has done it.

E.
From: Paul Dietz
Subject: Re: Lispy Python (was Re: Java, was Re: Be afraid of XML)
Date: 
Message-ID: <4072FC8D.19E95D6D@motorola.com>
Erann Gat wrote:

> The main one is that vectors are incompatible with certain very common
> (lower-case c) Lisp idioms, like iterating over lists using recursion and
> CDR.  When lists are implemented as vectors intead of cons cells, CDR
> conses.  :-)  This leads to all sorts of pretty horrible inefficiencies if
> one tries to program in a traditional Lispy style.

Sure.  These idioms would have to be replaced with the idioms
that are more natural for vectors.  The existence of the cons
idioms is not by itself an argument for conses (except to the
extent that the change requires existing programs to be changed,
but in that case you aren't going to go to a different language
anyway.)  If Lisp had been vector based from the beginning,
the same argument could be used against a consed-based lists.

Since Common Lisp does have vectors, perhaps it would be interesting
to determine what the alternate idioms would be, and determine
if CL supports them adequately.

	Paul
From: Erann Gat
Subject: Re: Lispy Python (was Re: Java, was Re: Be afraid of XML)
Date: 
Message-ID: <gNOSPAMat-0604041316210001@k-137-79-50-101.jpl.nasa.gov>
In article <·················@motorola.com>, Paul Dietz
<············@motorola.com> wrote:

> Erann Gat wrote:
> 
> > The main one is that vectors are incompatible with certain very common
> > (lower-case c) Lisp idioms, like iterating over lists using recursion and
> > CDR.  When lists are implemented as vectors intead of cons cells, CDR
> > conses.  :-)  This leads to all sorts of pretty horrible inefficiencies if
> > one tries to program in a traditional Lispy style.
> 
> Sure.  These idioms would have to be replaced with the idioms
> that are more natural for vectors.  The existence of the cons
> idioms is not by itself an argument for conses (except to the
> extent that the change requires existing programs to be changed,
> but in that case you aren't going to go to a different language
> anyway.)  If Lisp had been vector based from the beginning,
> the same argument could be used against a consed-based lists.
> 
> Since Common Lisp does have vectors, perhaps it would be interesting
> to determine what the alternate idioms would be, and determine
> if CL supports them adequately.

It's relatively straightforward to implement a vector-based language on
top of Common Lisp, or even in C as an interpreter (and even easier in C++
using STL vectors -- I have a toy implementation that actually does
this).  You immediately discover that not being able to efficiently take
the CDR of a list requires a truly radical change in your point of view. 
For example, at the heart of any interpreter for a Lispy language will be
a piece of code that does something like:

(cond
   ...

  ( (is-function-call-p form)
    (apply (evaluate-as-function (car form))
           (mapcar 'evaluate-as-argument (cdr form))) )
  ...
)

(There's also usually an environment argument being passed around that
I've omitted for simplicity.)

(N.B.: In Scheme, evaluate-as-function and evaluate-as-argument are the
same function.  In Common Lisp they are different.)

If you do a straightforward translation of this into VISP you end up
consing more than you have to because of the CDR.  If you want to be
efficient you have to do something like this:

[cond
   ...
   [ [is-function-call-p form]
     [let [ [args []] ]
        [loop for i from 1 to [length form] do
              [vector-push-extend args [evaluate-as-argument
                                               [vector-ref form i]]]]]
        [apply [evaluate-as-function [vector-ref form 0] args]]] ]
   ...
]

There's syntactic sugar you can apply to make that look not quite so
gross, but the important thing is not that it's ugly but that it relies on
side-effects.  You have given up on the possibility of writing code that
is both side-effect-free and efficient.  That's a Really Bad Thing.

How much that phenomenon appears outside of little toy examples like this
is an open question, but the fact that you (apparently) can't write an
efficient side-effect-free interpreter for a VISP seems like a bad omen to
me.

E.
From: Paul Dietz
Subject: Re: Lispy Python (was Re: Java, was Re: Be afraid of XML)
Date: 
Message-ID: <407327CF.69536E68@motorola.com>
Erann Gat wrote:

> You immediately discover that not being able to efficiently take
> the CDR of a list requires a truly radical change in your point of view.

What you'd want would be two kinds of vectors, simple vectors
and displaced vectors.  Simple vectors would be like CL simple
vectors, with fixed dimensions.  Displaced vectors could be
thought of as tuples containing: a reference to a simple vector,
a displacement, and a length.  This tuple would be immutable.

Displaced vectors would be created by a primitive operation,
say called DISV.  (CDR X) would be equivalent to (DISV X 1)
(the omitted third argument, the end position, would default as
in CL's SUBSEQ.)  It would be the case that

  (AREF X I) == (AREF (DISV X J K) (- I J))

(for J <= I < K.)

As an implementation trick, simple vectors can be implemented
with a header that makes them look like displaced vectors displaced
to themselves.

	Paul
From: Erann Gat
Subject: Re: Lispy Python (was Re: Java, was Re: Be afraid of XML)
Date: 
Message-ID: <gNOSPAMat-0604041552200001@k-137-79-50-101.jpl.nasa.gov>
In article <·················@motorola.com>, Paul Dietz
<············@motorola.com> wrote:

> Erann Gat wrote:
> 
> > You immediately discover that not being able to efficiently take
> > the CDR of a list requires a truly radical change in your point of view.
> 
> What you'd want would be two kinds of vectors, simple vectors
> and displaced vectors.  Simple vectors would be like CL simple
> vectors, with fixed dimensions.  Displaced vectors could be
> thought of as tuples containing: a reference to a simple vector,
> a displacement, and a length.  This tuple would be immutable.
> 
> Displaced vectors would be created by a primitive operation,
> say called DISV.  (CDR X) would be equivalent to (DISV X 1)
> (the omitted third argument, the end position, would default as
> in CL's SUBSEQ.)  It would be the case that
> 
>   (AREF X I) == (AREF (DISV X J K) (- I J))
> 
> (for J <= I < K.)
> 
> As an implementation trick, simple vectors can be implemented
> with a header that makes them look like displaced vectors displaced
> to themselves.

Yep.  Now if we could just figure out a way to fit a displaced vector into
a machine word life would be grand.

E.
From: Paul F. Dietz
Subject: Re: Lispy Python (was Re: Java, was Re: Be afraid of XML)
Date: 
Message-ID: <xYydnU7D3dZkpu7dRVn_iw@dls.net>
Erann Gat wrote:

> Yep.  Now if we could just figure out a way to fit a displaced vector into
> a machine word life would be grand.

You can't.  On the other hand, in many cases the compiler would be able
to determine that the tuple has dynamic extent, and can be stack allocated,
or even exploded into three independent variables (and optimized
away or put into registers.)  In some cases (to builtin functions,
say, or functions in which an argument is declared to be a vector)
the three fields could be passed as separate arguments.

	Paul
From: Peter Seibel
Subject: Re: Lispy Python (was Re: Java, was Re: Be afraid of XML)
Date: 
Message-ID: <m31xn0ales.fsf@javamonkey.com>
Paul Dietz <············@motorola.com> writes:

> If Lisp had been vector based from the beginning, the same argument
> could be used against a consed-based lists.

Though not quite "vector based" I was interested to see when I dug up
McCarthy's original paper describing Lisp[1], that he described
another way of representing Lisp expressions, L-expressions, where "L"
stood for linear. (These are not to be confused with M-expressions.)

L-expressions are defined on strings of charecters with FIRST
extracting the first character, i.e. (first s) == (char s 0), REST
gets the rest of the string: (rest s) == (subseq s 1), and COMBINE
creates a new string by prefixing its first argument (a char) onto its
second argument (a string). (It's not clear to me from the brief
discussion in the paper whether this meant all names were reduced to
being single characters--he doesn't really explain much more than what
I've just recapped.) As he says:

  The advantage of linear Lisp is that no characters are given special
  roles, as are parenthesis, dots, and commas in Lisp.

However he goes on to say:

  The disadvantage of linear Lisp is that extraction of subexpressions
  is a fairly involved, rather than an elementary, operation.

I think that last bit is something that would need to be addressed in
a non cons-based Lisp dialect. That is, if you don't have cons cells
as a native data structure for representing source code as data, then
you're going to have a hard time representing abstract syntax trees in
a way that's convenient for macros to operate on them.

-Peter

[1] "Recursive Functions of Symbolic Expressions and Their Computation
by Machine, Part I"

-- 
Peter Seibel                                      ·····@javamonkey.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp
From: Jeff Dalton
Subject: Re: Lispy Python (was Re: Java, was Re: Be afraid of XML)
Date: 
Message-ID: <fx4d66kg6un.fsf@todday.inf.ed.ac.uk>
Peter Seibel <·····@javamonkey.com> writes:

> However he goes on to say:
> 
>   The disadvantage of linear Lisp is that extraction of subexpressions
>   is a fairly involved, rather than an elementary, operation.

But linear lisp has strings as the basic data structure instead
of lists.  The alternative we're considering here is vectors,
which could have vectors as elements.  Strings have characters
as elements and strings only as substrings.

> I think that last bit is something that would need to be addressed in
> a non cons-based Lisp dialect. That is, if you don't have cons cells
> as a native data structure for representing source code as data, then
> you're going to have a hard time representing abstract syntax trees in
> a way that's convenient for macros to operate on them.

I'm not so sure about that.  A subexpression can still be
a sublist.  Imagine that [ ... ] was a notation for vectors
in Lisp.  Here's an example expression:

   [if [> x y] [f x] [f [g x]]]

All those lists could be vector-based lists.  

-- jd
From: Peter Seibel
Subject: Re: Lispy Python (was Re: Java, was Re: Be afraid of XML)
Date: 
Message-ID: <m3u0zw95mm.fsf@javamonkey.com>
Jeff Dalton <····@todday.inf.ed.ac.uk> writes:

> Peter Seibel <·····@javamonkey.com> writes:
>
>> However he goes on to say:
>> 
>>   The disadvantage of linear Lisp is that extraction of subexpressions
>>   is a fairly involved, rather than an elementary, operation.
>
> But linear lisp has strings as the basic data structure instead
> of lists.  The alternative we're considering here is vectors,
> which could have vectors as elements.  Strings have characters
> as elements and strings only as substrings.
>
>> I think that last bit is something that would need to be addressed in
>> a non cons-based Lisp dialect. That is, if you don't have cons cells
>> as a native data structure for representing source code as data, then
>> you're going to have a hard time representing abstract syntax trees in
>> a way that's convenient for macros to operate on them.
>
> I'm not so sure about that.  A subexpression can still be
> a sublist.  Imagine that [ ... ] was a notation for vectors
> in Lisp.  Here's an example expression:
>
>    [if [> x y] [f x] [f [g x]]]
>
> All those lists could be vector-based lists.  

That's fine. Now what kind of object does

  (rest (first (rest '[if [> x y] [f x] [f [g x]]])))

return? And where did it come from?

-Peter

-- 
Peter Seibel                                      ·····@javamonkey.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp
From: Erann Gat
Subject: Re: Lispy Python (was Re: Java, was Re: Be afraid of XML)
Date: 
Message-ID: <gNOSPAMat-0604041444260001@k-137-79-50-101.jpl.nasa.gov>
In article <··············@javamonkey.com>, Peter Seibel
<·····@javamonkey.com> wrote:

> Jeff Dalton <····@todday.inf.ed.ac.uk> writes:
> 
> > Peter Seibel <·····@javamonkey.com> writes:
> >
> >> However he goes on to say:
> >> 
> >>   The disadvantage of linear Lisp is that extraction of subexpressions
> >>   is a fairly involved, rather than an elementary, operation.
> >
> > But linear lisp has strings as the basic data structure instead
> > of lists.  The alternative we're considering here is vectors,
> > which could have vectors as elements.  Strings have characters
> > as elements and strings only as substrings.
> >
> >> I think that last bit is something that would need to be addressed in
> >> a non cons-based Lisp dialect. That is, if you don't have cons cells
> >> as a native data structure for representing source code as data, then
> >> you're going to have a hard time representing abstract syntax trees in
> >> a way that's convenient for macros to operate on them.
> >
> > I'm not so sure about that.  A subexpression can still be
> > a sublist.  Imagine that [ ... ] was a notation for vectors
> > in Lisp.  Here's an example expression:
> >
> >    [if [> x y] [f x] [f [g x]]]
> >
> > All those lists could be vector-based lists.  
> 
> That's fine. Now what kind of object does
> 
>   (rest (first (rest '[if [> x y] [f x] [f [g x]]])))
> 
> return? And where did it come from?

Ot this:

(setf x '[a b c])
(setf y (rest x))
(vector-push-extend x 'z)
(setf (first y) 'q)

Now, what are the values of X and Y?

E.
From: Jeff Dalton
Subject: Re: Lispy Python (was Re: Java, was Re: Be afraid of XML)
Date: 
Message-ID: <fx48yh838hx.fsf@todday.inf.ed.ac.uk>
Peter Seibel <·····@javamonkey.com> writes:

> Jeff Dalton <····@todday.inf.ed.ac.uk> writes:
> 
> > Peter Seibel <·····@javamonkey.com> writes:
> >
> >> However he goes on to say:
> >> 
> >>   The disadvantage of linear Lisp is that extraction of subexpressions
> >>   is a fairly involved, rather than an elementary, operation.
> >
> > But linear lisp has strings as the basic data structure instead
> > of lists.  The alternative we're considering here is vectors,
> > which could have vectors as elements.  Strings have characters
> > as elements and strings only as substrings.
> >
> >> I think that last bit is something that would need to be addressed in
> >> a non cons-based Lisp dialect. That is, if you don't have cons cells
> >> as a native data structure for representing source code as data, then
> >> you're going to have a hard time representing abstract syntax trees in
> >> a way that's convenient for macros to operate on them.
> >
> > I'm not so sure about that.  A subexpression can still be
> > a sublist.  Imagine that [ ... ] was a notation for vectors
> > in Lisp.  Here's an example expression:
> >
> >    [if [> x y] [f x] [f [g x]]]
> >
> > All those lists could be vector-based lists.  
> 
> That's fine. Now what kind of object does
> 
>   (rest (first (rest '[if [> x y] [f x] [f [g x]]])))
> 
> return? And where did it come from?

Assuming the language has first and rest, it would return a vector.
And it comes from the vector [> x y].

Why don't you just say what you think the problem is?

Anyway, The issue was supposed to be

  representing abstract syntax trees in
  a way that's convenient for macros to operate on them

not representing them in a way that's convenient for first
and rest to operate on them.

Many Lisp macros would translate easily.  There could be a
backquote notation for constructing vectors.  For example,

(defmacro delay (expr)
  `(make-delay #'(lambda () ,expr)))

would become

[defmacro delay [expr]
  `[make-delay #'[lambda [] ,expr]]]

-- jd
From: Rob Warnock
Subject: Re: Lispy Python (was Re: Java, was Re: Be afraid of XML)
Date: 
Message-ID: <rpadnUqpq9ecXO7dRVn-hg@speakeasy.net>
Jeff Dalton  <····@todday.inf.ed.ac.uk> wrote:
+---------------
| Peter Seibel <·····@javamonkey.com> writes:
| > you're going to have a hard time representing abstract syntax trees in
| > a way that's convenient for macros to operate on them.
| 
| I'm not so sure about that.  A subexpression can still be
| a sublist.  Imagine that [ ... ] was a notation for vectors
| in Lisp.  Here's an example expression:
| 
|    [if [> x y] [f x] [f [g x]]]
| 
| All those lists could be vector-based lists.  
+---------------

See my reply elsewhere in this thread on the problems that creates
with PROGN bodies:

    [progn [f x] [foo bar] [f [g x]] [baz gorp] [quxx blat]]
                          |
(Hint: What must be saved +-- here to get back from the call to "f"?)


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Ray Dillinger
Subject: Re: Lispy Python (was Re: Java, was Re: Be afraid of XML)
Date: 
Message-ID: <40734184.23E42523@sonic.net>
Peter Seibel wrote:
> 
> However he goes on to say:
> 
>   The disadvantage of linear Lisp is that extraction of subexpressions
>   is a fairly involved, rather than an elementary, operation.
> 
> I think that last bit is something that would need to be addressed in
> a non cons-based Lisp dialect. That is, if you don't have cons cells
> as a native data structure for representing source code as data, then
> you're going to have a hard time representing abstract syntax trees in
> a way that's convenient for macros to operate on them.

I've thought about this, but I haven't really reached a conclusion
of any concrete sort.  

The issue that comes to my mind is that there *is* another type of 
representation that can represent abstract syntax trees more 
directly than cons cells - and that is, tuples.  A cons cell is 
basically a pair; this is the "natural" representation for a node
of a parse tree with two subnodes. 

But many nodes of a parse tree have N subnodes, for N between 2 and 
the maximum expression arity on your lisp.  By convention, we 
represent the syntax tree using cons cells, but wouldn't it be 
a more direct mapping to represent it as a tree of N-tuples?  And,
possibly, more efficient as well, due to the constant-time access 
properties of tuples?

Source is immutable, so macros don't mutate source expressions; they
must create their parse tree expressions by copying, not mutation. 
Therefore the argument of minimizing structure mutation with cons 
cells doesn't actually apply to parse trees as such.

The problem is that tuples have more overhead than pairs and they
seem more complicated to reason about and use.  Where cons, car,
cdr seem to be the full set on pairs, tuples require cons2, 
cons3, cons4, ....   c1r, c2r, c3r, c4r, ...  not to mention an 
introspection routine such as tuple-size, and generally more 
complicated code. 

When I feel optimistic, I think this could be boiled down to macros 
or something that made tuples simple to use, but I always wind up
bogged in details when I attempt to design it.

				Bear
From: Jeff Dalton
Subject: Re: Lispy Python (was Re: Java, was Re: Be afraid of XML)
Date: 
Message-ID: <fx44qrw37ux.fsf@todday.inf.ed.ac.uk>
Ray Dillinger <····@sonic.net> writes:

> The issue that comes to my mind is that there *is* another type of 
> representation that can represent abstract syntax trees more 
> directly than cons cells - and that is, tuples.

> ...

> But many nodes of a parse tree have N subnodes, for N between 2 and 
> the maximum expression arity on your lisp.  By convention, we 
> represent the syntax tree using cons cells, but wouldn't it be 
> a more direct mapping to represent it as a tree of N-tuples?  And,
> possibly, more efficient as well, due to the constant-time access 
> properties of tuples?

That's pretty much what Prolog does, though it distinguishes the
functor from the arguments in a term, so that there's a bit more
structure than with a tuple.

> The problem is that tuples have more overhead than pairs and they
> seem more complicated to reason about and use.

2-tuples will probably have more overhead than pairs, but
whenthe arity goes up, there should be less overhead than
for a chain of conses.

>  Where cons, car,
> cdr seem to be the full set on pairs, tuples require cons2, 
> cons3, cons4, ....   c1r, c2r, c3r, c4r, ...  not to mention an 
> introspection routine such as tuple-size, and generally more 
> complicated code.

They wouldn't need that many separate functions.  Look up
hunks in MacLisp for an example.

Of think of the way contructors and pattern-matching work
in some functional languages such as ML.

-- jd
From: Jeff Dalton
Subject: Re: Lispy Python (was Re: Java, was Re: Be afraid of XML)
Date: 
Message-ID: <fx4hdvwg7qd.fsf@todday.inf.ed.ac.uk>
Paul Dietz <············@motorola.com> writes:

> Erann Gat wrote:
> 
> > The main one is that vectors are incompatible with certain very common
> > (lower-case c) Lisp idioms, like iterating over lists using recursion and
> > CDR.  When lists are implemented as vectors intead of cons cells, CDR
> > conses.  :-)  This leads to all sorts of pretty horrible inefficiencies if
> > one tries to program in a traditional Lispy style.
> 
> Sure.  These idioms would have to be replaced with the idioms
> that are more natural for vectors.

You seem to be assuming that there will always be a vector idiom
that's just as good.  But no, there are good reasons why there's
more than one collection type in the world.  You can't always
replace a Lisp-list idion with something just as good.

I do a lot of Java programming these days, and I even have
some Lisp-like lists that I can use in Java.  So I have to
decide between vector-like lists and Lisp-style lists all
the time.  Sometimes the Lisp-like ones are better; sometimes
they're worse.

> The existence of the cons
> idioms is not by itself an argument for conses

They provide an effective way to do certain things.  What's
the argument for not providing it?

> (except to the
> extent that the change requires existing programs to be changed,
> but in that case you aren't going to go to a different language
> anyway.)  If Lisp had been vector based from the beginning,
> the same argument could be used against a consed-based lists.

Sure, because in that case, Lisp programmers wouldn't be the
ones familiar with the advatages of cons-based lists.  They'd
therefore make the same mistakes the Python people do.  And
if Pythpn had been list-based from the start, the reversal
would be complete.

-- jd
From: Paul Dietz
Subject: Re: Lispy Python (was Re: Java, was Re: Be afraid of XML)
Date: 
Message-ID: <4073222D.1B10D585@motorola.com>
Jeff Dalton wrote:

> > Sure.  These idioms would have to be replaced with the idioms
> > that are more natural for vectors.
> 
> You seem to be assuming that there will always be a vector idiom
> that's just as good.  But no, there are good reasons why there's
> more than one collection type in the world.  You can't always
> replace a Lisp-list [idiom] with something just as good.

Yes, and vice versa.  My point is that the idioms that one has grown
used to in a cons-based lisp are (of course!) those that work
best with cons-based lisp.  There are other idioms (for example,
involving indexing into a list, or visiting its elements in
reverse order) that may work better with a vector-based system.

> > The existence of the cons
> > idioms is not by itself an argument for conses
> 
> They provide an effective way to do certain things.  What's
> the argument for not providing it?

It's not a matter of not providing it, but rather a question
of emphasis.  Cons-based lists occupy a central position in
lisp, more so than vectors.  Code is built of cons cells.
Lists (not vectors) are the usual data structures for
returning or passing sequences.

One can imagine a lisp in which this emphasis was reversed.
Programs would be trees of vectors.  Backquote notation would
be used for vector construction.  LOOP would have an accumulation
keyword for producing vectors.  And so on.

	Paul
From: Jeff Dalton
Subject: Re: Lispy Python (was Re: Java, was Re: Be afraid of XML)
Date: 
Message-ID: <fx4zn9o1sbn.fsf@todday.inf.ed.ac.uk>
Paul Dietz <············@motorola.com> writes:

> Jeff Dalton wrote:
> 
> > > Sure.  These idioms would have to be replaced with the idioms
> > > that are more natural for vectors.
> > 
> > You seem to be assuming that there will always be a vector idiom
> > that's just as good.  But no, there are good reasons why there's
> > more than one collection type in the world.  You can't always
> > replace a Lisp-list [idiom] with something just as good.
> 
> Yes, and vice versa.  My point is that the idioms that one has grown
> used to in a cons-based lisp are (of course!) those that work
> best with cons-based lisp.  There are other idioms (for example,
> involving indexing into a list, or visiting its elements in
> reverse order) that may work better with a vector-based system.

Of course.  But that doesn't mean that if I move from a language with
Lisp lists to a langauge that has vector "lists" instead that there's
no loss, or that it's just a question of what I'm used to or of
learning new idioms that are just as good.

Lisp lists are genuinely better for some things, and I don't
think replacing them with vectors is a win overall either.

Of course, a language could have both sorts of lists.

> > > The existence of the cons
> > > idioms is not by itself an argument for conses
> > 
> > They provide an effective way to do certain things.  What's
> > the argument for not providing it?
> 
> It's not a matter of not providing it, but rather a question
> of emphasis.

It is a matter of not providing it if it's not provided.
Python lists are the wrong sort of lists from my point of view.
I don't agree with Peter Norvig (for example) who seems to
think the difference is no big deal.

> Cons-based lists occupy a central position in
> lisp, more so than vectors.  Code is built of cons cells.
> Lists (not vectors) are the usual data structures for
> returning or passing sequences.
> 
> One can imagine a lisp in which this emphasis was reversed.

Sure, and I even defend such an approach in some other
messages.  "Defend" by arguing that it's not as bad as
some claim.  I don't think it's actually a good idea.
It's one of those things, like alternative syntaxes, that
are often brought up by people who don't like Lisp.

> Programs would be trees of vectors.  Backquote notation would
> be used for vector construction.  LOOP would have an accumulation
> keyword for producing vectors.  And so on.

Just so.

-- jd
From: André Thieme
Subject: Re: Lispy Python (was Re: Java, was Re: Be afraid of XML)
Date: 
Message-ID: <c58ok5$i36$1@ulric.tng.de>
Jeff Dalton wrote:

> Lisp lists are genuinely better for some things

Could you perhaps list some?


Andr�
--
From: Paul F. Dietz
Subject: Re: Lispy Python (was Re: Java, was Re: Be afraid of XML)
Date: 
Message-ID: <t-ydnWhIkYgWdOrdRVn-vw@dls.net>
Andr� wrote:
> Jeff Dalton wrote:
> 
>> Lisp lists are genuinely better for some things
> 
> 
> Could you perhaps list some?

They can be better for stacks or alists where you're going
to be sharing structure.  For example, representing information
on variable bindings down the various parts of a parse tree.

Lisp lists work better as &rest lists, again because you're
sharing structure will prepending elements.

	Paul
From: Rob Warnock
Subject: Re: Lispy Python (was Re: Java, was Re: Be afraid of XML)
Date: 
Message-ID: <rpadnUupq9fbIu7dRVn-hg@speakeasy.net>
Paul Dietz  <············@motorola.com> wrote:
+---------------
| Lists (not vectors) are the usual data structures for
| returning or passing sequences.
| 
| One can imagine a lisp in which this emphasis was reversed.
| Programs would be trees of vectors.
+---------------

Back when I was playing with writing my own Scheme (before switching
to CL), I actually did that, half-compiling IFs into 4-word vector-like
structures (a type marker plus 3 sub-form values), etc. But I found I
had a problem with the BEGIN form (PROGN in CL, also the bodies of
lambdas, do loops, etc.), namely, when a form in a BEGIN  (a vector
of nforms+1 elements) had to save a continuation (e.g., when calling
a function or processing a sub-form) it had to save *both* the pointer
to the BEGIN vector and the index (a fixnum) to the next element (the
continuation). Whereas had I used a list-based representation for BEGIN
blocks, only the CDR of the current element would have needed to be saved.

It was worse than just that, though, since without thinking it through
all the way I yielded to the temptation to re-use the continuation object
by simply incrementing the index as execution progressed through the
BEGIN body. Big mistake. If one of the earlier sub-forms had captured
the current continuation and later called it, the index would have been
already advanced too far.

Finally, in order to pass all of "pathological continuation capture"
tests (especially a couple I got from Queinnec's "Lisp in Small Pieces",
but also see thw recent thread in c.l.scheme for some of them) I had to
back out of the vector representation and make BEGINs be a series of
linked vectors #3(BEGIN this next). [I would have just used cons cells,
but the code vectors were a distinct type.]

Note that some of the problem could have been avoided if I'd implemented
locatives (specifically, allowing pointers to the interiors of objects),
but that had GC implications I wasn't ready to deal with.


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Jeff Dalton
Subject: Re: Lispy Python (was Re: Java, was Re: Be afraid of XML)
Date: 
Message-ID: <fx4isga75xu.fsf@todday.inf.ed.ac.uk>
····@rpw3.org (Rob Warnock) writes:

> It was worse than just that, though, since without thinking it through
> all the way I yielded to the temptation to re-use the continuation object
> by simply incrementing the index as execution progressed through the
> BEGIN body. Big mistake. If one of the earlier sub-forms had captured
> the current continuation and later called it, the index would have been
> already advanced too far.

That's an important general point, IMO.  If you want to process lists
without side effects, Lisp lists are generally easier to work with
and often more efficient.

Java's List implementations, for example, are designed to be
side-effected.  Utilities such as Collections.reverse(List)
don't even return the list.

-- jd
From: Sunnan
Subject: Re: Lispy Python
Date: 
Message-ID: <87r7v13pz7.fsf@handgranat.org>
·········@flownet.com (Erann Gat) writes:
> The main one is that vectors are incompatible with certain very common
> (lower-case c) Lisp idioms, like iterating over lists using recursion and
> CDR.  When lists are implemented as vectors intead of cons cells, CDR
> conses.  :-)  This leads to all sorts of pretty horrible inefficiencies if
> one tries to program in a traditional Lispy style.

In theory I can think of a c-array-ish list implementation that
doesn't "cons" when cdr-ing.

In pseudo-C/wannabe-BNF:
list[number-of-elems]

cdr list :== list++[number-of-elems-minus-one]

Maybe I've messed that up. The idea is to increment the pointer by
one.

-- 
One love,
Sunnan
From: Erann Gat
Subject: Re: Lispy Python
Date: 
Message-ID: <gNOSPAMat-0604041253560001@k-137-79-50-101.jpl.nasa.gov>
In article <··············@handgranat.org>, Sunnan <······@handgranat.org>
wrote:

> ·········@flownet.com (Erann Gat) writes:
> > The main one is that vectors are incompatible with certain very common
> > (lower-case c) Lisp idioms, like iterating over lists using recursion and
> > CDR.  When lists are implemented as vectors intead of cons cells, CDR
> > conses.  :-)  This leads to all sorts of pretty horrible inefficiencies if
> > one tries to program in a traditional Lispy style.
> 
> In theory I can think of a c-array-ish list implementation that
> doesn't "cons" when cdr-ing.
> 
> In pseudo-C/wannabe-BNF:
> list[number-of-elems]
> 
> cdr list :== list++[number-of-elems-minus-one]
> 
> Maybe I've messed that up. The idea is to increment the pointer by
> one.

There are more things wrong with that idea than I have time to explain to
you right now.  (You need to go do some very basic homework about how Lisp
works, and in particular how it differs from C.)  I'll just point out one
issue to get you started: what happens when you get to the end of a list? 
(You should consider that a rhetorical question.)

E.
From: Sunnan
Subject: Re: Lispy Python
Date: 
Message-ID: <878yh83kwo.fsf@handgranat.org>
·········@flownet.com (Erann Gat) writes:
> There are more things wrong with that idea than I have time to explain to
> you right now.  (You need to go do some very basic homework about how Lisp
> works, and in particular how it differs from C.)  I'll just point out one
> issue to get you started: what happens when you get to the end of a list? 
> (You should consider that a rhetorical question.)

Oh, I'm sorry. I left a few things implicit when I wrote my simplified
idea.

I do know that lisp vectors are implemented as fixed-length byte
strings while lists are ()-terminated pointer-based linked lists,
don't worry. I guess all my lisp-1/lisp-2 discussion today (and my
lack-of-sleep-induced sloppy language) is making me look newbier than
I really am.

I once designed (didn't implement it) a system of (don't know what to
call them, list/arrays?) that were implemented as fixed-length byte
strings linked together with NULL followed by the pointer to the next
"first byte", while the end was terminated by two NULL bytes. This was
primarily intended for character strings.

So the string "supercalifragilisticexpialidocious" could be stored as
the bytes "superc" followed by a NULL byte, followed by a pointer to
the first 'a' in "alifragilisticexpialidocious" which in turn was
followed by two consequential NULL bytes. The strings could be split
up arbitarily and two strings could share a common tail (which was
dangerous of course).

However, I never put it to practical use since I'm very happy with how
cons works and the various tree structures you can do with it.

You don't have to explain, just feel free to roll your eyes and groan
if I misunderstood you and I truly do need homework. (I don't know
much about Python, maybe that's where I went wrong.)

-- 
One love,
Sunnan
From: Erann Gat
Subject: Re: Lispy Python
Date: 
Message-ID: <gNOSPAMat-0604041500040001@k-137-79-50-101.jpl.nasa.gov>
In article <··············@handgranat.org>, Sunnan <······@handgranat.org>
wrote:

> I do know that lisp vectors are implemented as fixed-length byte
> strings

No, they aren't.

> You don't have to explain, just feel free to roll your eyes and groan
> if I misunderstood you and I truly do need homework. (I don't know
> much about Python, maybe that's where I went wrong.)

If I roll my eyes and groan, will that actually motivate you to go do your
homework?

Your problem is not that you misunderstand me, nor that you don't know
enough about Python.  Your problem is that some of the things you think
you know are wrong.  That is much more serious than not knowing, or even
not understanding.

E.
From: Sunnan
Subject: Re: Lispy Python
Date: 
Message-ID: <87lll8yrhc.fsf@handgranat.org>
·········@flownet.com (Erann Gat) writes:
> If I roll my eyes and groan, will that actually motivate you to go do your
> homework?

Yes, since I want to be respected.
So I'll go read up now.

-- 
One love,
Sunnan
From: Jeff Dalton
Subject: Re: Lispy Python
Date: 
Message-ID: <fx4d66lgc2k.fsf@todday.inf.ed.ac.uk>
Sunnan <······@handgranat.org> writes:

> ·········@flownet.com (Erann Gat) writes:
> > The main one is that vectors are incompatible with certain very common
> > (lower-case c) Lisp idioms, like iterating over lists using recursion and
> > CDR.  When lists are implemented as vectors intead of cons cells, CDR
> > conses.  :-)  This leads to all sorts of pretty horrible inefficiencies if
> > one tries to program in a traditional Lispy style.
> 
> In theory I can think of a c-array-ish list implementation that
> doesn't "cons" when cdr-ing.
> 
> In pseudo-C/wannabe-BNF:
> list[number-of-elems]
> 
> cdr list :== list++[number-of-elems-minus-one]
> 
> Maybe I've messed that up. The idea is to increment the pointer by
> one.

"cdr-coding" was similar.  The idea was that the cdr might just
be the next cell in memory, so that the list was stored in
vector fashion.  However, it's at least tricky to do it on
stock hardware (as opposed to Lisp machines).

But languages that don't have Lisp-style lists usually can't
take such an approach, because the list object has some extra
information that isn't repeated at each tail.

For example, a Java ArrayList is an instance of class
ArrayList; but that information is given only once, for
the whole list.

-- jd
From: Jeff Dalton
Subject: Re: Lispy Python (was Re: Java, was Re: Be afraid of XML)
Date: 
Message-ID: <fx4vfkdgefr.fsf@todday.inf.ed.ac.uk>
Paul Dietz <············@motorola.com> writes:

> Jeff Dalton wrote:

> > For example, Python has something like cons-based lists,
> > but in an awkward-to-use way, while the "lists" with a nice
> > syntax etc are more like stretchy vectors.

> There's an efficiency argument for vectors these days
> (better cache behavior, more pipeline friendly.)  I'd be
> interested in seeing a more Lispy Python that retained
> the vector orientation.

Sure, whenever there's a difference from Lisp, someone's
bound to give efficiency as the reason.  For many years,
that was a popular reason for not having garbage collection.
(That view seems to have infected Python as well.)

Yet Python isn't a maximally efficient language,
so it's hard to believe that's the real reason.

There are also cases where linked lists are more efficient
than array-based ones, and when singly linked lists are more
efficient than doubly-linked ones.

That's why Java has ArrayList and LinkedList (doubly linked).
It would not be hard to define a SinglyLinkedList, and some
collection packages for Java have had them.

But that's not the main difference between Python lists
and Lisp lists.  It's not that Lisp has SinglyLinkedLists
while Python has ArrayLists.  Lisp doesn't have either.
Lisp lists aren't ArrayLists, DoublyLinkedLists, or
SinglyLinkedLists.  Lisp's lists aren't any of those things,
despite being singly-linked (modulo cdr-coding).

For example, you can take the cdr (tail / rest) of a Lisp
list without creating any new object.  You don't have to
make a new list object and copy over all the elements
but the first.  You can iterate over the successive tails
of a Lisp list.

Moreover, Lisp lists don't have to be modified.  Rather than
modifying a list object to add an element at the front,
you create a new cons that has the new element as its car
and the old list as its cdr.

Many algorithms are written much more naturally with Lisp
lists.

(Of course, a language can have more than one kind of list.
For example, I've implemented Lisp-style lists in Java
for the cases where they're a better fit to what I want
to do.)

-- jd
From: Tim Bradshaw
Subject: Re: Lispy Python
Date: 
Message-ID: <ey3y8p8enff.fsf@cley.com>
* Jeff Dalton wrote:

> Sure, whenever there's a difference from Lisp, someone's
> bound to give efficiency as the reason.  For many years,
> that was a popular reason for not having garbage collection.
> (That view seems to have infected Python as well.)

Things like the lack of conses aren't my real problem with Python.
It's a pain not to have them, but what really annoys me is things like
the whole statement/expression distinction combined with crippled
lambda, or the lack of easy block structure (no LET), or scoping being
a bit weird and restricted.  Some at least of this seems to have been
done because it was `better' in the eyes of someone.  Other thing
(keyword argument defaulting is just wrong, I'm not sure there's a
fully-general equivalent to &REST) do just seem to be genuine
mistakes.

Of course python people will differ.  They will be rounded up and shot
in due course.

--tim
From: Jacek Generowicz
Subject: Re: Lispy Python
Date: 
Message-ID: <tyf3c7gxi1y.fsf@pcepsft001.cern.ch>
Tim Bradshaw <···@cley.com> writes:

> Things like the lack of conses aren't my real problem with Python.
> It's a pain not to have them, but what really annoys me is things like
> the whole statement/expression distinction combined with crippled
> lambda, or the lack of easy block structure (no LET), or scoping being
> a bit weird and restricted.

Yes, this is pretty much the core of what really annoys me about
Python.

> Some at least of this seems to have been done because it was
> `better' in the eyes of someone.

It looks to me as if it was mostly done by accident. IIRC, lambda was
submitted as a patch by someone, and somehow Guido let it in without
much thought (I guess it was the early days, and he was less wary -
remember that about half of the Python community hates lambda and
hopes that it will go away ASAP). But it's not clear to me how you
would implement a fully-fledged lambda in Python, given its
indentation-based syntax. (Getting rid of the statement expression
distinction would probably be a prerequisite.)

Nested scopes are a very recent addition (about 2 years ago), before
that there was only local, global and builtin; there was a "global"
keyword to disambiguate globals from locals, which allowed binding and
re-binding of names to have the same syntax ("=") ... but all this, of
course, isn't up to the task after the intoduction of nested scopes,
and the consequently a whole lot is built on shaky foundations.

The statement/expression distinction ... well, it really makes me
appreciate Lisp ... but it seems like it made implementation of the
interpreter easier in the very beginning.

I think that those who consider it "better" consider it better for
religious rather than logical reasons (we like Python because it is
small and simple, so we don't want to learn the lessons that Lisp has
already learnt, as that would be far too much work).

> Other thing (keyword argument defaulting is just wrong,

In what way ?  (Besides the time at which the default is evaluated)

> I'm not sure there's a fully-general equivalent to &REST

"*args, **kwds" gets you a long way, though perhaps not all the
way. Do you have an example of how this doesn't let you do what you
want. (I'm asking more in order to learn what I could be doing in
Lisp, rather than to learn what I can't do in Python :-)

> Of course python people will differ.  They will be rounded up and
> shot in due course.

You really seem to be in a foul mood this last week, or so ;-)
From: John Thingstad
Subject: Re: Lispy Python
Date: 
Message-ID: <opr545o7czxfnb1n@news.chello.no>
Python is not lisp. Many of the lisp operations like map and filter are
deprecated. They are replaced  by list comprehentions.
Hence there is less of a need for lambda notation.
It seems to me your main problen is that you think in lisp
and then complain that the abstraction dosn't carry through to python.
A python list is a lisp adjustable array.
They are not used the way cons arrays are.
It is difficult to iterate recurivly over a python array.
Recusion is used for subelements.
A array in python contains pointers to objects. It is not a vector. 
(sequence of numbers)
The itterate construct can be used to sequentaially parse arrays.
Python altso makes more use of classes.
Where you want a let (closure perhaps?) you would often use a class in 
python.
I used python extensivly a couple of years ago and found it simple, yet 
expressive.

I'll give you an example:

class PNF:
     """PNP -- return proposition p in Prenekens Normal Form
     Rewrite proposition to form: FORALL <variables> EXISTS variables 
<matrix>
     ex. [AND, ?x, [EXISTS, [?x], [FORALL, [?z], [OR, ?x, [rel, ?y, ?z]]]]]
     => [AND, ?x, [OR, ?x.1, [rel, ?y, ?z.2]]] and forallTable, existsTable
     Note that [AND, ?x... is not bound by EXISTS but [OR, ?x... is."""

     # while traversing the tree infix
     #  1. when seeing a forall or exists create a renamed variable for 
each new entry
     #     ex. [EXISTS, [?x, ?y] [...]] creates ?x.1, ?y.2
     #  2. store this in a two hashtables one for EXISTS and one for FORALL
     #     so we remeber them (ex. existTable = {?x -> ?x.1})
     #  3. while moving inward replace the variables that match entries in 
the tables
     #  4. when moving out of the scope of the kvantor stop replacing those 
variables
     #  5. remove kvantor when you exit it's scope
     # finally add [FORALL, [<collected>] [EXISTS, [<collected>] to the 
beginning
     # return the processed list

     def __genMatrix(self, varStore, p, substList):
         # pre: substList contains variables referenced by processed 
kvantors in scope
         #      either existsTable or forallTable map this variable name to 
a new name
         # ASSUME: curList is unchanged after a recursive return
         ind, result, curList = 0, [], substList[:]
         while ind < len(p):
             elt = p[ind]
             if type(elt) is ListType:
                 elt = self.__genMatrix(varStore, elt, curList)
             elif elt in [EXISTS, FORALL]:
                 if elt == EXISTS:
                     table = self.existsTable
                 else:
                     table = self.forallTable

                 for var in p[ind + 1]:
                     op, val = var
                     if not table.has_key(val):
                         table[val] = varStore.newName(val)
                     curList.append(val)
                 result += self.__genMatrix(varStore, p[ind + 2], curList)
                 return result
             elif type(elt) is TupleType:
                 op, val = elt
                 if op == VARIABLE:
                     if val in curList:
                         try:
                             newVal = self.forallTable[val]
                         except KeyError:
                             newVal = self.existsTable[val]
                         elt = (VARIABLE, newVal)
             result.append(elt)
             ind += 1
         return result

     def __call__(self, varStore, p):
         self.existsTable, self.forallTable = {}, {}
         # pre: varStore and p set, rest of params None
         result = self.__genMatrix(varStore, p, [])
         # post: result = kvantor free version of p with variables 
substituted
         #       forallTable, existsTable contains kvantor variables

         for val in self.existsTable.keys():
             if self.forallTable.has_key(val):
                 del self.existsTable[val]

         return result



On 07 Apr 2004 11:18:17 +0200, Jacek Generowicz <················@cern.ch> 
wrote:

> Tim Bradshaw <···@cley.com> writes:
>
>> Things like the lack of conses aren't my real problem with Python.
>> It's a pain not to have them, but what really annoys me is things like
>> the whole statement/expression distinction combined with crippled
>> lambda, or the lack of easy block structure (no LET), or scoping being
>> a bit weird and restricted.


-- 
Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
From: Gareth McCaughan
Subject: Re: Lispy Python
Date: 
Message-ID: <878yh6tdt2.fsf@g.mccaughan.ntlworld.com>
John Thingstad wrote:

> Python is not lisp. Many of the lisp operations like map and filter are
> deprecated. They are replaced by list comprehentions.
> Hence there is less of a need for lambda notation.

LAMBDA is useful for things other than mapping and filtering.
(In Lisp, too, you can express those operations without
lambdas; e.g., using LOOP ... COLLECT.)

> It seems to me your main problem is that you think in lisp
> and then complain that the abstraction dosn't carry through to python.
> A python list is a lisp adjustable array.
> They are not used the way cons arrays are.

I think this is obvious, and I don't think Jeff Dalton
(the only person I've noticed comparing Python's and Lisp's
"lists" in this thread) is saying "how nasty, Python doesn't
have Lisp-style lists".

> It is difficult to iterate recurivly over a python array.
> Recusion is used for subelements.
> A array in python contains pointers to objects. It is not a
> vector. (sequence of numbers)

In computer science, "vector" almost always means "sequence
of objects" (or "sequence of object references"). In particular,
that's how the term is used in Common Lisp, which has (e.g.)
a VECTOR function for constructing such things. 

> The iterate construct can be used to sequentaially parse arrays.

What does this mean? Which language are you talking about?

> Python also makes more use of classes.
> Where you want a let (closure perhaps?) you would often use a class in
> python.

Classes are a very, very cumbersome substitute for LET.
(Which is why that isn't generally how they are used.)

> I used python extensively a couple of years ago and found it simple,
> yet expressive.

I don't think anyone here is denying that Python is simple yet
expressive. Some people are saying that Common Lisp is *more*
expressive, which seems obviously correct to me.

> I'll give you an example:

I'm not sure what the purpose of the example is. I mean, are we
supposed to say "Gosh, now I see what a fine language Python is"?

> class PNF:
>      """PNP -- return proposition p in Prenekens Normal Form
>      Rewrite proposition to form: FORALL <variables> EXISTS variables <matrix>
>      ex. [AND, ?x, [EXISTS, [?x], [FORALL, [?z], [OR, ?x, [rel, ?y, ?z]]]]]
>      => [AND, ?x, [OR, ?x.1, [rel, ?y, ?z.2]]] and forallTable, existsTable
>      Note that [AND, ?x... is not bound by EXISTS but [OR, ?x... is."""
> 
>      # while traversing the tree infix
>      #  1. when seeing a forall or exists create a renamed variable for each new entry
>      #     ex. [EXISTS, [?x, ?y] [...]] creates ?x.1, ?y.2
>      #  2. store this in a two hashtables one for EXISTS and one for FORALL
>      #     so we remeber them (ex. existTable = {?x -> ?x.1})
>      #  3. while moving inward replace the variables that match entries in the tables
>      #  4. when moving out of the scope of the kvantor stop replacing those variables
>      #  5. remove kvantor when you exit it's scope
>      # finally add [FORALL, [<collected>] [EXISTS, [<collected>] to the beginning
>      # return the processed list
> 
>      def __genMatrix(self, varStore, p, substList):
>          # pre: substList contains variables referenced by processed kvantors in scope
>          #      either existsTable or forallTable map this variable name to a new name
>          # ASSUME: curList is unchanged after a recursive return
>          ind, result, curList = 0, [], substList[:]
>          while ind < len(p):
>              elt = p[ind]
>              if type(elt) is ListType:
>                  elt = self.__genMatrix(varStore, elt, curList)
>              elif elt in [EXISTS, FORALL]:
>                  if elt == EXISTS:
>                      table = self.existsTable
>                  else:
>                      table = self.forallTable
> 
>                  for var in p[ind + 1]:
>                      op, val = var
>                      if not table.has_key(val):
>                          table[val] = varStore.newName(val)
>                      curList.append(val)
>                  result += self.__genMatrix(varStore, p[ind + 2], curList)
>                  return result
>              elif type(elt) is TupleType:
>                  op, val = elt
>                  if op == VARIABLE:
>                      if val in curList:
>                          try:
>                              newVal = self.forallTable[val]
>                          except KeyError:
>                              newVal = self.existsTable[val]
>                          elt = (VARIABLE, newVal)
>              result.append(elt)
>              ind += 1
>          return result
> 
>      def __call__(self, varStore, p):
>          self.existsTable, self.forallTable = {}, {}
>          # pre: varStore and p set, rest of params None
>          result = self.__genMatrix(varStore, p, [])
>          # post: result = kvantor free version of p with variables substituted
>          #       forallTable, existsTable contains kvantor variables
> 
>          for val in self.existsTable.keys():
>              if self.forallTable.has_key(val):
>                  del self.existsTable[val]
> 
>          return result

Um, your algorithm is broken. If I feed it (E x f(x)) & (E x g(x)),
then it returns (E x) (f(x) & g(x)). Presumably it's by design
that it doesn't take any account of non-monotone operations like
negation and implication; if not, it's badly wrong there too.

Here's some code for full prenex form conversion in CL.
I've implemented variables as symbols whose names begin
with "?", rather than with list structure. In Common Lisp,
unlike some lesser languages, it isn't necessary to build
everything out of lists. :-)

My prenex normal form isn't quite the same as yours; I'm
assuming an "impure" predicate calculus in which some
predicates may have externally given meanings, and in that
context I don't think you can do any better than to move
all quantifiers to the front -- you can't, for instance,
guarantee that all the existential quantifiers come first,
or that all the universal quantifiers do.

(defun variablep (x)
  "True iff X is the name of a variable."
  (and (symbolp x) (char= (char (symbol-name x) 0) #\?)))

(defun rename-uniquely (v)
  "V is a variable. Make a new variable with a unique name
  that begins with the name of V."
  (gentemp (concatenate 'string (symbol-name v) "-")))

(defun uniquify-bound-variables (p)
  "P is a formula of predicate calculus, in s-exp form.
  Return a transformed version of P in which no two
  quantifiers use the same variable name, and in which
  no bound variable has the same name as any unbound
  variable. As second value, return an a-list mapping
  new names to old."
  (let ((new-to-old nil))
    (labels
      ((uniquify (p old-to-new)
         (if (atom p)
           (if (variablep p)
             (or (cdr (assoc p old-to-new)) p)
             p)
           (if (member (first p) '(for-all exists))
             (progn
               (dolist (v (second p))
                 (let ((new-v (rename-uniquely v)))
                   (push (cons v new-v) old-to-new)
                   (push (cons new-v v) new-to-old)))
               (list (first p)
                     (loop for q in (second p) collect (uniquify q old-to-new))
                     (uniquify (third p) old-to-new)))
             (loop for q in p collect (uniquify q old-to-new))))))
      (values (uniquify p nil) new-to-old))))

(defun switch-quantifier (q)
  (if (eq q 'for-all) 'exists 'for-all))

(defun prenex-normal-form-1 (p &optional (negate nil))
  "P is a formula of predicate calculus, in s-exp form,
  with all bound variables unique.
  Construct an equivalent formula with all quantifiers
  at the front. Return two values: a list of the quantifiers
  in order of appearance, and the 'body' of the formula."
  (if (atom p)
    (values nil (if negate `(not ,p) p))
    (let ((operator (first p)))
      (when (and (member operator '(for-all exists)) negate)
        (setf operator (switch-quantifier operator)))
      (case operator
        ((for-all exists)
         (multiple-value-bind (quantifiers body)
                              (prenex-normal-form-1 (third p) negate)
           (values (cons (list operator (second p)) quantifiers)
                   body)))
        ((not)
         (prenex-normal-form-1 (second p) (not negate)))
        (t
         (let ((quantifiers nil) (body (list operator)))
           (loop for child in (rest p) do
             (multiple-value-bind (q b) (prenex-normal-form-1 child)
               (setf quantifiers (nconc quantifiers q))
               (push b body)))
           (values quantifiers (if negate (list 'not (nreverse body))
                                          (nreverse body)))))))))

(defun prenex-normal-form (p)
  "P is a formula of predicate calculus, in s-exp form.
  Construct an equivalent formula with all quantifiers
  at the front. Return three values: a list of the quantifiers
  in order of appearance, the 'body' of the formula, and
  an alist mapping new names to old where bound variables
  have been renamed."
  (multiple-value-bind (new-p new-to-old)
                       (uniquify-bound-variables p)
    (multiple-value-bind (quantifiers body)
                         (prenex-normal-form-1 new-p nil)
      (values quantifiers body new-to-old))))

This code has 53 non-blank non-comment non-docstring lines,
compared to your 38; but this code solves a harder problem,
solves it correctly rather than incorrectly, and isn't
missing an important piece (the definition of the class
of which varStore is meant to be an instance, which I
reckon is at least 7 lines of Python), and treats variables
in what seems to me to be a much cleaner way.

I think Lisp wins in expressivity here.

-- 
Gareth McCaughan
.sig under construc
From: John Thingstad
Subject: Re: Lispy Python
Date: 
Message-ID: <opr58gfih7xfnb1n@news.chello.no>
On 08 Apr 2004 21:28:09 +0100, Gareth McCaughan 
<················@pobox.com> wrote:
> I'm not sure what the purpose of the example is. I mean, are we
> supposed to say "Gosh, now I see what a fine language Python is"?

The example illustrates using

class mumble
  def __init__(var1 var2)
  def foo ()
  def __call__(x) ...

mumble(x)

as an alternative to

let ((var1 var2))
   (defun mumble(x) ...)
   (defun foo () ...))

> Um, your algorithm is broken. If I feed it (E x f(x)) & (E x g(x)),
> then it returns (E x) (f(x) & g(x)). Presumably it's by design
> that it doesn't take any account of non-monotone operations like
> negation and implication; if not, it's badly wrong there too.
>

The code was taken out of a file normal.py
The calling sequence is as follows.

     def toCNF(self, varStore, p):
         "Conjuncts Normal Form"
         p = self.elimImpl(p)
         p = self.moveNot(p)
         pnfClause = PNF()
         p = self.skolemize(varStore, pnfClause(varStore, p),
                            pnfClause.existsTable, pnfClause.forallTable)
         p = self.inner(p)
         return p

As you can see due to the order it is not a problem in my code.


> Here's some code for full prenex form conversion in CL.
> (defun variablep (x)
>   "True iff X is the name of a variable."
>   (and (symbolp x) (char= (char (symbol-name x) 0) #\?)))

Thanks for the code I will look into it.


-- 
Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
From: Gareth McCaughan
Subject: Re: Lispy Python
Date: 
Message-ID: <87hdvpdw6a.fsf@g.mccaughan.ntlworld.com>
John Thingstad wrote:

> On 08 Apr 2004 21:28:09 +0100, Gareth McCaughan
> <················@pobox.com> wrote:
> > I'm not sure what the purpose of the example is. I mean, are we
> > supposed to say "Gosh, now I see what a fine language Python is"?
> 
> The example illustrates using
> 
> class mumble
>   def __init__(var1 var2)
>   def foo ()
>   def __call__(x) ...
> 
> mumble(x)
> 
> as an alternative to
> 
> let ((var1 var2))
>    (defun mumble(x) ...)
>    (defun foo () ...))

Well, yes. I'd say it mostly illustrates what a clumsy
idiom that is :-). Incidentally, you don't quite mean that;
__call__ describes what happens when you call an *instance*
of the class, not the class itself, so you'd need to say
mumble()(x).

>> Um, your algorithm is broken. If I feed it (E x f(x)) & (E x g(x)),
>> then it returns (E x) (f(x) & g(x)). Presumably it's by design
>> that it doesn't take any account of non-monotone operations like
>> negation and implication; if not, it's badly wrong there too.
> 
> The code was taken out of a file normal.py
> The calling sequence is as follows.
> 
>      def toCNF(self, varStore, p):
>          "Conjuncts Normal Form"
>          p = self.elimImpl(p)
>          p = self.moveNot(p)
>          pnfClause = PNF()
>          p = self.skolemize(varStore, pnfClause(varStore, p),
>                             pnfClause.existsTable, pnfClause.forallTable)
>          p = self.inner(p)
>          return p
> 
> As you can see due to the order it is not a problem in my code.

I can't, actually, since I don't know quite what those
other methods do. But if you're saying that the code,
in its proper context, has been proven correct and tested,
then I'll happily believe you :-).

>> Here's some code for full prenex form conversion in CL.
>> (defun variablep (x)
>>   "True iff X is the name of a variable."
>>   (and (symbolp x) (char= (char (symbol-name x) 0) #\?)))
> 
> Thanks for the code I will look into it.

You're welcome. I warn you that it's almost completely
untested, and not proven at all. It may be full of
errors. :-)

-- 
Gareth McCaughan
.sig under construc
From: Tim Bradshaw
Subject: Re: Lispy Python
Date: 
Message-ID: <ey3fzb7hfh3.fsf@cley.com>
[Sorry for the belated followup.  Our stupid ADSL modem likes to die when
I'm hundreds of miles away from it.]

* Jacek Generowicz wrote:

>> Other thing (keyword argument defaulting is just wrong,

> In what way ?  (Besides the time at which the default is evaluated)

No way other than that, but that has often meant that I end up with a
whacking great prologue to procedures which is just defaulting
arguments:

# This will be set at runtime to the class to instantiate, depending
# on which indexer is in use.
INDEX_CLASS = None

def foo(..., index_class=None):
    index_class = index_class or INDEX_CLASS
    ...

and repeat this for 5 arguments or something. It's just annoying.
Languages should go out of their way not to be annoying, and CL has
done just that in its argument defaulting: proper left-to-right order,
and defaults evaluated at the right point almost everywhere.

>> I'm not sure there's a fully-general equivalent to &REST

> "*args, **kwds" gets you a long way, though perhaps not all the
> way. Do you have an example of how this doesn't let you do what you
> want. (I'm asking more in order to learn what I could be doing in
> Lisp, rather than to learn what I can't do in Python :-)

I think they do go most of the way. The cases I find difficult are
where I'm essentially writing a method combination, and where I have
no real idea what arguments the other methods accept.  So I need to
accept arguments and pass them on to other methods, and I've just
found that hard.  I don't have the particular examples to hand, and it
may be that they are not as bad as I am making them out.  It's
probably bound up with getting frustrated at implementing, by hand,
yet another AROUND or BEFORE method.

--tim
From: Cesar Rabak
Subject: Re: Lispy Python -- off
Date: 
Message-ID: <407C431C.9090706@acm.org>
Tim Bradshaw escreveu:
> [Sorry for the belated followup.  Our stupid ADSL modem likes to die when
> I'm hundreds of miles away from it.]
> 
It seems it has some realatives with same behaviour thousand of miles of 
yours ;-D
From: Pascal Costanza
Subject: Re: Lispy Python
Date: 
Message-ID: <c51bm6$8mj$1@newsreader2.netcologne.de>
Tim Bradshaw wrote:

> keyword argument defaulting is just wrong

I am interested to hear why you think so. Until now, this is one of the 
very few things in Python that look somewhat neat to me...


Pascal

-- 
1st European Lisp and Scheme Workshop
June 13 - Oslo, Norway - co-located with ECOOP 2004
http://www.cs.uni-bonn.de/~costanza/lisp-ecoop/
From: Jacek Generowicz
Subject: Re: Java, was Re: Be afraid of XML
Date: 
Message-ID: <tyfd66lxhjb.fsf@pcepsft001.cern.ch>
Jeff Dalton <····@todday.inf.ed.ac.uk> writes:

> Is there an ideological objection, in the Python world, to 
> being too much like Lisp?

I think that there is quite a lot of that feeling among some members
of the Python community.

> For example, Python has something like cons-based lists,

It does ?

> Re GC, Python was presumably desinged while GC was considered
> bad.

I believe that ease of portability is considered to be a major
motivation for the use of reference counting in Python.
From: Jeff Dalton
Subject: Re: Java, was Re: Be afraid of XML
Date: 
Message-ID: <fx4ad1phvqy.fsf@todday.inf.ed.ac.uk>
Jacek Generowicz <················@cern.ch> writes:

> Jeff Dalton <····@todday.inf.ed.ac.uk> writes:

> > For example, Python has something like cons-based lists,

> It does ?

You can use 2-typles.  Peter Norvig counts them as Lisp lists
(linked lists) in his Lisp-Python comparison.

-- jd
From: Gareth McCaughan
Subject: Re: Java, was Re: Be afraid of XML
Date: 
Message-ID: <87oeq4wy1a.fsf@g.mccaughan.ntlworld.com>
Tim Bradshaw wrote:

> * Gareth McCaughan wrote:
> 
> > Python closes files when their objects get GCed. It uses
> > reference counting[1] (plus some real GC so that cycles
> > don't kill it), so generally that happens just about as
> > soon as the file's no longer in active use.
> 
> Well, `just about as soon' is not nearly the same as `now', for
> instance if you want to know when the data is on the disk. I guess
> you could use del everywhere. But it kind of feels bad, in a
> devils-prodding-you-with-burning-forks sort of way, to rely on
> horrible implementation details quite *that* much.

Yes. On the other hand, for a lot of applications you
basically never care exactly when your files get closed.
When you do care, you can close them explicitly. I'm
not saying this is as good as WITH-OPEN-FILE, but it's
good enough (tm) in practice. I've been using Python
quite a lot at work for several years, and have never
had any problem related to files not getting closed
because refcounting/GC isn't prompt enough.

>                                                     I for one live in
> hope that Python might one day have a real GC (but not that much hope,
> given the multitudinous other gratuitous cretinisms: Python seems to
> be completely unique in that its designer seems to be aware of the
> issues while still consciously making the worst choice everywhere he
> can).

Worst choices everywhere? It's not hard to tell you're coming
at this from Lisp. From most other directions, Python looks like
a big improvement.

But, perhaps relevantly, Python's refcounting *is* viewed as
a feature by many Pythonistas, and prompt closing of files
is one of the reasons commonly cited. :-)

-- 
Gareth McCaughan
.sig under construc
From: Tim Bradshaw
Subject: Re: Java, was Re: Be afraid of XML
Date: 
Message-ID: <fbc0f5d1.0404070400.cd6f18@posting.google.com>
Gareth McCaughan <················@pobox.com> wrote in message news:<··············@g.mccaughan.ntlworld.com>...

> Worst choices everywhere? It's not hard to tell you're coming
> at this from Lisp. From most other directions, Python looks like
> a big improvement.

It's not the bad choices that annoy me - all languages have them, and
I don't find spending my time sitting around whining that Lisp does it
better (which it doesn't always) endears me to anyone or is, in fact,
useful at all.  What bugs me about Python is the conscious bit: it
seems to be the case that Mr Python was aware of the issues, but
deliberately made various design decisions in a way to limit people's
options.  Crippled lambda is the obvious example.  The whole
expression/statement dichotomy combined with no compounding operations
is another, I think.  I don't like languages whose designers know what
is best for me.

--tim
From: Gareth McCaughan
Subject: Re: Java, was Re: Be afraid of XML
Date: 
Message-ID: <87ptajv4lm.fsf@g.mccaughan.ntlworld.com>
··········@tfeb.org (Tim Bradshaw) writes:

> Gareth McCaughan <················@pobox.com> wrote in message news:<··············@g.mccaughan.ntlworld.com>...
> 
> > Worst choices everywhere? It's not hard to tell you're coming
> > at this from Lisp. From most other directions, Python looks like
> > a big improvement.
> 
> It's not the bad choices that annoy me - all languages have them, and
> I don't find spending my time sitting around whining that Lisp does it
> better (which it doesn't always) endears me to anyone or is, in fact,
> useful at all.  What bugs me about Python is the conscious bit: it
> seems to be the case that Mr Python was aware of the issues, but
> deliberately made various design decisions in a way to limit people's
> options.  Crippled lambda is the obvious example.  The whole
> expression/statement dichotomy combined with no compounding operations
> is another, I think.  I don't like languages whose designers know what
> is best for me.

Yes, I hate the statement-versus-expression thing too.
(The crippling of lambda is a consequence of it.) I think
GvR thinks (perhaps correctly, perhaps even with evidence)
that the disctinction is (1) helpful to novice users and
(2) conducive to writing comprehensible code; Python is
for the most part very aggressively optimized for readability.
It bugs the hell out of me too sometimes[1], but it's not
obviously a *bad* choice. Just one aimed at a clientele
I'm not exactly in the middle of.

    [1] Another infuriating thing with the same motivation:
        the way that sorting or reversing a list *only*
        mutates the list and doesn't return a value.
        So to iterate over the keys of a dictionary in
        sorted order you have to go
            keys = d.keys()
            keys.sort()
            for key in keys: ...
        instead of
            for key in d.keys().sort(): ...
        Allegedly doing it this way makes it harder for
        people to forget that the operation is destructive.
        Readability (maybe "maintainability" is a better
        word) above all else, again.

-- 
Gareth McCaughan
.sig under construc
From: Jacek Generowicz
Subject: Re: Java, was Re: Be afraid of XML
Date: 
Message-ID: <tyffzbex66x.fsf@pcepsft001.cern.ch>
Gareth McCaughan <················@pobox.com> writes:

> [...] helpful to novice users [...]

>     [1] Another infuriating thing with the same motivation:
>         the way that sorting or reversing a list *only*
>         mutates the list and doesn't return a value.

Ironically enough, this seems to cause a lot of problems for people
learning the language. (I teach introductionary Python classes, and
see people repeatedly stumbling up against this.)
From: Jeff Dalton
Subject: Re: Java, was Re: Be afraid of XML
Date: 
Message-ID: <fx4isg97t4o.fsf@tarn.inf.ed.ac.uk>
Jacek Generowicz <················@cern.ch> writes:

> Gareth McCaughan <················@pobox.com> writes:
> 
> > [...] helpful to novice users [...]
> 
> >     [1] Another infuriating thing with the same motivation:
> >         the way that sorting or reversing a list *only*
> >         mutates the list and doesn't return a value.
> 
> Ironically enough, this seems to cause a lot of problems for people
> learning the language. (I teach introductionary Python classes, and
> see people repeatedly stumbling up against this.)

It helps make it clear that it's done by mutating.  (Since
the result isn't useful, that's all that's left.)

I also find it annoying that, say, Collections.reverse(List)
doesn't return the list in Java; but I think it actually
makes sense, given that reversing is done my mutation.

What I blame instead is the use in both Python and Java
of lists that are really stretchy vectors.  They result
in much more side-effecty ways of doing things.

-- jd
From: Jan Rychter
Subject: Re: Java, was Re: Be afraid of XML
Date: 
Message-ID: <m2oeq1imxw.fsf@tnuctip.rychter.com>
>>>>> "Jacek" == Jacek Generowicz <················@cern.ch> writes:
 Jacek> Gareth McCaughan <················@pobox.com> writes:

 >> [...] helpful to novice users [...]

 >> [1] Another infuriating thing with the same motivation: the way that
 >> sorting or reversing a list *only* mutates the list and doesn't
 >> return a value.

 Jacek> Ironically enough, this seems to cause a lot of problems for
 Jacek> people learning the language. (I teach introductionary Python
 Jacek> classes, and see people repeatedly stumbling up against this.)

I've seen the same problems when teaching basic Python. While beginners
do not really understand the expression "side-effects", they do have an
intuitive understanding of it. And even if they don't, eventually they
have to know whether they should write

  a = b.op() (and continue working on a)

or just

  b.op()

and the first question every beginner asks at that point is "well, how
do I know that?"

Having also done some experiments teaching very basic Scheme, it seems
that it is much easier to grasp for beginners. "Every form returns
something and you can feed that into other expressions". When you do get
to side-effects, they are obvious because of the naming conventions.

IMHO, the mythical "easy-to-use Python syntax" is just that -- a
myth. It is a syntax that looks easy to average programmers. Beginners
generally do not agree.

--J.
From: Gareth McCaughan
Subject: Re: Java, was Re: Be afraid of XML
Date: 
Message-ID: <878yh1dv7d.fsf@g.mccaughan.ntlworld.com>
Jan Rychter wrote:

> Having also done some experiments teaching very basic Scheme, it seems
> that it is much easier to grasp for beginners. "Every form returns
> something and you can feed that into other expressions". When you do get
> to side-effects, they are obvious because of the naming conventions.
> 
> IMHO, the mythical "easy-to-use Python syntax" is just that -- a
> myth. It is a syntax that looks easy to average programmers. Beginners
> generally do not agree.

I think Python is much more optimized for maintainability than
for ease of learning by complete beginners. On the other hand,
I have some good empirical evidence that complete beginners
(12-15-year-olds, indeed) can learn Python quite well. It would
be interesting to try them on Scheme instead...

-- 
Gareth McCaughan
.sig under construc
From: Howard Ding <······@hading.dnsalias.com>
Subject: Re: Java, was Re: Be afraid of XML
Date: 
Message-ID: <m33c79m5r2.fsf@frisell.localdomain>
Gareth McCaughan <················@pobox.com> writes:

> Jan Rychter wrote:
> 
> > IMHO, the mythical "easy-to-use Python syntax" is just that -- a
> > myth. It is a syntax that looks easy to average programmers. Beginners
> > generally do not agree.
> 
> I think Python is much more optimized for maintainability than
> for ease of learning by complete beginners. On the other hand,
> I have some good empirical evidence that complete beginners
> (12-15-year-olds, indeed) can learn Python quite well. It would
> be interesting to try them on Scheme instead...
> 

Well, one hardly needs to speculate about that.  It's what
www.teach-scheme.org and www.htdp.org are all about.


-- 
Howard Ding
<······@hading.dnsalias.com>
From: David Steuber
Subject: Re: Java, was Re: Be afraid of XML
Date: 
Message-ID: <873c79ezgq.fsf@david-steuber.com>
Gareth McCaughan <················@pobox.com> writes:

> I think Python is much more optimized for maintainability than
> for ease of learning by complete beginners. On the other hand,
> I have some good empirical evidence that complete beginners
> (12-15-year-olds, indeed) can learn Python quite well. It would
> be interesting to try them on Scheme instead...

Does LOGO qualify as a lisp?  That is a good language for children to
play with.  The immediate feedback from the turtle graphics is kind of
fun.  Of course, that masks the other things the language was able to
do.

-- 
I wouldn't mind the rat race so much if it wasn't for all the damn cats.
From: Jeff Dalton
Subject: Re: Java, was Re: Be afraid of XML
Date: 
Message-ID: <fx4hdvmzf22.fsf@tarn.inf.ed.ac.uk>
David Steuber <·····@david-steuber.com> writes:

> Does LOGO qualify as a lisp?  That is a good language for children to
> play with.  The immediate feedback from the turtle graphics is kind of
> fun.  Of course, that masks the other things the language was able to
> do.

Probably not quite a Lisp, but it is very close, to the point
where many dialects have properties that will seem odd to people
used to "mainstream" languages but understandable to someone
who can relate them back to Lisp.

Logo tries to reduce the need for punctuation (despite having
some odd punctuation of its own, such as the use of colons to
indicate variables); and I think that helps make it easier
for children.

Also turtles are very easy to understand intuitively.

-- jd
From: Jeff Dalton
Subject: Re: Java, was Re: Be afraid of XML
Date: 
Message-ID: <fx4d66azez7.fsf@tarn.inf.ed.ac.uk>
Jan Rychter <···@rychter.com> writes:

> IMHO, the mythical "easy-to-use Python syntax" is just that -- a
> myth. It is a syntax that looks easy to average programmers. Beginners
> generally do not agree.

I don't find Python very easy to understand.

Perhaps that's because some parts are easy, so that
I focus on the parts that aren't; but I don't think so.

-- jd
From: Jeff Dalton
Subject: Re: Java, was Re: Be afraid of XML
Date: 
Message-ID: <fx4ekqx7t2p.fsf@tarn.inf.ed.ac.uk>
Gareth McCaughan <················@pobox.com> writes:

> Python is
> for the most part very aggressively optimized for readability.

Is *is*?

It doesn't seem especially readable to me, though it's not
especially bad either.

-- jd
From: =?utf-8?b?QmrDtnJuIExpbmRiZXJn?=
Subject: Re: Java, was Re: Be afraid of XML
Date: 
Message-ID: <hcsfzbg848y.fsf@fnatte.nada.kth.se>
Gareth McCaughan <················@pobox.com> writes:

> >                                                     I for one live in
> > hope that Python might one day have a real GC (but not that much hope,
> > given the multitudinous other gratuitous cretinisms: Python seems to
> > be completely unique in that its designer seems to be aware of the
> > issues while still consciously making the worst choice everywhere he
> > can).
> 
> Worst choices everywhere? It's not hard to tell you're coming
> at this from Lisp. From most other directions, Python looks like
> a big improvement.
> 
> But, perhaps relevantly, Python's refcounting *is* viewed as
> a feature by many Pythonistas, and prompt closing of files
> is one of the reasons commonly cited. :-)

So is it considered good style in Python to not explicitly close
files, instead relying on them to be closed when all references have
been removed?


Björn
From: Tayssir John Gabbour
Subject: Re: Java, was Re: Be afraid of XML
Date: 
Message-ID: <866764be.0404070515.43b1c5cb@posting.google.com>
·······@nada.kth.se (Björn Lindberg) wrote in message news:<···············@fnatte.nada.kth.se>...
> Gareth McCaughan <················@pobox.com> writes:
> > But, perhaps relevantly, Python's refcounting *is* viewed as
> > a feature by many Pythonistas, and prompt closing of files
> > is one of the reasons commonly cited. :-)
> 
> So is it considered good style in Python to not explicitly close
> files, instead relying on them to be closed when all references have
> been removed?

No; I once posted a link and analysis about that here:

http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&oe=UTF-8&safe=off&selm=5627c6fa.0310230919.d2eb49a%40posting.google.com&prev=/groups%3Fhl%3Den%26lr%3D%26ie%3DUTF-8%26oe%3DUTF-8%26safe%3Doff%26q%3Dpython%2Bauthor%253Atayss%2Bgroup%253Acomp.lang.lisp.*%26btnG%3DSearch%26meta%3Dgroup%253Dcomp.lang.lisp.*

Issues like this hurt projects which move to Jython, because of all
the incorrect code -- the worst kind of intermittent bugs can appear.

One problem with Python is its insistence that "There Should be One,
and Preferably Only One, Obvious Way to Do It."  When Guido does not
guide people to the right solution, many will take the Path of Least
Resistance on the assumption that guardrails will keep them from harm.
From: Gareth McCaughan
Subject: Re: Java, was Re: Be afraid of XML
Date: 
Message-ID: <87lll7v46t.fsf@g.mccaughan.ntlworld.com>
·······@nada.kth.se (Bj�rn Lindberg) writes:

> Gareth McCaughan <················@pobox.com> writes:
> 
> > >                                                     I for one live in
> > > hope that Python might one day have a real GC (but not that much hope,
> > > given the multitudinous other gratuitous cretinisms: Python seems to
> > > be completely unique in that its designer seems to be aware of the
> > > issues while still consciously making the worst choice everywhere he
> > > can).
> > 
> > Worst choices everywhere? It's not hard to tell you're coming
> > at this from Lisp. From most other directions, Python looks like
> > a big improvement.
> > 
> > But, perhaps relevantly, Python's refcounting *is* viewed as
> > a feature by many Pythonistas, and prompt closing of files
> > is one of the reasons commonly cited. :-)
> 
> So is it considered good style in Python to not explicitly close
> files, instead relying on them to be closed when all references have
> been removed?

Authorities differ. I consider it good style if and only if you
don't mind exactly when the file gets closed.

-- 
Gareth McCaughan
.sig under construc
From: Rainer Joswig
Subject: Re: Java, was Re: Be afraid of XML
Date: 
Message-ID: <c366f098.0404060133.300f672c@posting.google.com>
Pascal Costanza <········@web.de> wrote in message news:<············@newsreader2.netcologne.de>...
> Andr� Thieme wrote:
> 
> > Jeff Dalton wrote:
> > 
> >> I have recently been doing in Java some things I did in Lisp,
> >> and it has been *MUCH* more work.
> > 
> > Could you please tell more about this?
> > Do you maybe even have some specific problems which you solved in Java
> > where you know that it would have been muss less work with Lisp?
> 
> My standard example is this. In Java, you have to say the following to 
> open a file, read from it and make sure that it is properly closed:
> 
> FileInputStream in = null;
> try {
>    in = new FileInputStream("name");
>    ...
>    in.read(...);
>    ...
> } catch (FileNotFoundException e) {
>  ...
> } catch (IOException e) {
>  ...
> } finally {
>  if (in != null) in.close();
> }
> 
> 
> In Common Lisp, the equivalent code is this:
> 
> (with-open-file (in "name")
>    ...
>    (read in ...)
>    ...)
> 
> It's interesting to look at the expansion of that macro:
> 
> ? (macroexpand '(with-open-file (in "name")
>                    ...
>                    (read in ...)
>                    ...))
> (LET (#:G429 #:G430)
>    (UNWIND-PROTECT
>        (MULTIPLE-VALUE-PROG1
>          (LET ((IN (SETQ #:G429 (OPEN "name"))))
>            ...
>            (READ IN ...)
>            ...)
>          (SETQ #:G430 T))
>      (WHEN #:G429 (CLOSE #:G429 :ABORT (NULL #:G430)))))
> 
> Here are some hints to read that code:
> 
> - #:G429 is a variable to hold a copy of the reference to the input stream.
> - #:G430 is a variable that indicates whether the body of the 
> WITH-OPEN-FILE macro has successfully executed.
> - UNWIND-PROTECT is Common Lisp's version of try-finally
> - MULTIPLE-VALUE-PROG1 says: Execute a number of expressions and return 
> the value of the first expression.
> 
> This all means that you basically get more or less the same code in 
> Common Lisp as in Java: Both variants declare variables before the 
> try-finally statement / UNWIND-PROTECT form; opening the file and 
> reading from it is done in the try-block / protected form; closing the 
> file is done in the finally-block / cleanup form.
> 
> The difference is that in Java, you have to keep all the details in your 
> head and write this idiom again and again and again, everywhere you need 
> accesses to files. In Common Lisp, the macro takes care of these details 
> and lets you focus on what's essential: You want to read from a file.
> 
> 
> Pascal

I'd rather use lambda abstraction to do this.

The macro version is
 a) code bloat,
 b) needs to be recompiled whenever you change the implementation,
 c) can't be passed to other functions and
 d) is harder to debug.

(If you want it to inline code, then declare the
function to be inlined.)
From: Tim Daly Jr.
Subject: Re: Java, was Re: Be afraid of XML
Date: 
Message-ID: <87isgd9t3b.fsf@hummer.intern>
······@corporate-world.lisp.de (Rainer Joswig) writes:
[...regarding with-open-file...]
> I'd rather use lambda abstraction to do this.
> 
> The macro version is
>  a) code bloat,
>  b) needs to be recompiled whenever you change the implementation,
>  c) can't be passed to other functions and
>  d) is harder to debug.
> 
> (If you want it to inline code, then declare the
> function to be inlined.)

Why not just have the macro call your higher-order function?  Maybe
something like:

(defmacro with-open-file ((stream filespec &rest options)
			  &body body)
  `(call-with-open-file ,filespec 
    (lambda (,stream) ,@body) ,@options))


Such a macro will not bloat your code, because you would have written
the same thing anyway.  Presumably it is also so simple that it will
never need to be changed.  Your higher-order function is still
available for passing to other functions.  I'm not sure how it affects
debuggability.

I agree with your reasoning, but I think the consequence should be
better support for macros, and better macros, not a proliferation of
explicit lambda abstractions.  Macros just make code pretty like
nothing else can.


-- 
-Tim
From: Jeff Dalton
Subject: Re: Java, was Re: Be afraid of XML
Date: 
Message-ID: <fx4brm5w556.fsf@todday.inf.ed.ac.uk>
······@corporate-world.lisp.de (Rainer Joswig) writes:

Re with-open-file --

> I'd rather use lambda abstraction to do this.
> 
> The macro version is
>  a) code bloat,

Why?

>  b) needs to be recompiled whenever you change the implementation,
>  c) can't be passed to other functions and
>  d) is harder to debug.

Perhaps you just don't like macros.

-- jd
From: Jeff Dalton
Subject: Re: Java, was Re: Be afraid of XML
Date: 
Message-ID: <fx4isgdn7mr.fsf@todday.inf.ed.ac.uk>
Pascal Costanza <········@web.de> writes:

> Andr� Thieme wrote:

> > Jeff Dalton wrote:

> >> I have recently been doing in Java some things I did in Lisp,
> >> and it has been *MUCH* more work.

> > Could you please tell more about this?
> > Do you maybe even have some specific problems which you solved in Java
> > where you know that it would have been muss less work with Lisp?

> My standard example is this.  [Discussion of with-open-file] ...

> The difference is that in Java, you have to keep all the details in
> your head and write this idiom again and again and again, everywhere
> you need accesses to files. In Common Lisp, the macro takes care of
> these details and lets you focus on what's essential: You want to read
> from a file.

I think that's a very important point.  In Java, it's harder
to "raise the level" of the language, so you often have to 
think at one level while manually translating into the lower
level that the language imposes.

I have even resorted to writing Lisp programs that write some
of my Java.

-- jd
From: Pete Kirkham
Subject: Re: Java, was Re: Be afraid of XML
Date: 
Message-ID: <40730e47$0$6543$cc9e4d1f@news-text.dial.pipex.com>
Jeff Dalton wrote:
> I have even resorted to writing Lisp programs that write some
> of my Java.

I have even resorted to writing _XSLT_ programs that write some of my Java.


Pete
From: Tayssir John Gabbour
Subject: Re: Java, was Re: Be afraid of XML
Date: 
Message-ID: <866764be.0404042052.3c9f284f@posting.google.com>
Andr� Thieme <······································@justmail.de> wrote in message news:<············@ulric.tng.de>...
> Do you maybe even have some specific problems which you solved in Java
> where you know that it would have been muss less work with Lisp?

My first useful (emacs) lisp program generated Java code for me. 
That's kind of my smallest use of lisp, but it illustrates the point
pretty aptly.

Also, I wrote a sleeker lisp counterpart to JUnit.  It's a little unit
testing language, with nice features like remembering old tests to
rerun, a comment syntax that can intelligently print to screen while
tests run, etc.  I once observed people trying to evangelize JUnit
into a company that used Java, and it got enormous pushback because it
was a capital-F Framework.  In contrast, my lisp testing language is
~25 lines, without any attempt to reduce it or trim unused features.

The nice thing is I am able to evolve the system as my needs change. 
Java does not compress where the programmer's thoughts compress, so
when you have a big pile of code, you're afraid to change it.  It is
just not worthwhile.


Andr� Thieme <······································@justmail.de> wrote in message news:<············@ulric.tng.de>...
> Jeff Dalton wrote:
> > I have recently been doing in Java some things I did in Lisp,
> > and it has been *MUCH* more work.
> 
> Could you please tell more about this?

As I currently understand Sun's intention with Java, the following
property is important:  it takes skill to write insecure programs. 
That is what you're likely to want if nearly everyone can weave a
process into the net's fabric.  If you read a book like Nancy Lynch's
on distributed algorithms, you might come to the same conclusion; you
don't want things getting r00ted and becoming Byzantine generals.

One tradeoff with that philosophy is that you will often err on the
side of safety, not abstraction.  The painful "checked exceptions" is
one example -- try writing map/fold/filter that can operate on objects
which throw these exceptions.  You will either lose safety or
abstraction.  (I believe Steele/Sussman talk a bit about this in Art
of the Interpreter, as they discuss dynamic variables.  Hopefully
these exceptions get something like generics...)

So Sun has made a lot of tradeoffs in order to make Java something
that wouldn't frighten you if you knew every process on the net ran
it.  Their hype campaign, braces & semicolons, gratis sourcecode, etc.
seem to be a Hail Mary run to make the future less doomed.  But it is
a beachhead, and the campaign needs to proceed.
From: David Fisher
Subject: Re: Java, was Re: Be afraid of XML
Date: 
Message-ID: <14030ca9.0404052030.3b122fc4@posting.google.com>
···········@yahoo.com (Tayssir John Gabbour) wrote in message news:<····························@posting.google.com>...

> 
> Also, I wrote a sleeker lisp counterpart to JUnit.  It's a little unit
> testing language, with nice features like remembering old tests to
> rerun, a comment syntax that can intelligently print to screen while
> tests run, etc.  I once observed people trying to evangelize JUnit
> into a company that used Java, and it got enormous pushback because it
> was a capital-F Framework.  In contrast, my lisp testing language is
> ~25 lines, without any attempt to reduce it or trim unused features.

OK, you got my attention. Sounds like this could make a great advocacy
example (for those who are interested). Post your awesome 25 Elisp
lines!
From: Tayssir John Gabbour
Subject: Re: Java, was Re: Be afraid of XML
Date: 
Message-ID: <866764be.0404060739.5411f6d7@posting.google.com>
·············@yahoo.com (David Fisher) wrote in message news:<····························@posting.google.com>...
> OK, you got my attention. Sounds like this could make a great advocacy
> example (for those who are interested). Post your awesome 25 Elisp
> lines!

If this will find personal use or for advocacy, let me grow the ball
of mud a little more, because what has evolved for my personal needs
just may not hit the spot for others.  (Someone else showed interest
in email.)

Peter's first pass has 17 non-comment lines, and there are others:
http://www.gigamonkeys.com/book/practical-building-a-unit-test-framework.html
http://www.gigamonkeys.com/book/practical-extending-the-unit-test-framework.html
http://www.cliki.net/Test%20Framework

A test system can evolve very simply.  What I initially just wanted
was a list of expressions which all evaluated to true or false; the
false ones caused something to be printed or a debugger visit.  Few
lines.  To support comments, we can just detect the comment prelude,
suck in the comment, perhaps print it and go on.  Should tests rerun
later with a single command?  We can store them somewhere.
From: Christian Lynbech
Subject: Re: Be afraid of XML
Date: 
Message-ID: <8765cnq6au.fsf@baguette.defun.dk>
>>>>> "Jeff" == Jeff Dalton <····@todday.inf.ed.ac.uk> writes:

Jeff> There are a lot of things I can do in Java that I can't do
Jeff> in Lisp without going to particular implementations or writing
Jeff> a lot of code that is just to build infrastructure: that isn't
Jeff> really part of what I'm trying to do.

Which is true,

_BUT_

things are currently improving at an incredible rate. Just see how
projects pop up right and left on common-lisp.net. I have been a Lisp
addict for quite some years and I have never seen such activity as we
have had since ILU 2002.

This still is not on par with Java, but we are getting there.

So, everybody, do as Tim says. Join a project, write some code, help
out in any way, big or small, that you can. Waiting for the perfect
version of the ANSI Lisp standard is not a good excuse for not getting
started (IMHO).


------------------------+-----------------------------------------------------
Christian Lynbech       | christian ··@ defun #\. dk
------------------------+-----------------------------------------------------
Hit the philistines three times over the head with the Elisp reference manual.
                                        - ·······@hal.com (Michael A. Petonic)
From: Wade Humeniuk
Subject: Re: Be afraid of XML
Date: 
Message-ID: <9fZ9c.23042$wg1.11488@edtnps84>
Tim Bradshaw wrote:

> Many posters to cll give the strong impression that they'd rather sit
> there and complain than actually do something.  There are just endless
> `I can't use Lisp because ...' threads (`there's no standard interface
> to x', `pathnames have some theoretical deficiency', `it was all
> better on the lisp machines' `vendor x charges too much', `cmucl
> doesn't run on windows, we need to spend lots of money to make it do
> so rather than use one of the several offerings that do, because
> they're commercial (hiss) / ideologically unsound (hiss hiss)').
> 
> I don't understand these people.  My current theory is that they
> actually don't *want* lisp to succeed, because it gives them an excuse
> not to do anything: if lisp was successful then they'd have to face
> the awful fact that they *have no ideas*.  Maybe this theory is wrong,
> but it's the best I have.

When we had our house built I got to see the whole process.  This
included all the warts, 2x6 studs slightly short or out of alignment,
holes drilled poorly, patches, etc, etc.  But we still have a functional
house and it looks pretty good.  The construction was good enough
though sometimes the reality of it is a little hard to stomach as it does not live
up to my idealized vision.  This is even worse when I build something
myself, I am aware of all the warts, incompletions and hacks.  Shelves
I built for the laundry room look really good on a cursory inspection,
but I KNOW every misalignment, knick and error.  The same goes for
software I have written.  But I have come to grips with it.

I too think there is too much whining and a propensity to try to KILL
that which does not live up to our expectations.  Nothing can live up
to our expectations and ideals.   Including the ideation we have of
the quality of our thinking and *ideas*.  I think the
whining comes from the *perfectionist* personality trait.  Perfectionists
end up doing nothing as nothing is worth starting.  No software or tool
is perfect (in this case anticipate our every need) and will always, always
need touching/shoring up.  But I know that if Common Lisp is not a sharp
enough tool, nothing is.

Wade
From: Joe Marshall
Subject: Re: Be afraid of XML
Date: 
Message-ID: <y8q6pal0.fsf@comcast.net>
Pete Kirkham <·················@cafemosaic.co.uk> writes:

> Sometimes the people here (and in the XML world) sound like it
> actually matters how pointy the delimiters in the syntax are.

But it does!  Everyone knows that code written with smooth parens is
much slower than code written with '{}'.

-- 
~jrm
From: ··········@YahooGroups.Com
Subject: Re: Be afraid of XML
Date: 
Message-ID: <REM-2004mar14-004@Yahoo.Com>
> From: Pete Kirkham <·················@cafemosaic.co.uk>
> XML is a general tree syntax suitable for world-wide use. XML is a
> pruned scion of SGML so it has angle brackets and closing tags (if
> you are marking up text, then you don't want to escape every
> parenthesis). Is <para id="foo">Hello World</para> so much worse than
> (para :id "foo" :text "Hello World")?

I find it a pain that every < and every > and every & in text needs to
be quoted via &lt; &gt; and &amp; respectively, so I don't see the
improvement compared to needing to quote parentheses instead.

Around 1975 I wrote MRPP3, a.k.a. POX, which was a text-formatting
program for the XGP (Xerox Graphics Printer). It had macros, and
various quoting notation for passing text as arguments to macros. Bill
Gosper used it extensively for his MacSyma research papers/notes,
prodding me to do some of the work on it. But the command syntax was
Algolish mostly, a brick (escape) character to switch from normal text
mode to command mode, followed by a command name, sometimes followed by
arguments, and terminated by a semicolon which returns to regular text
mode. But I got to liking LISP around that time, so in the end I
envisioned a LISP dialect which incorporated my various nesting
character system: (But there was never any funding for such work,
because XGP-PUB was promised any day now, and then TeX got invented and
became the standard, and I got a job doing something else so I switch
work to what was paying my living.)

Some quoting characters are symmetric and can be used only one level
deep, which always invokes super quote mode, for example:
 "Hello World!"    "This text has other (<$|/{[ nesting stuff quoted."
 |Hello World!|
Other nesting characters are asymmetric and can be used multiple levels
deep. One level deep they act in semi-quoting mode, where all other
nesting characters become ordinary characters, but the same nesting
characters, and the 'brick' (a sort of command-escape) character are
still usable. Two levels deep makes super-quote mode where the brick
character is also just a regular character. For example:
  <Stuff single-quoted ( and ( but $command; works <superQuote $junk>>
If you put two quoted strings one after another with no gap,
even/usually with different nesting characters, they append to make one
string. This allows you to mix *all* characters as regular text just by
using some *other* nesting character to quote troublesome text that had
nesting characters in it, even the brick character by using super-quote
mode. For example:
  [Let S = {r in R | r < 0}.]{ [4]}
See how braces are regular text when quoted by brackets, but then vice
versa later?

So the idea is that the same quoting/nesting notation could be used
both for streaming text which is processed on the fly, and for text
strings which are stored as actual strings as part of LISP source code,
except that streaming text is initially outside any quoting/nesting
whereas actual strings are always inside quoting/nesting. As just a
possibility of how this might be used (in lieu of HTML syntax):

If you want to break between paragraphs, you do [<P>] in HTML, but you
do [(P)] here. Here's an actual paragraph break:(P)Now this text is in
a new paragraph, do you see it? [(]Yeah, I know that's only how it was
done using the (B)original(-B) HTML. Nowadays you bracket paragraphs
with [<P>...</P>] instead, which would be [(P)...(-P)] here.[)]

I think it's visually easier to read text where some sort of bracketing
wraps around single troublesome characters or around sections of text
with several troublesome characters, instead of requiring special &lt;
etc. syntax every time a reserved character occurs in HTML text, or
likewise every time a " appears in a LISP string.

Note my proposed syntax is flexible with respect to two styles of
mark-up of nested textual structure, SGML-style:
  (+SECTION)some random text(+SUBSECTION)more(-SUBSECTION)final(-SECTION)
or s-expr polish style:
  (SECTION "some random text" (SUBSECTION "more") "final")

Anyway, just some ideas that never got tried, sigh.

> some of the postings here are bugs caused by parenthesis nesting.

I agree. (operator "Ten pages of text") is a pain, better to use
<OPERATOR>Ten pages of text<\OPERATOR>. But for short expressions
that are highly nested, regular parens such as:
  (LET ((X (+ N 2))
        (Y (- N 2)))
    (* X Y))
is easier to use than the equivalent SGML version:
  <LET><BIND>X<VAL><EXPR>+<,>N<,>2</EXPR></BIND>
       <BIND>Y<VAL><EXPR>-<,>N<,>2</EXPR></BIND>
    <STMT><EXPR>*<,>X<,>Y</EXPR></STMT>
    </LET>
The syntax should support both modes, with the user deciding which is
best for any given task.

> Allow the same abstract tree to be encoded as s-expr, XML, ASN.1,
> RDBMS tables for coding, browser integration, data exchange and
> persistence. Let the web monkeys use XML until they know how to match
> the parentheses. Map the object system to and from UML in an explicit
> manner, and provide model-driven, pattern based and aspect oriented
> programming as language level facilities.

Yeah! Mix them all within a single source/document/mix file.

By the way, whatever happened to true HyperText (Xanadu), where not
just GIFs and other images, but any segments of text also, can be
inlined from some other URL, with the browser presenting the illusion
that all the stuff on-screen came from a single document?
From: Rob Warnock
Subject: Re: Be afraid of XML
Date: 
Message-ID: <DEOdnWDBg4g0K8jd3czS-g@speakeasy.net>
<··········@YahooGroups.Com> wrote:
+---------------
| I agree. (operator "Ten pages of text") is a pain, better to use
| <OPERATOR>Ten pages of text<\OPERATOR>.
+---------------

Google in the c.l.l. archives for "TML", a format Tim Bradshaw uses that
was inspired by some postings by Erik Naggum. In TML, the above would be:

    <operator|Ten pages of text>

and the HTML <font color="red">This is a <b>bold</b> one!</font> would
in TML be <font :color "red"|This is a <b|bold> one!>.


-Rob

p.s. The following single hit gives a quick overview of TML:

    <URL:http://groups.google.com/groups?q=%2B%22TML%22+bradshaw+naggum+
	 group:comp.lang.lisp.*&hl=en&lr=&ie=UTF-8&group=comp.lang.lisp.*&
	 selm=ey3elagc8bz.fsf%40cley.com&rnum=1>

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Tim Bradshaw
Subject: Re: Be afraid of XML
Date: 
Message-ID: <fbc0f5d1.0403151204.47798b11@posting.google.com>
····@rpw3.org (Rob Warnock) wrote in message news:<······················@speakeasy.net>...
> <··········@YahooGroups.Com> wrote:
> +---------------
> | I agree. (operator "Ten pages of text") is a pain, better to use
> | <OPERATOR>Ten pages of text<\OPERATOR>.
> +---------------
> 
> Google in the c.l.l. archives for "TML", a format Tim Bradshaw uses that
> was inspired by some postings by Erik Naggum. In TML, the above would be:
> 
>     <operator|Ten pages of text>
> 

For what it's worth, we've now used TML (in its incarnation as DTML,
which is TML with a macro system) for pretty substantial documents - a
couple of commercial courses as well as a bunch of other stuff,
probably ~1000 pages of hardcopy (which is a small amount in real
terms, but large given that it was all done by 2 people).  Much of
www.cley.com (I think everything but the front page) originates as
TML.

The one substantial change to the syntax that I made is a
literal-section quoting mechanism, which works by using a hole in the
syntax:

  <|x ... x|>

is a literal section, for x being any character.  This is very useful
for (for instance) samples from command lines:

<|"
$ vxdisk list > /tmp/vxdisk.out
>|"

works as you'd expect.

The substantial change that I haven't made because we have `too much
text' to check through (in the same sense that there were `too many'
makefiles whenever they decided not to relax the requirement about
tabs) is to fix the parser to do comments right.  Currently it strips
comments before anything, and in particular it strips them before READ
gets its hands on the lispy part of a form.  So things like:

<this :is "a string with % in"|text>

don't do what you probably expect.  This is really ugly.

Semantically I probably need to rework the D bit of DTML, because it's
fairly non-trivial to implement macros.  Documentation might be enough
though.  There are some other things that need fixed - the output
protocol (it uses my htout stuff) needs reworked, and there needs to
be some way of specifying handlers for literal sections better.

However, these bugs aside, DTML has been an enormous win for us.  It's
not as easy to type as TeX, but the structure is clearer, and it's
much easier to produce good-looking HTML from it.  It's *much* easier
to type than any of the SGML-derived things.

One day, when I have time (so: when I retire I expect) I'm planning to
make it available for free.

--tim
From: Steven E. Harris
Subject: Re: Be afraid of XML
Date: 
Message-ID: <q67hdwpeu1k.fsf@L75001820.us.ray.com>
··········@tfeb.org (Tim Bradshaw) writes:

> The one substantial change to the syntax that I made is a
> literal-section quoting mechanism, which works by using a hole in
> the syntax:
>
>   <|x ... x|>
>
> is a literal section, for x being any character.  This is very
> useful for (for instance) samples from command lines:
>
> <|"
> $ vxdisk list > /tmp/vxdisk.out
> >|"

Should that closing line have been

  "|>

to mirror the opening one, with x being the double-quote character?

-- 
Steven E. Harris        :: ········@raytheon.com
Raytheon                :: http://www.raytheon.com
From: Tim Bradshaw
Subject: Re: Be afraid of XML
Date: 
Message-ID: <fbc0f5d1.0403160233.66cd6afe@posting.google.com>
"Steven E. Harris" <········@raytheon.com> wrote in message news:<···············@L75001820.us.ray.com>...
> 
> Should that closing line have been
> 
>   "|>
> 
> to mirror the opening one, with x being the double-quote character?

Yes, sorry.  I never know how I manage to make three-char
transpositions (xyz instead of zyx) but I do it quite a lot when
typing fast or at a strange keyboard.

--tim
From: Björn Lindberg
Subject: Re: Be afraid of XML
Date: 
Message-ID: <hcsu10pm05g.fsf@tjatte.nada.kth.se>
··········@tfeb.org (Tim Bradshaw) writes:

> ····@rpw3.org (Rob Warnock) wrote in message news:<······················@speakeasy.net>...
> > <··········@YahooGroups.Com> wrote:
> > +---------------
> > | I agree. (operator "Ten pages of text") is a pain, better to use
> > | <OPERATOR>Ten pages of text<\OPERATOR>.
> > +---------------
> > 
> > Google in the c.l.l. archives for "TML", a format Tim Bradshaw uses that
> > was inspired by some postings by Erik Naggum. In TML, the above would be:
> > 
> >     <operator|Ten pages of text>
> > 
> 
> For what it's worth, we've now used TML (in its incarnation as DTML,
> which is TML with a macro system) for pretty substantial documents - a
> couple of commercial courses as well as a bunch of other stuff,
> probably ~1000 pages of hardcopy (which is a small amount in real
> terms, but large given that it was all done by 2 people).  Much of
> www.cley.com (I think everything but the front page) originates as
> TML.

What is the advantage of this (DTML) compared to just using
S-expressions, or something similar to your HTOUT package? Is it only
so that you don't have to double-quote "normal text" or are there
other benefits as well?


Bj�rn
From: Russell Wallace
Subject: Re: Be afraid of XML
Date: 
Message-ID: <4055c14c.57608358@news.eircom.net>
On Sun, 14 Mar 2004 21:48:55 -0800, ··········@YahooGroups.Com wrote:

>By the way, whatever happened to true HyperText (Xanadu), where not
>just GIFs and other images, but any segments of text also, can be
>inlined from some other URL, with the browser presenting the illusion
>that all the stuff on-screen came from a single document?

Maybe someone realized that when a user saves a document, he wants to
come back and find the same document, not a version with half the text
replaced with "This page has moved" etc? Strange people, users :)

-- 
"Sore wa himitsu desu."
To reply by email, remove
the small snack from address.
http://www.esatclear.ie/~rwallace
From: Cliff Crawford
Subject: Re: Be afraid of XML
Date: 
Message-ID: <6zp5c.29377$KB.223@twister.nyroc.rr.com>
On 2004-03-15, ··········@YahooGroups.Com <··········@YahooGroups.Com> wrote:
| 
|  By the way, whatever happened to true HyperText (Xanadu), where not
|  just GIFs and other images, but any segments of text also, can be
|  inlined from some other URL, with the browser presenting the illusion
|  that all the stuff on-screen came from a single document?

Try http://xanadu.com/

(Funny how the first ten hits for "xanadu" on Google are either for
this project, for some mall in Madrid, or for the 1980 Olivia
Newton-John movie, with no mention of Kublai Khan or Coleridge at all
until the third page of results... :)


-- 
 Cliff Crawford             ***             ·····@cornell.edu

"The perfection of art is to conceal art."      -- Quintilian