From: larry
Subject: what lisp can do that C can't do
Date: 
Message-ID: <7b8f89d6.0205220934.6a8eca1b@posting.google.com>
People sometimes post messages asking what you can do in lisp that you
can't do in C.
Here's a toy example that I think answers that question.

Suppose you want to write a function that computes the dot product of
a constant vector
with a variable vector x. f(x,c) = c*x. The problem is that these
vectors are big, lets say
a million elements and the constant vector c contains many elements
that are zero.
A function like the following is very inefficient since you are
looping needlessly over many zero elements.

double f(double *x, double *c, long n)
{
   double s=0;
   for(long i =0;i < n ;i++){
     s += c[i]*x[i]; 
   }

  return s;
}

You might say, okay preprocess the constant vector c to extract the
nonzero elements and
the indices at which these non zero elements can occur.
So you would have a function
preprocess(c, nonzeroElements, nonZeroIndices).
Then you call a function

double f(double *x double *nonZeroElements, long *nonZeroIndices,long
n)
{
    double s=0;
    for(long i =0 ; i<n;i++){
        s += nonZeroElements[nonZeroIndices[i]]*x[nonZeroIndices[i]];
    }
    return s;
}



So now you're only looping through non zero elements.
But this function is still not as efficient as you can get if you
write the function specifically for a given c
since you are looping and doing indirect array indexing.

What you really want to do is write the function f, tailor made for a
specific c.
Suppose c contained the non zero elements = {5,3,2}  at indices =
{10,100,1000}
Then you would want to write the function tailor made for this c.

double f(double *x)
{
    return 5 * x[10] + 3*x[100] *2 *x[1000];
}

This would be nice, no loops, no indirect array indexing and no array
indexing at all for c.

Maybe programmatically creating and compiling a function at runtime
can be done in C, but
it seems like you'd have to hack it because as far as I know C does
not support this.

But in  lisp creating and compiling  functions at runtime is natural
and easy.

From: Wade Humeniuk
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <acivvj$uhk$1@news3.cadvision.com>
"larry" <··········@hotmail.com> wrote in message
·································@posting.google.com...
> People sometimes post messages asking what you can do in lisp that you
> can't do in C.
> Here's a toy example that I think answers that question.
>
> Suppose you want to write a function that computes the dot product of
> a constant vector
> with a variable vector x. f(x,c) = c*x. The problem is that these
> vectors are big, lets say
> a million elements and the constant vector c contains many elements
> that are zero.
> A function like the following is very inefficient since you are
> looping needlessly over many zero elements.
>
> double f(double *x, double *c, long n)
> {
>    double s=0;
>    for(long i =0;i < n ;i++){
>      s += c[i]*x[i];
>    }
>
>   return s;
> }

CL is more than this.  For your example a way of doing it in CL might be:

CL-USER 1 > (defun f (arr1 arr2)
              (loop for x across arr1
                    for c across arr2
                    sum (* x c)))
F

CL-USER 2 > (f #(0.0 10.2 6.5) #(1.2 0.0 2.1))
13.65

CL-USER 3 >

The CL f does much more than the C version..

First, arrays are actual types with length information built in.  If the arrays are of
unequal length an error is signalled.  Length does not explicitly have to passed around.

If the multiplication produces an overflow or underflow an error is signalled.  The C code
above does none of that.

It would be left up to the readers to imagine the code that would have to be added to the
C example to get comparable functionality.

CL-USER 4 > (handler-case (f #(0.0 10.2 6.5) #(1.2 0.0 #\c))
              (arithmetic-error (condition)
                  (format t "OhOh!")))
OhOh!
NIL

CL-USER 5 >

These richer types and error handling functionality, for me, are two things that really
distinguishes C from CL.  To produce a quality program, that can handle the unintended,
without having to write custom error detection code is something very good.

Wade

PS, If one needed to solve this large sparsely populated vector dot product, do it on a
capable vector processing machine (that has built-in assembly instructions for dot
product, like the old Cyber 205 used to have, just one assembly instruction if the vector
is not too large).
From: Barry Watson
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <3CECA7CE.C001262B@uab.ericsson.se>
larry wrote:
>
> Maybe programmatically creating and compiling a function at runtime
> can be done in C, but
> it seems like you'd have to hack it because as far as I know C does
> not support this.

#include <stdlib.h>
#includ <stdio.h>

int main()
{
	FILE *fp;
	fp=fopen("source.c", "w");
	fprintf(fp, "#include <stdio.h>\nint main(){printf(\"hello world\");
return 0}");
	fclose(fp);
	system("cc source.c");
	system("./a.out");
	return 0;
}


How hard was that?
From: Alexander Kjeldaas
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <aciccu$c4b$1@news.broadnet.no>
Barry Watson wrote:

> 
> 
> larry wrote:
>>
>> Maybe programmatically creating and compiling a function at runtime
>> can be done in C, but
>> it seems like you'd have to hack it because as far as I know C does
>> not support this.
> 
> #include <stdlib.h>
> #includ <stdio.h>
> 
> int main()
> {
> FILE *fp;
> fp=fopen("source.c", "w");
> fprintf(fp, "#include <stdio.h>\nint main(){printf(\"hello world\");
> return 0}");
> fclose(fp);
> system("cc source.c");
> system("./a.out");
> return 0;
> }
> 
> 
> How hard was that?

Is the "cc" program part of the C runtime system?

astor
From: Kragen Sitaker
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <831yblzjsn.fsf@panacea.canonical.org>
Alexander Kjeldaas <·····@fast.no> writes:
> Is the "cc" program part of the C runtime system?

The C language usually ships with a very large runtime system called
"Unix", although some more recent implementations aimed at small
systems (such as 8-bit microprocessors) omit this "Unix", including
only a minimal "C library".  "cc" is a standard part of Unix.
From: Rahul Jain
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <87k7pd385f.fsf@localhost.localdomain>
Kragen Sitaker <······@pobox.com> writes:

> "cc" is a standard part of Unix.

Then I suppose most Unices are non-standard, although that's probably
a given considering how much most of them seem to care about POSIX. :)

-- 
-> -/                        - Rahul Jain -                        \- <-
-> -\  http://linux.rice.edu/~rahul -=-  ············@techie.com   /- <-
-> -X "Structure is nothing if it is all you got. Skeletons spook  X- <-
-> -/  people if [they] try to walk around on their own. I really  \- <-
-> -\  wonder why XML does not." -- Erik Naggum, comp.lang.lisp    /- <-
|--|--------|--------------|----|-------------|------|---------|-----|-|
   (c)1996-2002, All rights reserved. Disclaimer available upon request.
From: Raymond Wiker
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <863cw13823.fsf@raw.grenland.fast.no>
Kragen Sitaker <······@pobox.com> writes:

> Alexander Kjeldaas <·····@fast.no> writes:
> > Is the "cc" program part of the C runtime system?
> 
> The C language usually ships with a very large runtime system called
> "Unix", although some more recent implementations aimed at small
> systems (such as 8-bit microprocessors) omit this "Unix", including
> only a minimal "C library".  "cc" is a standard part of Unix.

        Not correct - there have been several version of Unix that
shipped without any compilers at all - including, but not limited to,
Solaris and SCO.

-- 
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: Kragen Sitaker
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <83d6v5tpq5.fsf@panacea.canonical.org>
Raymond Wiker <·············@fast.no> writes:
> Kragen Sitaker <······@pobox.com> writes:
> > Alexander Kjeldaas <·····@fast.no> writes:
> > > Is the "cc" program part of the C runtime system?
> > 
> > The C language usually ships with a very large runtime system called
> > "Unix", although some more recent implementations aimed at small
> > systems (such as 8-bit microprocessors) omit this "Unix", including
> > only a minimal "C library".  "cc" is a standard part of Unix.
> 
>         Not correct - there have been several version of Unix that
> shipped without any compilers at all - including, but not limited to,
> Solaris and SCO.

Pretty much limited to those two.

SCO began as an implementation aimed at an 8-bit microprocessor; Unix
users always complained when they had to use SCO.  Solaris always has
a "cc", even when all it says is "pay us more money to supply you with
this standard functionality".

Besides, as long as I'm calling Unix a part of C, I might as well deny
Solaris-without-compilers and SCO the honor of being "Unix".

Back to reality.  In my life, I've had accounts on and logged into
several dozen Unix boxes, running SunOS, numerous versions of Solaris,
a couple of versions of IRIX, BSD/OS, dozens of versions of Linux,
FreeBSD, NetBSD, OpenBSD, AIX, Ultrix, "Tru64 Unix" (OSF/1), NeXTStep,
MacOS X.  Their CPUs have been 68000 variants, several varieties of
SPARC, StrongARMs, various POWER chips, Intel 386 family and their AMD
clones, IBM zSeries CPUs. HP PA-RISC chips, Motorola PowerPCs, and
bunches of MIPS variants.  Thank the lord, I have never logged into a
SCO box.  These machines have been owned by my university, a telecom
software company, Compaq, IBM, various friends, government research
contractors, and me.

Of all these machines, two have not had a working 'cc' command.  One
of them is the Sun 3/60 I use as an X terminal --- it netboots a
minimal NetBSD install, containing only the kernel, the shell, the X
server, and the startup script, from my Linux box --- and the other is
a handheld iPaq with no disk and 32 megs of RAM.

So you can buy Solaris with no C compiler.  But of the dozens of Suns
I've used, none were ever configured that way.

It's a stupid argument, anyway.  If I'd slept anytime in the last 24
hours, I probably wouldn't bother to participate.
From: Coby Beck
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <558H8.37514$Ka.2775665@news2.calgary.shaw.ca>
"Barry Watson" <············@uab.ericsson.se> wrote in message
······················@uab.ericsson.se...
>
>
> larry wrote:
> >
> > Maybe programmatically creating and compiling a function at runtime
> > can be done in C, but
> > it seems like you'd have to hack it because as far as I know C does
> > not support this.
>
> #include <stdlib.h>
> #includ <stdio.h>
>
> int main()
> {
> FILE *fp;
> fp=fopen("source.c", "w");
> fprintf(fp, "#include <stdio.h>\nint main(){printf(\"hello world\");
> return 0}");
> fclose(fp);
> system("cc source.c");
> system("./a.out");
> return 0;
> }
>
>
> How hard was that?

Pretty easy.  Of course it is really not comparable at all.  You did not
compile a function at runtime, you created an executable and ran it.  The
dynamically created function can see the special variables and global data
structures of the program that wrote it, it can be applied to arguments and
its return value used, it can side effect the creating program, it does not
rely on disc access and system calls and pipes or files to exchange
information.

(I answered assuming you are just being naive, not trolling)

--
Coby Beck
(remove #\Space "coby 101 @ bigpond . com")
From: Matthew X. Economou
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <w4olmaacwoi.fsf@eco-fs1.irtnog.org>
>>>>> "Coby" == Coby Beck <·····@mercury.bc.ca> writes:

    Coby> Pretty easy.  Of course it is really not comparable at all.
    Coby> You did not compile a function at runtime, you created an
    Coby> executable and ran it.  The dynamically created function can
    Coby> see the special variables and global data structures of the
    Coby> program that wrote it, it can be applied to arguments and
    Coby> its return value used, it can side effect the creating
    Coby> program, it does not rely on disc access and system calls
    Coby> and pipes or files to exchange information.

That's all possible in C.  Unfortunately, even with modern dynamic
linker/loaders, it is somewhat complicated and always non-standard.

Common Lisp makes standard access to the linker/loader as easy as a
single function call.  This is incredibly convenient.  :)

-- 
Matthew X. Economou <········@irtnog.org> - Unsafe at any clock speed!
I'm proud of my Northern Tibetian heritage! (http://www.subgenius.com)
From: Kaz Kylheku
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <slrnaer2qr.e9.kaz@localhost.localdomain>
On 23 May 2002 18:43:25 -0400, Matthew X. Economou
<···············@irtnog.org> wrote:
>>>>>> "Coby" == Coby Beck <·····@mercury.bc.ca> writes:
>
>    Coby> Pretty easy.  Of course it is really not comparable at all.
>    Coby> You did not compile a function at runtime, you created an
>    Coby> executable and ran it.  The dynamically created function can
>    Coby> see the special variables and global data structures of the
>    Coby> program that wrote it, it can be applied to arguments and
>    Coby> its return value used, it can side effect the creating
>    Coby> program, it does not rely on disc access and system calls
>    Coby> and pipes or files to exchange information.
>
>That's all possible in C.  Unfortunately, even with modern dynamic
>linker/loaders, it is somewhat complicated and always non-standard.
>
>Common Lisp makes standard access to the linker/loader as easy as a
>single function call.  This is incredibly convenient.  :)

Even with access to nonstandard functions for dynamically loading modules,
C leaves to you the problem of managing the representation of a C program.

You have no easy way to construct C code, or to subject it to verifications or
transformations upon loading it. 

You have the binary representation, which is not susceptible to such processes,
and you have the source representation, which has an unwieldy syntax for you to
parse, and leaves to you the selection of data structures for its intermediate
representation.

What if, for instance, you want to load an expression from a file, and then
walk over that expression, prior to evaluating it, to make sure that it
conforms to some ``safe'' language subset, for instance?

To do that in C, you would have to write your own parser.  If a C program needs
this type of functionality, it's better to just embed a Lisp implementation in
it and use that.
From: Barry Watson
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <3CEDF424.17A17B14@uab.ericsson.se>
Kaz Kylheku wrote:
> 
> On 23 May 2002 18:43:25 -0400, Matthew X. Economou
> <···············@irtnog.org> wrote:
> >>>>>> "Coby" == Coby Beck <·····@mercury.bc.ca> writes:
> >
> >    Coby> Pretty easy.  Of course it is really not comparable at all.
> >    Coby> You did not compile a function at runtime, you created an
> >    Coby> executable and ran it.  The dynamically created function can
> >    Coby> see the special variables and global data structures of the
> >    Coby> program that wrote it, it can be applied to arguments and
> >    Coby> its return value used, it can side effect the creating
> >    Coby> program, it does not rely on disc access and system calls
> >    Coby> and pipes or files to exchange information.
> >
> >That's all possible in C.  Unfortunately, even with modern dynamic
> >linker/loaders, it is somewhat complicated and always non-standard.
> >
> >Common Lisp makes standard access to the linker/loader as easy as a
> >single function call.  This is incredibly convenient.  :)
> 
> Even with access to nonstandard functions for dynamically loading modules,
> C leaves to you the problem of managing the representation of a C program.

It's not a problem really.
 
> You have no easy way to construct C code, or to subject it to verifications or
> transformations upon loading it.

Yes you do, no difference between printf and cons. 
 
> You have the binary representation, which is not susceptible to such processes,
> and you have the source representation, which has an unwieldy syntax for you to
> parse, 

Lex and yacc. I don't even have to generate C code, I can create code in
another language if I want. 

> and leaves to you the selection of data structures for its intermediate
> representation.

A non argument, you're using a list. What's to stop me using a list. 
 
> What if, for instance, you want to load an expression from a file, and then
> walk over that expression, prior to evaluating it, to make sure that it
> conforms to some ``safe'' language subset, for instance?

People have written whole compilers in C :)
 
> To do that in C, you would have to write your own parser.  If a C program needs
> this type of functionality, it's better to just embed a Lisp implementation in
> it and use that.

*shakes the heid*
From: Marco Antoniotti
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <y6cr8k1blkq.fsf@octagon.mrl.nyu.edu>
Barry Watson <············@uab.ericsson.se> writes:

> Kaz Kylheku wrote:
> > 
        ...
> > You have no easy way to construct C code, or to subject it to verifications or
> > transformations upon loading it.
> 
> Yes you do, no difference between printf and cons. 
>  

What is the "seventh" element of the result (in a file) of

        printf("I am @the [34th element, given the array <1 2 3>]\n");

You are missing the basic (Common) Lisp mantra, what you PRINT is what
you READ :)

> > You have the binary representation, which is not susceptible to such processes,
> > and you have the source representation, which has an unwieldy syntax for you to
> > parse, 
> 
> Lex and yacc. I don't even have to generate C code, I can create code in
> another language if I want. 

Exaclty the Lisper's point.  You do not want to deal with Lex and yacc :)

....

Cheers

-- 
Marco Antoniotti ========================================================
NYU Courant Bioinformatics Group        tel. +1 - 212 - 998 3488
719 Broadway 12th Floor                 fax  +1 - 212 - 995 4122
New York, NY 10003, USA                 http://bioinformatics.cat.nyu.edu
                    "Hello New York! We'll do what we can!"
                           Bill Murray in `Ghostbusters'.
From: Barry Margolin
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <fwtH8.4$006.613@paloalto-snr2.gtei.net>
In article <···············@octagon.mrl.nyu.edu>,
Marco Antoniotti  <·······@cs.nyu.edu> wrote:
>Exaclty the Lisper's point.  You do not want to deal with Lex and yacc :)

The Lisp reader is most closely analogous to lex.  If you want to analyze
the code, you still have to write much of your own parser.

However, Lisp's syntax is easier to parse than C, since everything is in
the form (<operator> . <operands>).  But your parser still needs to
understand the detailed structure of all special forms, just as a C parser
needs to know about all the keywords.

-- 
Barry Margolin, ······@genuity.net
Genuity, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Marco Antoniotti
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <y6csn4hgnps.fsf@octagon.mrl.nyu.edu>
Barry Margolin <······@genuity.net> writes:

> In article <···············@octagon.mrl.nyu.edu>,
> Marco Antoniotti  <·······@cs.nyu.edu> wrote:
> >Exaclty the Lisper's point.  You do not want to deal with Lex and yacc :)
> 
> The Lisp reader is most closely analogous to lex.  If you want to analyze
> the code, you still have to write much of your own parser.
> 
> However, Lisp's syntax is easier to parse than C, since everything is in
> the form (<operator> . <operands>).  But your parser still needs to
> understand the detailed structure of all special forms, just as a C parser
> needs to know about all the keywords.

Yes.  But in (Common) Lisp, parsing is more trivial also because you
your expressions are already in a almost completely parsed form.  For
any language you define, working with C (C++, Java, whatever) demands
that you use a Lex/Yacc pair (or similar).

The bottom line is that writing "parsers" for S-exprs based languages
is extremely easy in (Common) Lisp.  Writing any parser in another
language is at a minimum a tedious chore.

Cheers


-- 
Marco Antoniotti ========================================================
NYU Courant Bioinformatics Group        tel. +1 - 212 - 998 3488
719 Broadway 12th Floor                 fax  +1 - 212 - 995 4122
New York, NY 10003, USA                 http://bioinformatics.cat.nyu.edu
                    "Hello New York! We'll do what we can!"
                           Bill Murray in `Ghostbusters'.
From: Christopher Browne
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <acmmtk$qpvcv$1@ID-125932.news.dfncis.de>
Quoth Marco Antoniotti <·······@cs.nyu.edu>:
> The bottom line is that writing "parsers" for S-exprs based languages
> is extremely easy in (Common) Lisp.  Writing any parser in another
> language is at a minimum a tedious chore.

Hardly.  

Writing "parsers" for S-expression-based languages is _completely
unnecessary_, because the language comes with a perfectly good parser
built-in.
-- 
(concatenate 'string "chris" ·@cbbrowne.com")
http://www3.sympatico.ca/cbbrowne/spiritual.html
"World domination.  Fast."  -- Linus Torvalds
From: Marco Antoniotti
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <y6coff0fig8.fsf@octagon.mrl.nyu.edu>
Christopher Browne <········@acm.org> writes:

> Quoth Marco Antoniotti <·······@cs.nyu.edu>:
> > The bottom line is that writing "parsers" for S-exprs based languages
> > is extremely easy in (Common) Lisp.  Writing any parser in another
> > language is at a minimum a tedious chore.
> 
> Hardly.  
> 
> Writing "parsers" for S-expression-based languages is _completely
> unnecessary_, because the language comes with a perfectly good parser
> built-in.

Well yes. :)  I meant that you still have to write a few
DESTRUCTURING-BIND here and there to "interpret" you S-exprs :) And
this happens only if you need to go beyond macros.

Cheers

-- 
Marco Antoniotti ========================================================
NYU Courant Bioinformatics Group        tel. +1 - 212 - 998 3488
719 Broadway 12th Floor                 fax  +1 - 212 - 995 4122
New York, NY 10003, USA                 http://bioinformatics.cat.nyu.edu
                    "Hello New York! We'll do what we can!"
                           Bill Murray in `Ghostbusters'.
From: Barry Margolin
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <U0OI8.6$hV.291@paloalto-snr2.gtei.net>
In article <··············@ID-125932.news.dfncis.de>,
Christopher Browne  <········@acm.org> wrote:
>Writing "parsers" for S-expression-based languages is _completely
>unnecessary_, because the language comes with a perfectly good parser
>built-in.

What's the name of the standard function that parses a DEFUN form,
extracting the variable bindings, declarations, documentation string, and
body forms?

-- 
Barry Margolin, ······@genuity.net
Genuity, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Christopher Browne
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <ad0d8u$t60po$1@ID-125932.news.dfncis.de>
The world rejoiced as Barry Margolin <······@genuity.net> wrote:
> In article <··············@ID-125932.news.dfncis.de>,
> Christopher Browne  <········@acm.org> wrote:
>>Writing "parsers" for S-expression-based languages is _completely
>>unnecessary_, because the language comes with a perfectly good parser
>>built-in.
>
> What's the name of the standard function that parses a DEFUN form,
> extracting the variable bindings, declarations, documentation string, and
> body forms?

EVAL :-).
-- 
(reverse (concatenate 'string ········@" "enworbbc"))
http://www.cbbrowne.com/info/spreadsheets.html
"...I'm not one  of those who think Bill Gates is  the devil. I simply
suspect that if Microsoft ever met up with the devil, it wouldn't need
an interpreter." -- Nicholas Petreley, InfoWorld, Sept 16, 1996
From: Marco Antoniotti
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <y6cbsay4yex.fsf@octagon.mrl.nyu.edu>
Barry Margolin <······@genuity.net> writes:

> In article <··············@ID-125932.news.dfncis.de>,
> Christopher Browne  <········@acm.org> wrote:
> >Writing "parsers" for S-expression-based languages is _completely
> >unnecessary_, because the language comes with a perfectly good parser
> >built-in.
> 
> What's the name of the standard function that parses a DEFUN form,
> extracting the variable bindings, declarations, documentation string, and
> body forms?

Well, you do have a point, but the code snippet that does that is

        (defstructuring-bind (defun-kwd fun-name arglist &rest rest)
            defun-form
          (grok rest))

You know very well, that before getting to that point with Lex/Yacc
you have to do quite a bit of grunt work.

Cheers

-- 
Marco Antoniotti ========================================================
NYU Courant Bioinformatics Group        tel. +1 - 212 - 998 3488
719 Broadway 12th Floor                 fax  +1 - 212 - 995 4122
New York, NY 10003, USA                 http://bioinformatics.cat.nyu.edu
                    "Hello New York! We'll do what we can!"
                           Bill Murray in `Ghostbusters'.
From: Russell Wallace
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <3cf4a62a.101447839@news.eircom.net>
On 24 May 2002 18:55:43 -0400, Marco Antoniotti <·······@cs.nyu.edu>
wrote:

>Yes.  But in (Common) Lisp, parsing is more trivial also because you
>your expressions are already in a almost completely parsed form.

Yes.

>For
>any language you define, working with C (C++, Java, whatever) demands
>that you use a Lex/Yacc pair (or similar).

I find writing parsers in C for simple languages is trivial.

>The bottom line is that writing "parsers" for S-exprs based languages
>is extremely easy in (Common) Lisp.  Writing any parser in another
>language is at a minimum a tedious chore.

I'd put it in the category of cat-hoovering exercise - a pleasant
activity for when you're too tired to do any real work.

(Parsing the full C language, on the other hand, is real work. Parsing
C++ is a job for a braver man than me :))

-- 
"Mercy to the guilty is treachery to the innocent."
http://www.esatclear.ie/~rwallace
mail:rw(at)eircom(dot)net
From: Paolo Amoroso
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <8STxPJzFBaBU5zPtbC6Xnqbahe6O@4ax.com>
On Fri, 24 May 2002 16:04:27 GMT, Barry Margolin <······@genuity.net>
wrote:

> The Lisp reader is most closely analogous to lex.  If you want to analyze
> the code, you still have to write much of your own parser.

I must be missing something. If I READ a list such as:

  (let's add (some (nesting) here))

I get a data structure that is more than the sequence of tokens such as
"(", "let's", "add", and so on that I would get with lex. Or not? Isn't
what READ returns more similar to what you would get from a barebone yacc
grammar without actions?


Paolo
-- 
EncyCMUCLopedia * Extensive collection of CMU Common Lisp documentation
http://www.paoloamoroso.it/ency/README
[http://cvs2.cons.org:8000/cmucl/doc/EncyCMUCLopedia/]
From: Christopher Browne
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <acp69q$rk5qm$13@ID-125932.news.dfncis.de>
In the last exciting episode, Marco Antoniotti <·······@cs.nyu.edu> wrote::
> Barry Watson <············@uab.ericsson.se> writes:
>> Kaz Kylheku wrote:
>> > You have the binary representation, which is not susceptible to
>> > such processes, and you have the source representation, which has
>> > an unwieldy syntax for you to parse,
>> 
>> Lex and yacc. I don't even have to generate C code, I can create
>> code in another language if I want.
>
> Exactly the Lisper's point.  You do not want to deal with Lex and
> yacc :)

The _Lisper_ doesn't want to deal with Lex and yacc.

I recently had the opportunity to fiddle through some samples; never
had worked with lex/yacc before.  It _far_ and away beats the sort of
code that typically gets written by hand.  I will say that the
combination of the tools Sucks Pretty Bad; it is a _pain_ to work
with.

But it still beats the typical hand-written C for the purpose.  The
world would probably be a slightly better place if lex and yacc were
more widely used.

But my primary reaction was that the way I'd _prefer_ to use lex and
yacc would be to generate s-expressions :-).
-- 
(reverse (concatenate 'string ··········@" "enworbbc"))
http://www.cbbrowne.com/info/wp.html
"Like I've always  said, if you don't have anything  nice to say, come
sit by me." -- Steel Magnolias
From: Kaz Kylheku
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <slrnaesvpa.16d.kaz@localhost.localdomain>
On Fri, 24 May 2002 10:04:52 +0200, Barry Watson
<············@uab.ericsson.se> wrote:
>
>
>Kaz Kylheku wrote:
>> 
>> On 23 May 2002 18:43:25 -0400, Matthew X. Economou
>> <···············@irtnog.org> wrote:
>> >>>>>> "Coby" == Coby Beck <·····@mercury.bc.ca> writes:
>> >
>> >    Coby> Pretty easy.  Of course it is really not comparable at all.
>> >    Coby> You did not compile a function at runtime, you created an
>> >    Coby> executable and ran it.  The dynamically created function can
>> >    Coby> see the special variables and global data structures of the
>> >    Coby> program that wrote it, it can be applied to arguments and
>> >    Coby> its return value used, it can side effect the creating
>> >    Coby> program, it does not rely on disc access and system calls
>> >    Coby> and pipes or files to exchange information.
>> >
>> >That's all possible in C.  Unfortunately, even with modern dynamic
>> >linker/loaders, it is somewhat complicated and always non-standard.
>> >
>> >Common Lisp makes standard access to the linker/loader as easy as a
>> >single function call.  This is incredibly convenient.  :)
>> 
>> Even with access to nonstandard functions for dynamically loading modules,
>> C leaves to you the problem of managing the representation of a C program.
>
>It's not a problem really.
> 
>> You have no easy way to construct C code, or to subject it to verifications or
>> transformations upon loading it.
>
>Yes you do, no difference between printf and cons. 

There is a big difference. Printf creates an unstructured text string, a flat
array of character objects.  Whereas cons creates a structure.

Before you can use your printf, you will likely need some data structures
in which you do cons-like things. The printf function is just the vehicle
for creating a printed representation of that structure. If you choose a bad
syntax for that representation, you will also need a complicated parser.

In Lisp, we have the formatting and parsing built in. A program can format a
piece of itself to text, store it in a file, and later retrieve it; the
structure instantly materializes. This just requires a few lines of code.

>> You have the binary representation, which is not susceptible to such processes,
>> and you have the source representation, which has an unwieldy syntax for you to
>> parse, 
>
>Lex and yacc. I don't even have to generate C code, I can create code in
>another language if I want. 
>
>> and leaves to you the selection of data structures for its intermediate
>> representation.
>
>A non argument, you're using a list. What's to stop me using a list. 

Firstly, that you will have to invent that data structure from scratch, like
every other C programmer before you.  Secondly, that it's not enough to have a
list, but to also have other data types to put into that list.  Let's take
symbols for instance; you will have to invent a symbol data structure. And not
only that, but data structures for storing symbols and looking them up. And of
course, your symbol data structure will be slightly different from that
previously invented by every compiler hacker before you.  With the parser, and
all the abstract syntax tree data structures in place, you still need an
evaluator.  In the midst of all this, you will have to deal with memory leaks,
premature deallocations and other C programming nasties.

It's clear that C is a systems programming language in which you can make
implementations of other languages. That doesn't make it comparable to these
other languages; it just means that if you start with C, you have extra work to
do. You get very little help from the language in doing this, because you have
to instruct the machine in every little detail how to behave as a symbolic
processor. It should also be noted that doing this well requires a background
in compiler construction, something that not every developer has.

This is a major software project in itself.

If something is a major software project in C, but in Lisp I it can be done
using a few function calls, then it's something that Lisp can do that C cannot.
It's something that Lisp can do which a C *programmer* can also emulate
with a lot of human effort, but that's not the same thing.

I think you should internalize Greenspun's Tenth Rule: ``Any sufficiently
complicated C or Fortran program contains an ad hoc informally-specified
bug-ridden slow implementation of half of Common Lisp.''

>> What if, for instance, you want to load an expression from a file, and then
>> walk over that expression, prior to evaluating it, to make sure that it
>> conforms to some ``safe'' language subset, for instance?
>
>People have written whole compilers in C :)

But unfortunately most of those compilers don't integrate into other
applications written in C. Which means that their developers can take
shortcuts, such as never free()'ing the data structures produced during
parsing, and other stages. That's okay, because the program is short-lived and
the operating system will clean up after it.  In an embeddable compiler, much
more care is required, because it returns control to the calling program. 

Writing compilers in C requires a significant time investment; viable C
compilers are major software projects spanning years of effort by multiple
developers who chose to sacrifice their lives, so that others could do the same
in their footsteps.

Now what if the actual application you want to write is something other than a
compiler, but you want a built-in compiler in order to write parts of it?

If you don't want to spend your time writing that compiler, you can use
some off-the shelf one.  Among your choices would be embedding some Lisp
into your C program.

In Lisp, we have access to the compiler built into the language in a standard
way, and all the data structures needed to conveniently manipulate code.  If
it's morning, and you need to write a program that stores pieces of itself in a
file to be later loaded and evaluated, you can be done by afternoon.  Moreover,
a Lisp expression written by one implementation can be read by another.
It's not stored in a representation that is unique to your program.
From: Barry Watson
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <3CEDF326.318319FE@uab.ericsson.se>
Coby Beck wrote:
> 
> "Barry Watson" <············@uab.ericsson.se> wrote in message
> ······················@uab.ericsson.se...
> >
> >
> > larry wrote:
> > >
> > > Maybe programmatically creating and compiling a function at runtime
> > > can be done in C, but
> > > it seems like you'd have to hack it because as far as I know C does
> > > not support this.
> >
> > #include <stdlib.h>
> > #includ <stdio.h>
> >
> > int main()
> > {
> > FILE *fp;
> > fp=fopen("source.c", "w");
> > fprintf(fp, "#include <stdio.h>\nint main(){printf(\"hello world\");
> > return 0}");
> > fclose(fp);
> > system("cc source.c");
> > system("./a.out");
> > return 0;
> > }
> >
> >
> > How hard was that?
> 
> Pretty easy.  Of course it is really not comparable at all. 

eh?

> You did not
> compile a function at runtime, 

yes I did

>you created an executable and ran it.  

I compiled a function then ran it.

>The
> dynamically created function can see the special variables and global data
> structures of the program that wrote it, it can be applied to arguments and
> its return value used, it can side effect the creating program, it does not
> rely on disc access and system calls and pipes or files to exchange
> information.

Doing it in C is much cleaner than in lisp, I get to control the
namespaces plus I get the advantage of compiled code. I think you're
biased.

> (I answered assuming you are just being naive, not trolling)

You're funny.
From: Gareth McCaughan
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <slrnaes2u5.2ia3.Gareth.McCaughan@g.local>
(I think Barry Watson is probably trolling, but even if so
it's possible that someone might be reading this who takes
his points seriously. So ...)

Barry Watson wrote:

[SNIP: a C program invoking an external C compiler and running
the executable it produces. Someone else responded:]

> >The
> > dynamically created function can see the special variables and global data
> > structures of the program that wrote it, it can be applied to arguments and
> > its return value used, it can side effect the creating program, it does not
> > rely on disc access and system calls and pipes or files to exchange
> > information.
> 
> Doing it in C is much cleaner than in lisp, I get to control the
> namespaces plus I get the advantage of compiled code. I think you're
> biased.

That phrase "plus I get the advantages of compiled code" sets
some little alarm bells ringing. You aren't under the impression
that Lisp code doesn't run compiled, are you? That's commonly
believed but about 40 years out of date.

The technique you describe can be used equally well in any
language that gives you the ability to run external programs.
Lisp can do it just as well as C can. You're right that it has
some advantages over the Lisp way, but it also has some serious
disadvantages.

  - It is likely to be much slower, in two ways.

      - When you compile your dynamically-generated function,
        you have all the overhead of starting a new process,
        running a compiler, reading and writing multiple files,
        and so on. On my machine, calling the C compiler on the
        most trivial input file possible takes about 0.1 seconds.
        That's a long time if you have to do it often.

      - When you call your dynamically-generated function,
        you have to run a new program each time (with code
        maximally like what you posted earlier) or, with
        substantially more implementation effort, you can
        instead just have to marshal all the arguments into
        textual form, pass them through a pipe, get the results
        back from a pipe, and unmarshal them into whatever form
        you really need. Either way, it's likely to be much
        more expensive than just calling the function.
        This particular source of pain largely goes away
        with dynamic linking, but that has other drawbacks;
        it diminishes but doesn't completely go if you use
        shared memory, but that too has other drawbacks.

  - It is much more cumbersome to write, especially if you
    want to do the communicating-via-pipes thing. Still more
    if you want to use shared memory or dynamic linking.
    If you use the external-program approach then there's
    a lot of bookkeeping pain if you want the external program
    to stay around (e.g., so it can have persistent state, or
    for greater efficiency).

  - Portability is terrible. This is bad in theory but possibly
    OK in practice in the simplest and most inefficient case
    (though you still lose horribly on most Windows machines,
    for instance); if you want to use pipes, it gets worse; if
    you want shared memory, worse again; if you want dynamic
    linking, even worse still.

  - It isn't true that you "get to control the namespaces". You
    get *less* control over the namespaces than a Lisp programmer
    does. Your only option is to have them entirely disjoint,
    and to have the programs communicate through some sort of
    explicit interface: pipes or shared memory or external files
    or something. Dynamic linking makes it possible to communicate
    through global variables, but then it's even less true that
    you "get to control the namespaces".

  - It's much more awkward to create little functions on the fly
    and then pass them around. The exact way in which this hurts
    varies according to your implementation strategy; all of them
    are hugely worse than for Lisp, where you just say "lambda"
    and you're done.

  - It relies on the ability to create arbitrary files and run
    arbitrary programs. This can be a major security risk. That's
    why server programs often run with insufficient privileges to
    do what you described.

If you seriously think that the C way is just as good as the
Lisp way, then either (1) you need to find out more about the
Lisp way, or (2) you've been tricked by years of C programming
into thinking that the C way is painless, or (3) I'm missing
something really big.

I don't think it's #3.

-- 
Gareth McCaughan  ················@pobox.com
.sig under construc
From: Barry Watson
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <3CEE14B3.5DCAD6F3@uab.ericsson.se>
Gareth McCaughan wrote:
> 
> (I think Barry Watson is probably trolling, but even if so
> it's possible that someone might be reading this who takes
> his points seriously. So ...)

no troll

 
> That phrase "plus I get the advantages of compiled code" sets
> some little alarm bells ringing. You aren't under the impression
> that Lisp code doesn't run compiled, are you? That's commonly
> believed but about 40 years out of date.

I've only ever written lisp interpreters and compiled lisp to byte code,
never native. Maybe I was relying to much on experiences with my own
toys and not commerical systems. 

> The technique you describe can be used equally well in any
> language that gives you the ability to run external programs.
> Lisp can do it just as well as C can. You're right that it has
> some advantages over the Lisp way, but it also has some serious
> disadvantages.

Ok, but the original suggestion was it was not doable in C. My claim was
that it was.
 
>   - It is likely to be much slower, in two ways.
> 
>       - When you compile your dynamically-generated function,
>         you have all the overhead of starting a new process,
>         running a compiler, reading and writing multiple files,
>         and so on. On my machine, calling the C compiler on the
>         most trivial input file possible takes about 0.1 seconds.
>         That's a long time if you have to do it often.

Yes I agree. However, this is a one time cost.
 
>       - When you call your dynamically-generated function,
>         you have to run a new program each time (with code
>         maximally like what you posted earlier) or, with
>         substantially more implementation effort, you can
>         instead just have to marshal all the arguments into
>         textual form, pass them through a pipe, get the results
>         back from a pipe, and unmarshal them into whatever form
>         you really need. Either way, it's likely to be much
>         more expensive than just calling the function.
>         This particular source of pain largely goes away
>         with dynamic linking, but that has other drawbacks;
>         it diminishes but doesn't completely go if you use
>         shared memory, but that too has other drawbacks.

True. I could however keep the functions hanging around as processes.
 
>   - It is much more cumbersome to write, especially if you
>     want to do the communicating-via-pipes thing. Still more
>     if you want to use shared memory or dynamic linking.

But doable.

>     If you use the external-program approach then there's
>     a lot of bookkeeping pain if you want the external program
>     to stay around (e.g., so it can have persistent state, or
>     for greater efficiency).

I don't see this. Can you explain further?
 
>   - Portability is terrible. This is bad in theory but possibly
>     OK in practice in the simplest and most inefficient case
>     (though you still lose horribly on most Windows machines,
>     for instance); if you want to use pipes, it gets worse; if
>     you want shared memory, worse again; if you want dynamic
>     linking, even worse still.

granted but it was more demonstration of how it might be done.
 
>   - It isn't true that you "get to control the namespaces". You
>     get *less* control over the namespaces than a Lisp programmer
>     does. Your only option is to have them entirely disjoint,
>     and to have the programs communicate through some sort of
>     explicit interface: pipes or shared memory or external files
>     or something.

The control comes from the freedom to design this interface. With lisp
it is built in so to say.

>  Dynamic linking makes it possible to communicate
>     through global variables, but then it's even less true that
>     you "get to control the namespaces".

I wasn't actually thinking about dynamic linking but I agree it is the
least flexible option.

 
>   - It's much more awkward to create little functions on the fly
>     and then pass them around. The exact way in which this hurts
>     varies according to your implementation strategy; all of them
>     are hugely worse than for Lisp, where you just say "lambda"
>     and you're done.

For the human programmer yes but not for a machine generated C code,
i.e., human problems not language problems.
 
>   - It relies on the ability to create arbitrary files and run
>     arbitrary programs. This can be a major security risk. That's
>     why server programs often run with insufficient privileges to
>     do what you described.

Nah, we can get round that. This is an OS issue. A modern well designed
OS would remove this problem.
 
> If you seriously think that the C way is just as good as the
> Lisp way, then either (1) you need to find out more about the
> Lisp way, or (2) you've been tricked by years of C programming
> into thinking that the C way is painless, or (3) I'm missing
> something really big.
> 
> I don't think it's #3.

All I'm saying is that it is doable. Might be a pain in the arse but it
is doable.
From: Daniel Barlow
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <87n0upwx6v.fsf@noetbook.telent.net>
Barry Watson <············@uab.ericsson.se> writes:

>larry wrote: 
>> Maybe programmatically creating and compiling a function at runtime
>> can be done in C, but
>> it seems like you'd have to hack it because as far as I know C does
>> not support this.
>
> [meta-hello-world.c excised]
>
> How hard was that?

and twenty five articles later:

> All I'm saying is that it is doable. Might be a pain in the arse but it
> is doable.

Moving from the position of 'How hard was that?' to 'pain in the arse'
while appearing not to have shifted position at all really marks you
as a master of Usenet debating.

(You can consider that a compliment if you like.  I wouldn't)


-dan

-- 

  http://ww.telent.net/cliki/ - Link farm for free CL-on-Unix resources 
From: Duane Rettig
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <4hekxv85z.fsf@beta.franz.com>
[Daniel,  I am answering less to your article than to this entire
thread. Your response just happens to be a good place to hang mine]

Daniel Barlow <···@telent.net> writes:

> Barry Watson <············@uab.ericsson.se> writes:
> 
> >larry wrote: 
> >> Maybe programmatically creating and compiling a function at runtime
> >> can be done in C, but
> >> it seems like you'd have to hack it because as far as I know C does
> >> not support this.
> >
> > [meta-hello-world.c excised]
> >
> > How hard was that?
> 
> and twenty five articles later:
> 
> > All I'm saying is that it is doable. Might be a pain in the arse but it
> > is doable.
> 
> Moving from the position of 'How hard was that?' to 'pain in the arse'
> while appearing not to have shifted position at all really marks you
> as a master of Usenet debating.
> 
> (You can consider that a compliment if you like.  I wouldn't)

I think most of the people arguing with Barry Watson are looking at it
from the wrong point of view.  Many are arguing against "doability" or
"ease of implementation", or assigning qualities of "hackiness" to
Barry's solution.  But you're not arguing the case in a manner consistent
with the bigger picture - with point of view of Greenspun's Tenth Rule.

I believe that Barry is right, and that his phrase 'pain in the arse'
was unfortunately said during a moment of weakness while under a lot of
pressure from many people.  I personally found his implementation simple
and intriguing.  And even given no standard library for doing this
portably, if I had been a C-only programmer, it would still have seemed
a whole lot easier to implement this technique than to learn Lisp (I'm
not saying that it would be true, but that to a C-only programmer it
would seem true and would save me from learning Lisp).

But even if the solution given by Barry weren't easy, it wouldn't be
hard to create a portable facility to do the job (most lisps have a
portable shell command-line facility, so "doable portably" isn't an
issue).

Gareth McCaugan had it right on his first point when he talked about
speed.  The speed of compilation is always a problem, whether in Lisp
or in C.  But once the compilation is done, what are the issues involving 
the speed of invocation of these "functions"?  A static function in any
language takes a few instructions, some to set up arguments, zero to two
to resolve the address of the target function, and one to make the call.
Lisp takes a similar time; the argument setup is similar, the address
resolution of the caller is usually 1, and the call may take 3 to 10
instructions (this is also more consistent with calling through function
addresses in C).  Barry's solution has a large overhead - several thousand
instructions, plus possible waiting for scheduling of the "function".

Below is a description of similar functionality to what is being discussed,
although it is not quite the same because it is not fully integrated as
might be the presumption:

Currently in Allegro CL, we provide facilities to load and execute
shared-libraries - this provides a way to dynamically define and execute
C functions.  We don't bother invoking the C compiler, because it is
indeed hard to get that interface portable, especially when there are
so many options which vary across implementations.  And on those platforms
where there is a choice bwteen C compilers, we would want to give the
users a choice on which compiler they use.

The invocation of such dynamically loaded C functions is usually as fast as
any cross-shared-library C calls - perhaps the same overhead as calling
through function addresses in C.  The calls to C from Lisp are slightly
more expensive, but since we are talking about C calling C, I am just
viewing our Lisp as a host for running C functions here.  It would be
just as easy, and probably more appropriate to the C culture, to load in
a .so/.sl/.dll/.dylib file into a C program and start calling away, than
to try to invoke each function using a fork/exec in a separate process.

Barry's solution certainly isn't fast.  But it is definitely simpler than
trying to create and load shared-libraries and invoke them.  And as for
portability, it is probably a little more portable than the shared-library
approach. It is much slower, of course, but very few are arguing that point.

Now, I have ignored environmental issues, and I don't care to discuss
the possibilities of emulating closures, first-class environments, or
CLOS in such a shell/C implementation.  Suffice it to say that it would
be painful to take Greenspun's Tenth Rule to its fullest extent.  But if
someone wanted to finish off the implementation that Barry started, I
would be happy to pit any of the CL implementations against this new one
in some timing tests ...

-- 
Duane Rettig          Franz Inc.            http://www.franz.com/ (www)
1995 University Ave Suite 275  Berkeley, CA 94704
Phone: (510) 548-3600; FAX: (510) 548-8253   ·····@Franz.COM (internet)
From: John Markus Bjorndalen
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <hvk7psi8t9.fsf@johnmnb.cs.uit.no>
Note: This is not a direct reply to Duane Rettigs article, but he brought up the 

To put a little meat on the "shared library bone", here is the
original example modified to using a shared library instead of
invoking the function though an external executable.

-------- snip ---------
/* Remember to compile with -ldl on linux */ 
#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>

typedef int(*foo_fun_t)(void);

int main()
{
    FILE      *fp;
    void      *handle; 
    foo_fun_t foo; 
    fp=fopen("source.c", "w");
    fprintf(fp, "#include <stdio.h>\nint foo(){printf(\"hello world\n\");
return 0; }");
    fclose(fp);
    system("cc -shared source.c -o /tmp/shared.so");
    handle = dlopen("/tmp/shared.so", RTLD_NOW);
    foo = dlsym(handle, "foo");
    foo();
    foo();
    dlclose(handle);
    return 0;
}
-------- snip ---------

Warning: There is a potential security problem with this one (loading
   a shared library from /tmp).

It's not difficult, and the efficiency should be equivalent to using
other shared libraries. On the other hand, error handling in
compilation, loading and execution of the generated code is nowhere
near what you get in a good common lisp environment. Debugging can be 
a bit tricky as well. 

Maybe the subject line should have been changed, because the original
article ( <····························@posting.google.com> ) ended
with:

> Maybe programmatically creating and compiling a function at runtime
> can be done in C, but it seems like you'd have to hack it because as
> far as I know C does not support this.
>
> But in lisp creating and compiling functions at runtime is natural
> and easy.

I think this one fails as a "Can't do it in C" and should rather be
written up as something you would _prefer_ to do in Lisp - especially
if you want quick and easy development of robust code. 

In general, I think we've been on thin ice when we have tried to come
up with problems that "Can't be done in C" - perhaps because of the
brash style they sometimes are presented in. Maybe that's useful to
provoke discussions, but we seem to be able to degenerate into
unproductive bickering (and worse) very easily. Especially when the
assertions get shot down (at least for some interpretation of the
problem statement).

Trying to modify the problem or the requirements to the solution
(especially to require a "lispy" solution) seems only to confirm that
we were wrong with the original statement, and that we're trying to
squirm our way out of a position where we were caught out.

If we do this as an attempt to justify why people should use (or even
take a look at or try) Lisp, I think we've chosen a weak position to
argue from.

I get the impression that people generally come to Lisp after spending
several years with other languages. Maybe we should take a closer look
at why this happens rather than trying to convince people that "we can
do things you can't do". At least for me, some of the reasons for
enjoying the discovery of Lisp after ~15 years of programming was:

a) It removed a good portion of the simple and boring coding. 

b) Less fighting with the compiler (C++ had been one of my core languages
   for nearly 10 years). 

c) Made the complex problems easier to handle. Actually, after just a few
   days of playing with Lisp I started playing with ideas that I never had 
   the energy to play with in C++ - basically because it took me hours 
   instead of days to code up things (even if I had to use the documentation
   frequently). 

   I could often attack and get a working solution to a problem while the 
   inspiration was still there. As a bonus, this could easily spawn another
   round of inspiration for a better solution. 

d) The read/eval, interpreter and integrated compiler. 
   
And more. Common Lisp simply put the fun back into programming, where
10 years of C++ as the main language had nearly killed that feeling.

I don't think it had anything to do with solving problems that I
_couldn't_ solve in C, it was more that Common Lisp could move the
line of what I _would_ solve because I had the time and energy to do
it.

Maybe the subject line should have been "Would you use this technique
in C" instead?  ;-)

-- 
	// John Markus Bj�rndalen
From: Thomas F. Burdick
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <xcvlma665md.fsf@famine.OCF.Berkeley.EDU>
John Markus Bjorndalen <·····@cs.uit.no> writes:

> I get the impression that people generally come to Lisp after spending
> several years with other languages. Maybe we should take a closer look
> at why this happens rather than trying to convince people that "we can
> do things you can't do".

 [ ... ]

> I don't think it had anything to do with solving problems that I
> _couldn't_ solve in C, it was more that Common Lisp could move the
> line of what I _would_ solve because I had the time and energy to do
> it.
> 
> Maybe the subject line should have been "Would you use this technique
> in C" instead?  ;-)

This phrasing would probably shake the silly link between these kinds
of questions and Turing-completeness.  It's not "what can you do in
Lisp", but "what are you willing to do".  And also "what can you get
away with", because I was fairly willing to go to great lengths
(including preprocessors and hacking to compiler) to get better
abstractions in C++, but no one else wants to touch your system if you
do that.

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | No to Imperialist war |                        
     ,--'    _,'   | Wage class war!       |                        
    /       /      `-----------------------'                        
   (   -.  |                               
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Gareth McCaughan
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <slrnafavth.2t9o.Gareth.McCaughan@g.local>
Barry Watson wrote:

[I said:]
> > (I think Barry Watson is probably trolling, but even if so
> > it's possible that someone might be reading this who takes
> > his points seriously. So ...)
> 
> no troll

OK.

> >     If you use the external-program approach then there's
> >     a lot of bookkeeping pain if you want the external program
> >     to stay around (e.g., so it can have persistent state, or
> >     for greater efficiency).
> 
> I don't see this. Can you explain further?

On further reflection, I recant: there's bookwork, but
not a huge amount. You need a data structure containing
a process ID and a couple of pipes; you need some
criterion for when to kill the process and discard
the data structure. It's a bit ugly, but "a lot of
bookkeeping pain" isn't fair. Probably only two orders
of magnitude worse than doing it in Lisp, not three.

> >   - It isn't true that you "get to control the namespaces". You
> >     get *less* control over the namespaces than a Lisp programmer
> >     does. Your only option is to have them entirely disjoint,
> >     and to have the programs communicate through some sort of
> >     explicit interface: pipes or shared memory or external files
> >     or something.
> 
> The control comes from the freedom to design this interface. With lisp
> it is built in so to say.

Freedom isn't always good. I want the freedom to decide whether
my variables get shared, and with what. I don't really want the
freedom of deciding whether to do it via the joy of SysV shared
memory, or via a bunch of external files, or via some dynamic
linking mechanism, or whatever. I want to decide the behaviour,
not the implementation. Sometimes the freedom to decide the
implementation is necessary because there's no single mechanism
that can solve all the problems adequately. In this case, however,
the choice is between a single mechanism that solves all the
problems (with CL) and a wide choice of horrible implementations
(with C).

If you want to build a function in CL that can't refer
to global variables, it's easy to write a macro called
WITH-RENAMED-SYMBOLS or something that has just that
effect. Strictly, that's not quite true, because your
function could use SYMBOL-FUNCTION on a symbol someone
else passed it, or something like that, but then Erik
Naggum's famous aphorism becomes relevant:

  | ... it's just that in C++ and the like, you don't
  | trust _anybody_, and in CLOS you basically trust everybody.
  | the practical result is that thieves and bums use C++
  | and nice people use CLOS.

(If you're actually worried about security, then running
the function in a separate process may have advantages.
It certainly also opens up several exciting new possible
exploits to worry about.)

> >   - It's much more awkward to create little functions on the fly
> >     and then pass them around. The exact way in which this hurts
> >     varies according to your implementation strategy; all of them
> >     are hugely worse than for Lisp, where you just say "lambda"
> >     and you're done.
> 
> For the human programmer yes but not for a machine generated C code,
> i.e., human problems not language problems.

In CL, a dynamically created function looks exactly like
any other function. In C, it can't, because the only state
a function can carry around is in its static variables,
and you only get one set per function, not one per function
invocation. So instead of saying

    (do-something (funcall my-function some-argument))

you need to say

    do_something(call_external_function(my_function, some_argument))

Except that it's worse than that, because C is statically
typed and anyway you'll need to do some argument marshalling
and result unmarshalling. So either you encode the type
information into the name of your "function"-calling function

    do_something(call_external_function_i_s(my_function, some_argument))

or else you use functions that do it explicitly, which is
more flexible and doesn't require you to have a hundred
versions of call_external_function_x_y but makes the code
more verbose:

    do_something(
      unmarshal("i",
        call_external_function(my_function, marshal("s", some_argument))))

Except that this latter approach is worse than that, because C
doesn't have automatic memory management and |marshal| and
|unmarshal| will be having to allocate memory. So you need to
say something more like

    {
      MarshalledData * a = marshal("s", some_argument);
      MarshalledData * b = call_external_function(my_function, a);
      do_something(unmarshal("i", b));
      discard_marshalled(a);
      discard_marshalled(b);
    }

Except that it's worse than that, because C is statically typed
and so you'll surely get a compiler warning on the call to |do_something|
unless you replace it with

      do_something((int)unmarshal("i", b));

Well, OK, so the version with 100 different |call_external_function|
variants is better, at least in terms of code size. Except that
then each of those needs to be defined separately. Ow.

In C++ a lot of this pain goes away, by the way; you can
overload operator() to make your magic pseudo-function look
just like a real one, and you can play template games to
avoid needing to write the same code 100 times. On the
other hand, C++ introduces some exquisite varieties of
pain that are all its own.

> >   - It relies on the ability to create arbitrary files and run
> >     arbitrary programs. This can be a major security risk. That's
> >     why server programs often run with insufficient privileges to
> >     do what you described.
> 
> Nah, we can get round that. This is an OS issue. A modern well designed
> OS would remove this problem.

Perhaps it would. Unfortunately no one has one.

> > If you seriously think that the C way is just as good as the
> > Lisp way, then either (1) you need to find out more about the
> > Lisp way, or (2) you've been tricked by years of C programming
> > into thinking that the C way is painless, or (3) I'm missing
> > something really big.
> > 
> > I don't think it's #3.
> 
> All I'm saying is that it is doable. Might be a pain in the arse but it
> is doable.

Certainly, you can do something that can be described as "creating
functions dynamically" in C. You can also do something that can
be described as "object-oriented programming" in C; you can do
something that can be described as "functional programming" in C;
and so on. The term "pain in the arse" applies pretty well to many
of these things. But there are very few things that you can do with
any language and simply can't do at all in C.

Or assembler.

-- 
Gareth McCaughan  ················@pobox.com
.sig under construc
From: Raymond Wiker
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <864rgy53jw.fsf@raw.grenland.fast.no>
Barry Watson <············@uab.ericsson.se> writes:

> Coby Beck wrote:
> > You did not
> > compile a function at runtime, 
> 
> yes I did
> 
> >you created an executable and ran it.  
> 
> I compiled a function then ran it.

        No, you didn't. You created an executable, and ran that. If
you want to do something that _at all_ resembles creating a function
and calling it, you'll have to allow for parameter and value
passing. In doing so, you'll probably end up re-implementing much of
the Unix shells (or CORBA :-)

> > The dynamically created function can see the special variables and
> > global data structures of the program that wrote it, it can be
> > applied to arguments and its return value used, it can side effect
> > the creating program, it does not rely on disc access and system
> > calls and pipes or files to exchange information.
> 
> Doing it in C is much cleaner than in lisp, I get to control the
> namespaces plus I get the advantage of compiled code. I think you're
> biased.

        _What_ namespaces? C doesn't have any namespaces.

> > (I answered assuming you are just being naive, not trolling)
> 
> You're funny.

        Coby's phrase can be reused, I think:

        "I answered assuming you are just being naive, not trolling."

-- 
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: Barry Watson
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <3CEE0750.4BEABDC1@uab.ericsson.se>
Raymond Wiker wrote:
> 
> Barry Watson <············@uab.ericsson.se> writes:
> 
> > Coby Beck wrote:
> > > You did not
> > > compile a function at runtime,
> >
> > yes I did
> >
> > >you created an executable and ran it.
> >
> > I compiled a function then ran it.
> 
>         No, you didn't. You created an executable,

using a compiler, hence compiling. The thing I compiled was a function.
I then ran the function. Not trying to be funny but I think you're
wrong. 

> and ran that. If
> you want to do something that _at all_ resembles creating a function
> and calling it, you'll have to allow for parameter and value
> passing. In doing so, you'll probably end up re-implementing much of
> the Unix shells (or CORBA :-)

or use argc and argv. 


> > Doing it in C is much cleaner than in lisp, I get to control the
> > namespaces plus I get the advantage of compiled code. I think you're
> > biased.
> 
>         _What_ namespaces? C doesn't have any namespaces.

I create the namespaces when I compile and run the code. 
 
> > > (I answered assuming you are just being naive, not trolling)
> >
> > You're funny.
> 
>         Coby's phrase can be reused, I think:
> 
>         "I answered assuming you are just being naive, not trolling."

Treated with the contempt it deserves.
From: Dave Pearson
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <slrnaes3qm.csj.davep.news@hagbard.davep.org>
* Barry Watson <············@uab.ericsson.se>:

> Raymond Wiker wrote:
>
> >         No, you didn't. You created an executable,
> 
> using a compiler, hence compiling. The thing I compiled was a function. I
> then ran the function. Not trying to be funny but I think you're wrong.

Isn't the real question here "can you do that, but without calling that
function 'main', having it take arguments other than `argv' and `argc' and
have it return something other than an integer"?

-- 
Dave Pearson:                   |     lbdb.el - LBDB interface.
http://www.davep.org/           |  sawfish.el - Sawfish mode.
Emacs:                          |  uptimes.el - Record emacs uptimes.
http://www.davep.org/emacs/     | quickurl.el - Recall lists of URLs.
From: Barry Margolin
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <mztH8.5$006.637@paloalto-snr2.gtei.net>
In article <·························@hagbard.davep.org>,
Dave Pearson  <·····@davep.org> wrote:
>* Barry Watson <············@uab.ericsson.se>:
>
>> Raymond Wiker wrote:
>>
>> >         No, you didn't. You created an executable,
>> 
>> using a compiler, hence compiling. The thing I compiled was a function. I
>> then ran the function. Not trying to be funny but I think you're wrong.
>
>Isn't the real question here "can you do that, but without calling that
>function 'main', having it take arguments other than `argv' and `argc' and
>have it return something other than an integer"?

Yes.  Most systems support DLLs, so you can compile a source file
containing an arbitrary function, turn it into a DLL, and then use an API
to load it into memory.

This is all very OS-dependent, but so was the "cc" example, so it's not
much worse than that one.  On Unix you would use dlopen() and dlsym() to
load it into memory and link to it.

-- 
Barry Margolin, ······@genuity.net
Genuity, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Chris Double
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <u7klsftbt.fsf@double.co.nz>
Barry Margolin <······@genuity.net> writes:

> Yes.  Most systems support DLLs, so you can compile a source file
> containing an arbitrary function, turn it into a DLL, and then use an API
> to load it into memory.

The Goo (Generic Object Orientator) language does this on Linux I
believe. It dynamically generates C code, compiles it and loads the
shared library as required. See: http://www.googoogaga.org

Goo is a Lisp like language btw.

Chris.
-- 
http://radio.weblogs.com/0102385
From: Immanuel Litzroth
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <m2g00hyhqi.fsf@enfocus.be>
>>>>> "Barry" == Barry Watson <············@uab.ericsson.se> writes:

    Barry> Treated with the contempt it deserves.

I found your solution very elegant and am now convinced that with this
brilliant technologcal innovation you have singlehandedly dealt a
devastating blow to the lisp community. 
Have you considered creating dynamic link libraries and loading them 
dynamically?
Immanuel
From: Barry Watson
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <3CEE1547.C6C19F93@uab.ericsson.se>
Immanuel Litzroth wrote:
> 
> >>>>> "Barry" == Barry Watson <············@uab.ericsson.se> writes:
> 
>     Barry> Treated with the contempt it deserves.
> 
> I found your solution very elegant and am now convinced that with this
> brilliant technologcal innovation you have singlehandedly dealt a
> devastating blow to the lisp community.
> Have you considered creating dynamic link libraries and loading them
> dynamically?
> Immanuel

Never set out to deal a blow. I think lisp is very interesting. I'm not
saying C is better than lisp. I have no strong feelings either way.
From: Christophe Rhodes
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <sqvg9d3ktj.fsf@lambda.jcn.srcf.net>
One last try.  Please read this as though it contained information new
to you, even if you're sure that it doesn't.

Barry Watson <············@uab.ericsson.se> writes:

> Raymond Wiker wrote:
> > 
> > Barry Watson <············@uab.ericsson.se> writes:
> > 
> > > Coby Beck wrote:
> > > > You did not
> > > > compile a function at runtime,
> > >
> > > yes I did
> > >
> > > >you created an executable and ran it.
> > >
> > > I compiled a function then ran it.
> > 
> >         No, you didn't. You created an executable,
> 
> using a compiler, hence compiling. The thing I compiled was a function.
> I then ran the function. Not trying to be funny but I think you're
> wrong. 

You invoked, using a mechanism that is not specified in ANSI C, an
external program called "cc". This in turn compiled a C source file
into an object file, invoked a linker to link it with relevant
libraries and turned it into an executable, which you then ran using a
system call.

As a first point, think about what would have been different if
  * your C compiler wasn't in your $PATH;
  * your C compiler wasn't called "cc";
  * you were not running on a Unixoid system.

> > and ran that. If
> > you want to do something that _at all_ resembles creating a function
> > and calling it, you'll have to allow for parameter and value
> > passing. In doing so, you'll probably end up re-implementing much of
> > the Unix shells (or CORBA :-)
> 
> or use argc and argv. 

Please stop and think just for a moment.

How are you going to pass, say, a structure that you have in your
original program to your new program? That is, what if you have:

int main() {
  ucontext_t current_context;

  /* Let's dynamically create something to handle signals and compile
     it, using the Watson mechanism ("cc" to produce an ./a.out
     executable) */
  /* ... */
  /* Uhoh, we've caught an exception -- better call our handler */
  current_context = get_current_context(signal);
  system("./a.out <what goes here?>");
}

I hope you can see that this is not the same as a normal function
call. I grant that you _can_ do it, assuming that you know where your
C compiler lives, by creating a shared object file and dynamically
linking it in by hand, but I hope you also see that this way lies
pain.

Now, consider that the Lisp environment defines a compiler and linker
(the Lisp function COMPILE) that does all of this for you in a
standardized way, with none of the above worries; this allows dynamic
code creation in a way that C does not.

> > > Doing it in C is much cleaner than in lisp, I get to control the
> > > namespaces plus I get the advantage of compiled code. I think you're
> > > biased.
> > 
> >         _What_ namespaces? C doesn't have any namespaces.
> 
> I create the namespaces when I compile and run the code. 

Yes, but you don't actually have any control over the namespaces --
all you can do is achieve complete separation (i.e. no variable in
your dynamically generated "function" can be the same as that in your
main program).  I hope you also realize that the "advantage of
compiled code" that you cite is also available to Lisp, where most of
the implementations compile to native code --  an interactive
environment does not imply an interpreted environment.

Christophe
-- 
Jesus College, Cambridge, CB5 8BL                           +44 1223 510 299
http://www-jcsu.jesus.cam.ac.uk/~csr21/                  (defun pling-dollar 
(str schar arg) (first (last +))) (make-dispatch-macro-character #\! t)
(set-dispatch-macro-character #\! #\$ #'pling-dollar)
From: Barry Watson
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <3CEE15DF.EE8C7694@uab.ericsson.se>
Christophe Rhodes wrote:
> 
> One last try.  Please read this as though it contained information new
> to you, even if you're sure that it doesn't.

I don't think you're thinking "big " enough. Just because something is
standardised in a language doesn't mean it cannot be done in another
language. I'm not criticising the way it is done in Lisp. I'm just
pointing out it is doable in C. That's all. Relaxez vous!
From: Immanuel Litzroth
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <m2g00hx0ho.fsf@enfocus.be>
>>>>> "Barry" == Barry Watson <············@uab.ericsson.se> writes:

    Barry> Christophe Rhodes wrote:
    >>  One last try.  Please read this as though it contained
    >> information new to you, even if you're sure that it doesn't.

    Barry> I don't think you're thinking "big " enough. Just because
    Barry> something is standardised in a language doesn't mean it
    Barry> cannot be done in another language. I'm not criticising the
    Barry> way it is done in Lisp. I'm just pointing out it is doable
    Barry> in C. That's all. Relaxez vous!

Actually you don't even need a computer to this stuff. You definition
of doable seems to be too close to turing computability to be of any
practical value. 
Your solution is OS dependent (and I fail to see that it would work on
non-multitasking systems), it requires you to reinvent parameter
passing, return values, error handling for each "dynamically compiled
function". I was also thinking about recursive calls and mutually
recursive calls, but I had to lie down when I imagined using ps as
debugger to get a stack trace.
Immanuel
From: Barry Watson
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <3CEE3300.CD3DC2E1@uab.ericsson.se>
Immanuel Litzroth wrote:
> 
> >>>>> "Barry" == Barry Watson <············@uab.ericsson.se> writes:
> 
>     Barry> Christophe Rhodes wrote:
>     >>  One last try.  Please read this as though it contained
>     >> information new to you, even if you're sure that it doesn't.
> 
>     Barry> I don't think you're thinking "big " enough. Just because
>     Barry> something is standardised in a language doesn't mean it
>     Barry> cannot be done in another language. I'm not criticising the
>     Barry> way it is done in Lisp. I'm just pointing out it is doable
>     Barry> in C. That's all. Relaxez vous!
> 
> Actually you don't even need a computer to this stuff. You definition
> of doable seems to be too close to turing computability to be of any
> practical value.

Thank you for showing me the folly of my ways Immanuel. Look, I was just
showing it was doable (=could be done) that's all. I never argued
anything else. No need for anyone to get het up.
From: Erik Naggum
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <3231229123051721@naggum.net>
* Barry Watson <············@uab.ericsson.se>
| I don't think you're thinking "big " enough. Just because something is
| standardised in a language doesn't mean it cannot be done in another
| language. I'm not criticising the way it is done in Lisp. I'm just
| pointing out it is doable in C. That's all. Relaxez vous!

  I think you have shown us something interesting.  You think Common Lisp
  only offers what you can do in C, so naturally you can do in C what you
  think Common Lisp offers.  This is not quite the same as doing in C what
  Common Lisp offers to a Common Lisp programmer.
-- 
  In a fight against something, the fight has value, victory has none.
  In a fight for something, the fight is a loss, victory merely relief.

  70 percent of American adults do not understand the scientific process.
From: Raymond Wiker
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <86znyp50hu.fsf@raw.grenland.fast.no>
Barry Watson <············@uab.ericsson.se> writes:

> Raymond Wiker wrote:
> > 
> > Barry Watson <············@uab.ericsson.se> writes:
> > 
> > > Coby Beck wrote:
> > > > You did not
> > > > compile a function at runtime,
> > >
> > > yes I did
> > >
> > > >you created an executable and ran it.
> > >
> > > I compiled a function then ran it.
> > 
> >         No, you didn't. You created an executable,
> 
> using a compiler, hence compiling. The thing I compiled was a function.
> I then ran the function. Not trying to be funny but I think you're
> wrong. 

        The thing you compiled was a source file. This file contained
a single function. There is a difference. The C compiler
created an object file, which the linker combined with system
libraries and object files to create a stand-alone (more or less)
executable. 

> > and ran that. If
> > you want to do something that _at all_ resembles creating a function
> > and calling it, you'll have to allow for parameter and value
> > passing. In doing so, you'll probably end up re-implementing much of
> > the Unix shells (or CORBA :-)
> 
> or use argc and argv. 

        argc and argv solves (more or less) the "parameter"
problem. The (return) value problem remains. The exit code from the
program is an integer with a limited range. You could print the
result(s) on a file descriptor, but then you would have to set up the
pipes, and do some sort of parsing of the text written by the
program. Keep going on this, and you'll end up with re-implementing
one of the Unix shells.

> > > Doing it in C is much cleaner than in lisp, I get to control the
> > > namespaces plus I get the advantage of compiled code. I think you're
> > > biased.
> > 
> >         _What_ namespaces? C doesn't have any namespaces.
> 
> I create the namespaces when I compile and run the code. 

        No, you don't - that's not what namespace means. 

        You create a new executable that doesn't share
anything with it's creator. When run, the executable is unable to
interact in any way with its parent. If you want to create anything
with close to the functionality of a lisp system, you'd have to
provide some sort of communication/control framework - like CORBA. At
that point, it's silly to talk about a C program.

-- 
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: Barry Watson
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <3CEE11B6.BFFFE0E0@uab.ericsson.se>
Raymond Wiker wrote:


>         The thing you compiled was a source file. This file contained
> a single function. There is a difference. The C compiler
> created an object file, which the linker combined with system
> libraries and object files to create a stand-alone (more or less)
> executable.

And I never claimed anything other than that. 


>         argc and argv solves (more or less) the "parameter"
> problem. The (return) value problem remains. The exit code from the
> program is an integer with a limited range. You could print the
> result(s) on a file descriptor, but then you would have to set up the
> pipes, and do some sort of parsing of the text written by the
> program. Keep going on this, and you'll end up with re-implementing
> one of the Unix shells.

The return value is more complex, granted but as you point out, doable.
The subject line contains the argument orignally posed. I intended to
show it could be done in C.


>         No, you don't - that's not what namespace means.

Think about it, I do create namespaces.
 
>         You create a new executable that doesn't share
> anything with it's creator.

I create the state in the new executable so I can copy across pretty
much what I want.

> When run, the executable is unable to
> interact in any way with its parent.

no. You pointed out yourself interaction was possible.

> If you want to create anything
> with close to the functionality of a lisp system, you'd have to
> provide some sort of communication/control framework - like CORBA. At
> that point, it's silly to talk about a C program.

Even if we go that way (just one of many) we still have to admit it is
doable in C.
From: Raymond Wiker
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <86vg9d4y0l.fsf@raw.grenland.fast.no>
Barry Watson <············@uab.ericsson.se> writes:

> Raymond Wiker wrote:
> >         You create a new executable that doesn't share
> > anything with it's creator.
> 
> I create the state in the new executable so I can copy across pretty
> much what I want.

        That's only half of what is implied by "sharing".

> > When run, the executable is unable to
> > interact in any way with its parent.
> 
> no. You pointed out yourself interaction was possible.

        Not without adding massive amounts of support code.

> 
> > If you want to create anything
> > with close to the functionality of a lisp system, you'd have to
> > provide some sort of communication/control framework - like CORBA. At
> > that point, it's silly to talk about a C program.
> 
> Even if we go that way (just one of many) we still have to admit it is
> doable in C.

        In that case, one of the better solutions would be to have a
Lisp system (partially) implemented in C...

-- 
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: Tim Bradshaw
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <ey3r8k1y9mv.fsf@cley.com>
I think I'm going to follow up to this because it's so often asked in
such a way that it's easy to answer in this really annoying way.

* Barry Watson wrote:

> Even if we go that way (just one of many) we still have to admit it is
> doable in C.

Let's phrase the question better, then.

Here is the (Lisp) source of a function which performs a simple tree
search. 

    (defvar *search-source*
      '(lambda (o get-children get-child next-children test)
         (block done
           (labels ((search (oo)
                      (when (funcall test oo)
                        (return-from done oo))
                      (loop for children = (funcall get-children oo) 
                            then (funcall next-children children)
                            for child = (and children
                                             (funcall get-child children))
                            while children
                            do
                            (search child)
                            finally (return false))))
             (search o)))))

This is written somewhat obscurely, but the intention is not to be
willfully obscure but to achieve the following goals:

1. The function is entirely data-structure agnostic: you pass it some
   opaque object O, and four functions:

     * GET-CHILDREN returns the children of an object, or false if
       there are none.  The type of the children is opaque, but it is
       not false.
     * GET-CHILD gets the first child from whatever GET-CHILDREN
       returns.  The type of a child is opaque.
     * NEXT-CHILDREN moves the `current child' cursor along whatever
       GET-CHILDREN returned, and returns either a set of children or
       false, if there are no more.  Again, you are given that no set
       of children is false.
     * TEST takes an object and returns true if it passes the test,
       otherwise false.  This terminates the search.

2. It doesn't internally need lists or anything like that (this is why
   it has this GET-CHILDREN / GET-CHILD / NEXT-CHILDREN thing - I
   didn't want to do the obvious `return a list of children' thing
   since that would unfairly burden C.

3. I think it should be fairly easy to write such a function in C or
   most other recent languages.  It is OK to use an auxiliary
   function, which I think you need in C (bonus points will be given
   for not polluting the namespace too much).

The task is then: given this function's source code - represented as a
string if you like - compile this function, and then call it.  You do
not control the data or functions it is called with (not even the
types), and you are given the data when the program which must do the
compiling runs, and not later (so, if you compile it into another
executable, then invoke that executable, you must arrange to pass both
the data into the executable, and get the result back) When you call
it, it must work, in particular:

    You have no control over the data type of O it is called with;

    You have no control over the functions it is passed;

    If it succeeds, the object it returns must be *identical* to the
    element in the tree it was passed.  If it's a number it must be
    the same number, if it's a pointer it must be a pointer to the
    same thing, and so on.

In particular, in Lisp terms, the following test function, when passed
the compiled function, should return T, NIL, T, NIL. (Ignore the
debugging output).

    (defun test-searcher (searcher)
      (let* ((good '(1 2 3))
             (tree-1
              `(1 
                (1 2 3)
                (2 3 4)
                (4 (5 6 (7 8 9 (1 2 3) ,good) (1 2 3) 10))
                (1 2 3)))
             (tree-2 (copy-tree tree-1)))
        (flet ((test (tree)
                 (format *debug-io* "~&Testing ~S~%" tree)
                 (eql (funcall searcher 
                               tree
                               #'(lambda (x)
                                   (let ((c (and (consp x)
                                                 (cdr x))))
                                     (format *debug-io* "~& Childing ~S -> ~:[()~;~:*~S~]~%"
                                             x c)
                                     c))
                               #'car
                               #'cdr
                               #'(lambda (x)
                                   (let ((r (eql x good)))
                                     (format *debug-io* "~& Testing ~S: ~:[no~;yes~]~%"
                                             x r)
                                     r)))
                      good)))
          (values (test tree-1) (test tree-2) 
                  (test good) (test '(1 2 3))))))

Obviously, in a language without first-class functions you'd have to
define this test-harness somewhat differently: that's OK.

The way you do this in CL is:

    (test-searcher (compile nil *search-source*))

OK, that's the challenge.  I hope I've specified it tightly enough to
be meaningful and to avoid the normal silly answers.

If anyone wants to submit answers could they please provide complete
source source, and specify:

* Language used with an indication of any detailed requirements (ANSI
  C rather than K&R say, or Perl 5 rather than 4).  If possible give
  pointers to an implementation (need not be free).

* Any libraries or interfaces required on top of the language,
  together with any details of them, and preferably implementation
  pointers as before (need not be free).

* Any environmental requirements: for instance `a C compiler with the
  standard unix cc calling conventions'.

* Instructions for building and running the source.

Finally I have not tried to construct this question in such a way as
to be deliberately hard.  The reason for the slightly obscure
interface to the function is that I want to *reduce* the requirements
of specific data types in the language.

I fully expect that languages other than Lisp can solve this quite
easily - in particular I'm fairly sure that Perl and Python will be
able to provide quite concise solutions, and Java may well do as well.

What I hope the problem does expose is what people actually want to be
able to do when they say `compile source into code and then run it on
the fly' - something like this problem is much more like what people
trying to, say, do genetic programming, want to be able to do.

Thanks

--tim
From: Tim Bradshaw
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <ey3lma9y8lv.fsf@cley.com>
* I wrote:

>     (defun test-searcher (searcher)
>       (let* ((good '(1 2 3))
>              (tree-1
>               `(1 
>                 (1 2 3)
>                 (2 3 4)
>                 (4 (5 6 (7 8 9 (1 2 3) ,good) (1 2 3) 10))
>                 (1 2 3)))
>              (tree-2 (copy-tree tree-1)))
>          ...

I realise that I'm not 100% sure that backquote is not allowed to copy
GOOD, or that the other constants may be coalesced with it (in fact I
am sure that other constants may be coalesced).  Fool.

Please use this definition instead

    (defun test-searcher (searcher)
      (let* ((good (list 1 2 3))
             (tree-1
              (cons 1
                    (list
                     '(1 2 3)
                     '(2 3 4)
                     (cons 4
                           (cons 5
                                 (list
                                  6
                                  (cons 7
                                        (list 8 9 '(1 2 3) good))
                                  '(1 2 3)
                                  10)))
                     '(1 2 3))))
             (tree-2 (copy-tree tree-1)))
        (flet ((test (tree)
                 (format *debug-io* "~&Testing ~S~%" tree)
                 (eql (funcall searcher 
                               tree
                               #'(lambda (x)
                                   (let ((c (and (consp x)
                                                 (cdr x))))
                                     (format *debug-io* "~& Childing ~S -> ~:[()~;~:*~S~]~%"
                                             x c)
                                     c))
                               #'car
                               #'cdr
                               #'(lambda (x)
                                   (let ((r (eql x good)))
                                     (format *debug-io* "~& Testing ~S: ~:[no~;yes~]~%"
                                             x r)
                                     r)))
                      good)))
          (values (test tree-1) (test tree-2) 
                  (test good) (test '(1 2 3))))))


--tim
From: Coby Beck
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <D3sH8.131485$xS2.10391815@news1.calgary.shaw.ca>
"Barry Watson" <············@uab.ericsson.se> wrote in message
······················@uab.ericsson.se...
> Coby Beck wrote:
> > "Barry Watson" <············@uab.ericsson.se> wrote in message
> > dynamically created function can see the special variables and global
data
> > structures of the program that wrote it, it can be applied to arguments
and
> > its return value used, it can side effect the creating program, it does
not
> > rely on disc access and system calls and pipes or files to exchange
> > information.
>
> Doing it in C is much cleaner than in lisp, I get to control the
> namespaces plus I get the advantage of compiled code. I think you're
> biased.
>
> > (I answered assuming you are just being naive, not trolling)
>
> You're funny.

Right-o.  Troll it is...

--
Coby Beck
(remove #\Space "coby 101 @ bigpond . com")
From: Kaz Kylheku
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <slrnaeq79r.v2v.kaz@localhost.localdomain>
On Thu, 23 May 2002 10:26:54 +0200, Barry Watson
<············@uab.ericsson.se> wrote:
>
>
>larry wrote:
>>
>> Maybe programmatically creating and compiling a function at runtime
>> can be done in C, but
>> it seems like you'd have to hack it because as far as I know C does
>> not support this.
>
>#include <stdlib.h>
>#includ <stdio.h>
>
>int main()
>{
>	FILE *fp;
>	fp=fopen("source.c", "w");
>	fprintf(fp, "#include <stdio.h>\nint main(){printf(\"hello world\");
>return 0}");
>	fclose(fp);
>	system("cc source.c");
>	system("./a.out");
>	return 0;
>}
>
>
>How hard was that?

There is no requirement in the C language that system("cc source.c") does what
is intended above.  Moreover, you have no useful facilities in the C language
to actually construct and manipulate C programs as objects.  Lastly, running a
child program isn't the same thing as calling a function in the context of the
current program.

For thirty years, people have written programs to filter or generate C code.

This area of human activity, by and large, has accomplished next to nothing.
From: Barry Watson
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <3CEDF5CE.E4FE435F@uab.ericsson.se>
Kaz Kylheku wrote:

> There is no requirement in the C language that system("cc source.c") does what
> is intended above. 

A non argument, I can change the code  to use whatever compiler I want.

> Moreover, you have no useful facilities in the C language
> to actually construct and manipulate C programs as objects. 

I am not limited by the internal reperesentation of code. I have
complete flexibility. 

> Lastly, running a
> child program isn't the same thing as calling a function in the context of the
> current program.

Exactly. I get to control all the environments in a way you as a Lisp
programmer (I think) cannot do without writing your own eval. I have the
possability to hide data and code in a way enforced by the OS. If I want
to can set up pipes, sockets, shared memory, whatever. I am not even
forced to run the child on the same computer/network. 

> For thirty years, people have written programs to filter or generate C code.
> 
> This area of human activity, by and large, has accomplished next to nothing.

What are you trying to get at?

Some (not I say some) of you lispers need to see the bigger picture.
There is very little between what I did and using eval & apply. Lisp is
great, I've used it for years in many forms (lisp/scheme/logo) but it
doesn't have a monopoly on things.
From: Espen Wiborg
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <usn4hpzju.fsf@empolis.no>
Barry Watson <············@uab.ericsson.se> writes:
> Kaz Kylheku wrote:
> > There is no requirement in the C language that system("cc
> > source.c") does what is intended above.
> A non argument, I can change the code to use whatever compiler I
> want.

But (as other people have pointed out) you lose horribly on machines
without compilers (which are not as rare as you may think - anything
running Microsoft Windows will most likely fall into this category, as
will many machines running Solaris).

My point here is that your technique is certainly workable (although
with more emphasis on the 'work' than the 'able' - to do argument
passing or return values, for instance, you'd have to come up with
some sort of external data representation), but only on *some*
implementations of the C language - nowhere in the C standard is it
guaranteed that the compiler will be available at runtime (or even
that system(3) will work the way you expect it to - meditate on
embedded systems and you may achieve enlightenment).

-- 
Espen Wiborg <·······@empolis.no>
Do not meddle in the affairs of gurus,
for they can make your life miserable by doing nothing.
From: Barry Watson
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <3CEE3169.6F3A0CC@uab.ericsson.se>
Espen Wiborg wrote:
> 

> My point here is that your technique is certainly workable 

This is all I was really trying to show.
From: Espen Wiborg
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <uk7ptpui5.fsf@empolis.no>
Barry Watson <············@uab.ericsson.se> writes:
> Espen Wiborg wrote:
> > My point here is that your technique is certainly workable 
> This is all I was really trying to show.

You didn't read the rest of my article, did you?  I went on to say
that it is not workable *within the C standard*.

-- 
Espen Wiborg <·······@empolis.no>
"Usenet is a co-operative venture, backed by nasty people -
	 follow the standards."  -- Chris Rovers
From: Geoff Summerhayes
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <j0sH8.40864$Ka.3170669@news2.calgary.shaw.ca>
"Barry Watson" <············@uab.ericsson.se> wrote in message
······················@uab.ericsson.se...
>
>
> Kaz Kylheku wrote:
>
> > There is no requirement in the C language that system("cc source.c") does
what
> > is intended above.
>
> A non argument, I can change the code  to use whatever compiler I want.
>

Try this one, your program is too long. By your arguments,
the OS and the tools available are open game, compliancy
and portability are not issues so,

#include <stdio.h>

int main()
{
    system("lisp");
    return 0;
}

is completely valid. Now you do have a non-compliant C program
that does everything common lisp can do.

As a side effect, you have also proved that compiled languages
have no real speed advantage over interpreted ones. :-)

--
Geoff
From: Barry Margolin
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <_GtH8.6$006.676@paloalto-snr2.gtei.net>
In article <·················@uab.ericsson.se>,
Barry Watson  <············@uab.ericsson.se> wrote:
>Exactly. I get to control all the environments in a way you as a Lisp
>programmer (I think) cannot do without writing your own eval. I have the
>possability to hide data and code in a way enforced by the OS. If I want
>to can set up pipes, sockets, shared memory, whatever. I am not even
>forced to run the child on the same computer/network. 

Well, there's certainly nothing stopping a Lisp program from using the
equivalent of system() to spawn a separate Lisp process, running some other
functions in that process, and communicating to it via those methods.

I think the problem with this debate is the OP's choice of words in the
Subject line.  You saw "can't" and interpreted it as an absolute.  Since
most programming languages are Turing-equivalent, there's virtually nothing
that can be done in one language that can't be done in another.

The difference is really in how easy or practical it is.  Lisp makes it
trivial to create and execute new code on the fly, in a totally portable
manner.  C makes it very difficult; not impossible, but hard enough that
such a technique will almost never be used.

-- 
Barry Margolin, ······@genuity.net
Genuity, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Kaz Kylheku
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <slrnaet1c7.16d.kaz@localhost.localdomain>
On Fri, 24 May 2002 16:15:54 GMT, Barry Margolin <······@genuity.net> wrote:
>I think the problem with this debate is the OP's choice of words in the
>Subject line.  You saw "can't" and interpreted it as an absolute.  Since
>most programming languages are Turing-equivalent, there's virtually nothing
>that can be done in one language that can't be done in another.
>
>The difference is really in how easy or practical it is.  Lisp makes it
>trivial to create and execute new code on the fly, in a totally portable
>manner.  C makes it very difficult; not impossible, but hard enough that
>such a technique will almost never be used.

And also hard enough that when it's used, it will turn into a major software
project, with its own bugs, quirks and peculiar limitations. It will also be
incompatible with everyone else's such project. The external representations
produced by this software will invariable have their own unique grammar;
if there arises a need for interoperability, even more individuals will be
sucked into wasting their time reverse engineering the custom language and
writing their own parsers.

One advantage in Lisp is that its printed notation is universal and standard.

Syntaxes are toxic waste: use as little as possible, and recycle like mad!

If in doing your work you create a new read syntax, you have released a toxic
byproduct into the world.
From: Paolo Amoroso
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <mZ3vPH3I+XAV7sUoimW9pQTTkwWY@4ax.com>
On Fri, 24 May 2002 10:11:58 +0200, Barry Watson
<············@uab.ericsson.se> wrote:

> Some (not I say some) of you lispers need to see the bigger picture.
> There is very little between what I did and using eval & apply. Lisp is
> great, I've used it for years in many forms (lisp/scheme/logo) but it
> doesn't have a monopoly on things.

Given that the compilers of most languages, including Lisp, generate
machine code, everything the languages do can be also done in Assembly, and
possibly also in C. So what?

I guess I'm missing your bigger picture. But your reference to a monopoly
seems to suggest that you may have some some sort of personal problem or
grudge with Lisp and/or its community (note the usual pattern "Lisp is
great... but...").

Just out of curiosity: are you aware of Greenspun's Tenth Rule?


Paolo
-- 
EncyCMUCLopedia * Extensive collection of CMU Common Lisp documentation
http://www.paoloamoroso.it/ency/README
[http://cvs2.cons.org:8000/cmucl/doc/EncyCMUCLopedia/]
From: ozan s yigit
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <vi4wutptufw.fsf@blue.cs.yorku.ca>
Paolo Amoroso [to Barry Watson]:

> Just out of curiosity: are you aware of Greenspun's Tenth Rule?

is that the one about how anyone who teaches and practices in a field
still in its infancy has an informally specified, ad-hoc and bug-ridden
collection of rules that often amuse but not always enlighten? :) :)

oz
-- 
practically no other tree in the forest looked so tree-like as this tree.
	-- terry pratchett
 
From: Erik Naggum
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <3231228399661732@naggum.net>
* Barry Watson
| How hard was that?

  Well, if you want to do something that might be similar in functionality,
  write for and compile it into a shared, relocatablec object, dynamically
  load it into the running image and use it there lika a regular function.
  People do this with so-called "plugins".  This is not _that_ much harder
  than what Common Lisp does so naturally we do not even think about it,
  but it indicates what kinds of things are done _for_ you in Common Lisp.
  Faking things along the path of least resistance with an executable is
  not the way to convince people that you can deal with the conplexity of
  the issue at hand.  Making this work on a single system is not that hard,
  but making it an intrinsic feature of an environment is something else.
  Could you show us what that would look like in C?  Has it been done?
-- 
  In a fight against something, the fight has value, victory has none.
  In a fight for something, the fight is a loss, victory merely relief.

  70 percent of American adults do not understand the scientific process.
From: Joe Marshall
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <nkNH8.198$YV2.306851@typhoon.ne.ipsvc.net>
"Barry Watson" <············@uab.ericsson.se> wrote in message ······················@uab.ericsson.se...
>
>
> larry wrote:
> >
> > Maybe programmatically creating and compiling a function at runtime
> > can be done in C, but
> > it seems like you'd have to hack it because as far as I know C does
> > not support this.
>
> #include <stdlib.h>
> #includ <stdio.h>
>
> int main()
> {
> FILE *fp;
> fp=fopen("source.c", "w");
> fprintf(fp, "#include <stdio.h>\nint main(){printf(\"hello world\");
> return 0}");
> fclose(fp);
> system("cc source.c");
> system("./a.out");
> return 0;
> }
>
>
> How hard was that?

Cool, but I tried it on a pair of mutually recursive functions....
From: Duane Rettig
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <43cwg17s0.fsf@beta.franz.com>
"Joe Marshall" <·············@attbi.com> writes:

> "Barry Watson" <············@uab.ericsson.se> wrote in message
 ······················@uab.ericsson.se...
> >
> >
> > larry wrote:
> > >
> > > Maybe programmatically creating and compiling a function at runtime
> > > can be done in C, but
> > > it seems like you'd have to hack it because as far as I know C does
> > > not support this.
> >
> > #include <stdlib.h>
> > #includ <stdio.h>
> >
> > int main()
> > {
> > FILE *fp;
> > fp=fopen("source.c", "w");
> > fprintf(fp, "#include <stdio.h>\nint main(){printf(\"hello world\");
> > return 0}");
> > fclose(fp);
> > system("cc source.c");
> > system("./a.out");
> > return 0;
> > }
> >
> >
> > How hard was that?
> 
> Cool, but I tried it on a pair of mutually recursive functions....

You'd have to expand the example to us C's version of gensym (i.e.
mktemp(3)) to create the recursions.  But instead of a stack overflow,
you'd get a "no more processes" error ...


-- 
Duane Rettig          Franz Inc.            http://www.franz.com/ (www)
1995 University Ave Suite 275  Berkeley, CA 94704
Phone: (510) 548-3600; FAX: (510) 548-8253   ·····@Franz.COM (internet)
From: Joe Marshall
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <lIRH8.248$YV2.398379@typhoon.ne.ipsvc.net>
"Duane Rettig" <·····@franz.com> wrote in message ··················@beta.franz.com...
> "Joe Marshall" <·············@attbi.com> writes:
>
> > "Barry Watson" <············@uab.ericsson.se> wrote in message
>  ······················@uab.ericsson.se...
> > >
> > >
> > > larry wrote:
> > > >
> > > > Maybe programmatically creating and compiling a function at runtime
> > > > can be done in C, but
> > > > it seems like you'd have to hack it because as far as I know C does
> > > > not support this.
> > >
> > > #include <stdlib.h>
> > > #includ <stdio.h>
> > >
> > > int main()
> > > {
> > > FILE *fp;
> > > fp=fopen("source.c", "w");
> > > fprintf(fp, "#include <stdio.h>\nint main(){printf(\"hello world\");
> > > return 0}");
> > > fclose(fp);
> > > system("cc source.c");
> > > system("./a.out");
> > > return 0;
> > > }
> > >
> > >
> > > How hard was that?
> >
> > Cool, but I tried it on a pair of mutually recursive functions....
>
> You'd have to expand the example to us C's version of gensym (i.e.
> mktemp(3)) to create the recursions.  But instead of a stack overflow,
> you'd get a "no more processes" error ...

Gotcha.  Now the next problem is catch/throw and unwind-protect.
From: Duane Rettig
Subject: Re: what lisp can do that C can't do
Date: 
Message-ID: <4y9e7zvey.fsf@beta.franz.com>
"Joe Marshall" <·············@attbi.com> writes:

> "Duane Rettig" <·····@franz.com> wrote in message
 ··················@beta.franz.com...
> > "Joe Marshall" <·············@attbi.com> writes:
> >
> > > "Barry Watson" <············@uab.ericsson.se> wrote in message
> >  ······················@uab.ericsson.se...
> > > >
> > > >
> > > > larry wrote:
> > > > >
> > > > > Maybe programmatically creating and compiling a function at runtime
> > > > > can be done in C, but
> > > > > it seems like you'd have to hack it because as far as I know C does
> > > > > not support this.
> > > >
> > > > #include <stdlib.h>
> > > > #includ <stdio.h>
> > > >
> > > > int main()
> > > > {
> > > > FILE *fp;
> > > > fp=fopen("source.c", "w");
> > > > fprintf(fp, "#include <stdio.h>\nint main(){printf(\"hello world\");
> > > > return 0}");
> > > > fclose(fp);
> > > > system("cc source.c");
> > > > system("./a.out");
> > > > return 0;
> > > > }
> > > >
> > > >
> > > > How hard was that?
> > >
> > > Cool, but I tried it on a pair of mutually recursive functions....
> >
> > You'd have to expand the example to us C's version of gensym (i.e.
> > mktemp(3)) to create the recursions.  But instead of a stack overflow,
> > you'd get a "no more processes" error ...
> 
> Gotcha.  Now the next problem is catch/throw and unwind-protect.

Piece of cake.  Every catch forks a process.  The child's process-id
is the catch tag.  When the child dies, the catch is completed, and
can continue.  A special throw-server process sits waiting for messages.
A throw is a message to this server with the process-id of the child,
and it kills off that child and all of its children, in reverse order.
But it kills the process by sending it a terminate signal instead of a
kill signal, so that any processes with protected forms to execute can
execute them.

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