From: Eli Gottlieb
Subject: Foreign Function Interfaces
Date: 
Message-ID: <T3W3g.1565$Gg.832@twister.nyroc.rr.com>
If I may once again request the community's wisdom on a small matter...

I am designing a Lisp dialect (and interpreter, which is largely coded 
by now) for my pet operating system, and wish to add an FFI.  I've heard 
of every implementation of CL having its own, in addition to 
compatibility layers such as the Universal Foreign Function Interface 
and Common Foreign Function Interface, but which is best?  By "best", I 
mean 1) Easy for systems hackers to use and 2) Powerful and capable.

The goal is to create a Lisp interpreter which could be booted into and 
used as a systems progamming language, ie: to write important libraries 
and device drivers in.  I can code the primitives of the FFI into the 
interpreter (once I finally get the abominable returning tagbody error 
sorted out), but I want to make sure it'll have enough power to code the 
entire system (besides the kernel itself) in Lisp.

Also, would it be better to export Lisp functions in binary form 
(callable from C), or simply provide the one exported function eval(), 
which would be take a C string containing the Lisp expression to evaluate?

And yes, this interpreter will be released to the public so you can tell 
me how bad my code is.

Todah rabah,
Eli
-- 
The science of economics is the cleverest proof of free will yet 
constructed.

From: Friedrich Dominicus
Subject: Re: Foreign Function Interfaces
Date: 
Message-ID: <87lktr5y3q.fsf@flarge.here>
Eli Gottlieb <···········@gmail.com> writes:

> If I may once again request the community's wisdom on a small matter...
>
> I am designing a Lisp dialect (and interpreter, which is largely coded
> by now) for my pet operating system, and wish to add an FFI.  I've
> heard of every implementation of CL having its own, in addition to
> compatibility layers such as the Universal Foreign Function Interface
> and Common Foreign Function Interface, but which is best?  By "best",
> I mean 1) Easy for systems hackers to use and 2) Powerful and
>capable.
Well it seems that you have gone your way, however I'm curious why
you had to implement you own Lisp.

I guess you have seen 
Lush: http://lush.sourceforge.net/
ECL : 

diverse Schemes etc. 

> The goal is to create a Lisp interpreter which could be booted into
> and used as a systems progamming language, ie: to write important
> libraries and device drivers in.

Hm according to their docs Lush was developed for that purpose. Maybe
you should check their FLI?

Regards
Friedrich


-- 
Please remove just-for-news- to reply via e-mail.
From: Eli Gottlieb
Subject: Re: Foreign Function Interfaces
Date: 
Message-ID: <ID44g.1597$Gg.733@twister.nyroc.rr.com>
Friedrich Dominicus wrote:
> Eli Gottlieb <···········@gmail.com> writes:
> 
> 
>>If I may once again request the community's wisdom on a small matter...
>>
>>I am designing a Lisp dialect (and interpreter, which is largely coded
>>by now) for my pet operating system, and wish to add an FFI.  I've
>>heard of every implementation of CL having its own, in addition to
>>compatibility layers such as the Universal Foreign Function Interface
>>and Common Foreign Function Interface, but which is best?  By "best",
>>I mean 1) Easy for systems hackers to use and 2) Powerful and
>>capable.
> 
> Well it seems that you have gone your way, however I'm curious why
> you had to implement you own Lisp.

I wanted language constructs not available in current Lisps.  Examples: 
Environment objects, all-code-is-a-function, and dynamic coding capability.

> 
> I guess you have seen 
> Lush: http://lush.sourceforge.net/
> ECL : 
> 
> diverse Schemes etc. 

Yep.  Looked at all of those (including several of the "diverse 
Schemes") before deciding to write my own.

ECLS was extremely interesting, given that its functions are "naturally" 
compiled with C-like protocols.  I corresponded Juan Jose Garcia Ripoll 
about it, actually.  Apparently documentation on adding and removing 
primitive functions is scarce.

> 
> 
>>The goal is to create a Lisp interpreter which could be booted into
>>and used as a systems progamming language, ie: to write important
>>libraries and device drivers in.
> 
> 
> Hm according to their docs Lush was developed for that purpose. Maybe
> you should check their FLI?
> 
> Regards
> Friedrich
"Lush is an object-oriented programming language designed for 
researchers, experimenters, and engineers interested in large-scale 
numerical and graphic applications."

I considered Lush, then realized it seems to want every library under 
the sun in order to work properly.  If it can be compiled down, though, 
it'll work.  It just has to compile down so far that even POSIX support 
isn't even needed (for device drivers).

Loving it when a Lisper reacts viscerally with "don't break the herd!" 
rather than answering the asked question,
Eli Gottlieb (NOT planning world domination of my Lisp)
-- 
The science of economics is the cleverest proof of free will yet 
constructed.
From: bradb
Subject: Re: Foreign Function Interfaces
Date: 
Message-ID: <1146151703.378995.224300@u72g2000cwu.googlegroups.com>
I would suggest basing your FFI around CFFI, as that appears to be the
current best portable FFI.
Putting on my device driver programmer hat for a moment, I would expect
that one truely useful feature of a Lisp that is designed for embedded
work would be the ability to easily specify the types of variables
being written to the hardware.
For example, in C.

typedef unsigned int uint32;
uint32 poke (uint32 *addr, uint32 value)
{
   *addr = value;
   return *addr;
}

I think that a Lisp aimed at device drivers would need to be able to
explicitly handle static types easily, the syntax could be like:

(define-typed-func :uint32 poke ((:uint32 addr) (:uint32 value))
  (setf (mem-ref addr) value)
  (mem-ref addr))

The Lisp is a little more verbose, but I think device drivers is a
domain that C excels in because it maps so well to the underlying
hardware.  If I were doing this, I would think about making [] the
defererence operator, so that
(mem-ref addr) -> [addr]
(setf (mem-ref addr) x) -> (setf [addr] x)
(mem-ref (+ addr 5)) === (mem-ref addr 5) -> [addr 5]

You mention that your Lisp will be interpreted, is compilation an
eventual goal?

Good luck with your Lisp!

Brad
From: Eli Gottlieb
Subject: Re: Foreign Function Interfaces
Date: 
Message-ID: <3k64g.9485$ZQ3.3029@twister.nyroc.rr.com>
bradb wrote:
> I would suggest basing your FFI around CFFI, as that appears to be the
> current best portable FFI.

Thanks.

> Putting on my device driver programmer hat for a moment, I would expect
> that one truely useful feature of a Lisp that is designed for embedded
> work would be the ability to easily specify the types of variables
> being written to the hardware.
> For example, in C.
> 
> typedef unsigned int uint32;
> uint32 poke (uint32 *addr, uint32 value)
> {
>    *addr = value;
>    return *addr;
> }
> 
> I think that a Lisp aimed at device drivers would need to be able to
> explicitly handle static types easily, the syntax could be like:
> 
> (define-typed-func :uint32 poke ((:uint32 addr) (:uint32 value))
>   (setf (mem-ref addr) value)
>   (mem-ref addr))
> 
> The Lisp is a little more verbose, but I think device drivers is a
> domain that C excels in because it maps so well to the underlying
> hardware.  If I were doing this, I would think about making [] the
> defererence operator, so that
> (mem-ref addr) -> [addr]
> (setf (mem-ref addr) x) -> (setf [addr] x)
> (mem-ref (+ addr 5)) === (mem-ref addr 5) -> [addr 5]

Makes quite a bit of sense.  The Lisp code would need to be able to know 
about the hardware representation of low-level data.

> 
> You mention that your Lisp will be interpreted, is compilation an
> eventual goal?

When I learn about compilation.
-- 
The science of economics is the cleverest proof of free will yet 
constructed.
From: Ari Johnson
Subject: Re: Foreign Function Interfaces
Date: 
Message-ID: <m2r73j551x.fsf@hermes.theari.com>
Eli Gottlieb <···········@gmail.com> writes:

> bradb wrote:
>> You mention that your Lisp will be interpreted, is compilation an
>> eventual goal?
>
> When I learn about compilation.

Whatever you do, think about compilation before you design your data
structures.  Because of how I handled symbol lookups in a lisp
interpreter I wrote a few years ago, it is impossible to actually gain
anything by writing a compiler.  I didn't understand CL symbols so I
didn't copy them, and they are a Good Idea (TM) if you're going to be
compiling things.
From: Eli Gottlieb
Subject: Re: Foreign Function Interfaces
Date: 
Message-ID: <5S74g.1922$Gg.490@twister.nyroc.rr.com>
Ari Johnson wrote:
> Eli Gottlieb <···········@gmail.com> writes:
> 
> 
>>bradb wrote:
>>
>>>You mention that your Lisp will be interpreted, is compilation an
>>>eventual goal?
>>
>>When I learn about compilation.
> 
> 
> Whatever you do, think about compilation before you design your data
> structures.  Because of how I handled symbol lookups in a lisp
> interpreter I wrote a few years ago, it is impossible to actually gain
> anything by writing a compiler.  I didn't understand CL symbols so I
> didn't copy them, and they are a Good Idea (TM) if you're going to be
> compiling things.
"Didn't copy them"?

I just wrote a descendant of TLispObject (which makes it Pascal 
type-safe with other Lisp data and subjects it to reference counting) 
which contained a symbol name string.  A function obtains symbols by 
name, and symbol equality is determined by performing an object 
comparison.  Will that work?

-- 
The science of economics is the cleverest proof of free will yet 
constructed.
From: Ari Johnson
Subject: Re: Foreign Function Interfaces
Date: 
Message-ID: <m2mze66fbe.fsf@hermes.theari.com>
Eli Gottlieb <···········@gmail.com> writes:

> Ari Johnson wrote:
>> Whatever you do, think about compilation before you design your data
>> structures.  Because of how I handled symbol lookups in a lisp
>> interpreter I wrote a few years ago, it is impossible to actually gain
>> anything by writing a compiler.  I didn't understand CL symbols so I
>> didn't copy them, and they are a Good Idea (TM) if you're going to be
>> compiling things.
> "Didn't copy them"?
>
> I just wrote a descendant of TLispObject (which makes it Pascal
> type-safe with other Lisp data and subjects it to reference counting)
> which contained a symbol name string.  A function obtains symbols by
> name, and symbol equality is determined by performing an object
> comparison.  Will that work?

Here's what I did "wrong" ...

I wanted to have one lisp image of sorts that provided separation of
environment for many users.  If you're interested, I wrote it as a
control language for a space simulation engine that I created for MUSH
games to use.  I wanted to allow the players of the game to use this
lisp dialect to control their ships and so forth.  It's actually very
successful for that, even if nobody but myself has coded for it (it's
so much easier to code an autopilot in lisp than in C or, worse,
MUSHcode).  So each ship has to have its own environment, but I didn't
want one lisp image per ship since it seemed wasteful of memory.

So what I have is a tree structure of "environments."  Each one is a
4-element vector of the form #(symbols global dynamic parent), where
symbols is an alist of symbols and values, global is a pointer to the
global environment (the procedures and such that the language provides
are in that environment's symbol list), dynamic is a pointer to the
dynamic environment, which is defined as the local root-level one (so,
global symbols for the current user), and parent is a pointer to the
parent environment.

Environments are created when entering a funcall and when entering a
let body.

The problem with this in terms of compilation is that, unless I make
it extremely smart (which I'm frankly not willing to spend the time
doing because I'm not a compiler wizard to begin with and this is just
a hobby project), the compiler will not be able to do any better than
compiling to bytecode and placing the symbol name into the output,
while the bytecode interpreter would have to read the symbol name and
then look it up through the alists of the environment chain to
determine the symbol value.

Also, I do not have separate namespaces for variables and functions.

What I would prefer to have done (and it's possible to change to this,
but involves extensive changes that I don't really have time for, see
above) is to have at least a value slot on the symbol and then stored
just a list of symbols rather than an alist of (symbol . value) pairs.
Essentially, my symbols only have a name and nothing else.  (In fact,
other than parsing, printing, and evaluating, they are the exact same
underlying C code as for strings.)

Contrast with Common Lisp, where symbols have the following slots:
  Name
  Package
  Value
  Function
  Property list
...possibly more that I'm forgetting in this quick post.

Trying to figure out how to implement a compiler for my lisp dialect
was one of the stepping stones to grokking CL symbols.
From: Eli Gottlieb
Subject: Re: Foreign Function Interfaces
Date: 
Message-ID: <2V84g.1923$Gg.608@twister.nyroc.rr.com>
Ari Johnson wrote:
> Eli Gottlieb <···········@gmail.com> writes:
> 
> 
>>Ari Johnson wrote:
>>
>>>Whatever you do, think about compilation before you design your data
>>>structures.  Because of how I handled symbol lookups in a lisp
>>>interpreter I wrote a few years ago, it is impossible to actually gain
>>>anything by writing a compiler.  I didn't understand CL symbols so I
>>>didn't copy them, and they are a Good Idea (TM) if you're going to be
>>>compiling things.
>>
>>"Didn't copy them"?
>>
>>I just wrote a descendant of TLispObject (which makes it Pascal
>>type-safe with other Lisp data and subjects it to reference counting)
>>which contained a symbol name string.  A function obtains symbols by
>>name, and symbol equality is determined by performing an object
>>comparison.  Will that work?
> 
> 
> Here's what I did "wrong" ...
> 
> I wanted to have one lisp image of sorts that provided separation of
> environment for many users.  If you're interested, I wrote it as a
> control language for a space simulation engine that I created for MUSH
> games to use.  I wanted to allow the players of the game to use this
> lisp dialect to control their ships and so forth.  It's actually very
> successful for that, even if nobody but myself has coded for it (it's
> so much easier to code an autopilot in lisp than in C or, worse,
> MUSHcode).  So each ship has to have its own environment, but I didn't
> want one lisp image per ship since it seemed wasteful of memory.
> 
> So what I have is a tree structure of "environments."  Each one is a
> 4-element vector of the form #(symbols global dynamic parent), where
> symbols is an alist of symbols and values, global is a pointer to the
> global environment (the procedures and such that the language provides
> are in that environment's symbol list), dynamic is a pointer to the
> dynamic environment, which is defined as the local root-level one (so,
> global symbols for the current user), and parent is a pointer to the
> parent environment.
> 
> Environments are created when entering a funcall and when entering a
> let body.
> 
> The problem with this in terms of compilation is that, unless I make
> it extremely smart (which I'm frankly not willing to spend the time
> doing because I'm not a compiler wizard to begin with and this is just
> a hobby project), the compiler will not be able to do any better than
> compiling to bytecode and placing the symbol name into the output,
> while the bytecode interpreter would have to read the symbol name and
> then look it up through the alists of the environment chain to
> determine the symbol value.
> 
> Also, I do not have separate namespaces for variables and functions.
> 
> What I would prefer to have done (and it's possible to change to this,
> but involves extensive changes that I don't really have time for, see
> above) is to have at least a value slot on the symbol and then stored
> just a list of symbols rather than an alist of (symbol . value) pairs.
> Essentially, my symbols only have a name and nothing else.  (In fact,
> other than parsing, printing, and evaluating, they are the exact same
> underlying C code as for strings.)
> 
> Contrast with Common Lisp, where symbols have the following slots:
>   Name
>   Package
>   Value
>   Function
>   Property list
> ...possibly more that I'm forgetting in this quick post.
> 
> Trying to figure out how to implement a compiler for my lisp dialect
> was one of the stepping stones to grokking CL symbols.
Wouldn't the Value and Function slots be stacks of values then, to allow 
for lexical variables?

-- 
The science of economics is the cleverest proof of free will yet 
constructed.
From: Eli Gottlieb
Subject: Re: Foreign Function Interfaces
Date: 
Message-ID: <xW84g.1925$Gg.13@twister.nyroc.rr.com>
Ari Johnson wrote:
> Eli Gottlieb <···········@gmail.com> writes:
> 
> 
>>Ari Johnson wrote:
>>
>>>Whatever you do, think about compilation before you design your data
>>>structures.  Because of how I handled symbol lookups in a lisp
>>>interpreter I wrote a few years ago, it is impossible to actually gain
>>>anything by writing a compiler.  I didn't understand CL symbols so I
>>>didn't copy them, and they are a Good Idea (TM) if you're going to be
>>>compiling things.
>>
>>"Didn't copy them"?
>>
>>I just wrote a descendant of TLispObject (which makes it Pascal
>>type-safe with other Lisp data and subjects it to reference counting)
>>which contained a symbol name string.  A function obtains symbols by
>>name, and symbol equality is determined by performing an object
>>comparison.  Will that work?
> 
> 
> Here's what I did "wrong" ...
> 
> I wanted to have one lisp image of sorts that provided separation of
> environment for many users.  If you're interested, I wrote it as a
> control language for a space simulation engine that I created for MUSH
> games to use.  I wanted to allow the players of the game to use this
> lisp dialect to control their ships and so forth.  It's actually very
> successful for that, even if nobody but myself has coded for it (it's
> so much easier to code an autopilot in lisp than in C or, worse,
> MUSHcode).  So each ship has to have its own environment, but I didn't
> want one lisp image per ship since it seemed wasteful of memory.
> 
> So what I have is a tree structure of "environments."  Each one is a
> 4-element vector of the form #(symbols global dynamic parent), where
> symbols is an alist of symbols and values, global is a pointer to the
> global environment (the procedures and such that the language provides
> are in that environment's symbol list), dynamic is a pointer to the
> dynamic environment, which is defined as the local root-level one (so,
> global symbols for the current user), and parent is a pointer to the
> parent environment.
> 
> Environments are created when entering a funcall and when entering a
> let body.
> 
> The problem with this in terms of compilation is that, unless I make
> it extremely smart (which I'm frankly not willing to spend the time
> doing because I'm not a compiler wizard to begin with and this is just
> a hobby project), the compiler will not be able to do any better than
> compiling to bytecode and placing the symbol name into the output,
> while the bytecode interpreter would have to read the symbol name and
> then look it up through the alists of the environment chain to
> determine the symbol value.
> 
> Also, I do not have separate namespaces for variables and functions.
> 
> What I would prefer to have done (and it's possible to change to this,
> but involves extensive changes that I don't really have time for, see
> above) is to have at least a value slot on the symbol and then stored
> just a list of symbols rather than an alist of (symbol . value) pairs.
> Essentially, my symbols only have a name and nothing else.  (In fact,
> other than parsing, printing, and evaluating, they are the exact same
> underlying C code as for strings.)
> 
> Contrast with Common Lisp, where symbols have the following slots:
>   Name
>   Package
>   Value
>   Function
>   Property list
> ...possibly more that I'm forgetting in this quick post.
> 
> Trying to figure out how to implement a compiler for my lisp dialect
> was one of the stepping stones to grokking CL symbols.
Wouldn't the Value and Function slots be stacks of values then, to allow 
for lexical variables?

Also, it appears I made the same mistake you did.  Oh, well.  I don't 
see a way to implement first-class environments with the CL method, anyway.

-- 
The science of economics is the cleverest proof of free will yet 
constructed.
From: Ari Johnson
Subject: Re: Foreign Function Interfaces
Date: 
Message-ID: <m2irou68qr.fsf@hermes.theari.com>
Eli Gottlieb <···········@gmail.com> writes:

> Ari Johnson wrote:
>> Eli Gottlieb <···········@gmail.com> writes:
>> 
>>>Ari Johnson wrote:
>>>
>>>>Whatever you do, think about compilation before you design your data
>>>>structures.  Because of how I handled symbol lookups in a lisp
>>>>interpreter I wrote a few years ago, it is impossible to actually gain
>>>>anything by writing a compiler.  I didn't understand CL symbols so I
>>>>didn't copy them, and they are a Good Idea (TM) if you're going to be
>>>>compiling things.
>>>
>>>"Didn't copy them"?
>>>
>>>I just wrote a descendant of TLispObject (which makes it Pascal
>>>type-safe with other Lisp data and subjects it to reference counting)
>>>which contained a symbol name string.  A function obtains symbols by
>>>name, and symbol equality is determined by performing an object
>>>comparison.  Will that work?
>> Here's what I did "wrong" ...
>> I wanted to have one lisp image of sorts that provided separation of
>> environment for many users.  If you're interested, I wrote it as a
>> control language for a space simulation engine that I created for MUSH
>> games to use.  I wanted to allow the players of the game to use this
>> lisp dialect to control their ships and so forth.  It's actually very
>> successful for that, even if nobody but myself has coded for it (it's
>> so much easier to code an autopilot in lisp than in C or, worse,
>> MUSHcode).  So each ship has to have its own environment, but I didn't
>> want one lisp image per ship since it seemed wasteful of memory.
>> So what I have is a tree structure of "environments."  Each one is a
>> 4-element vector of the form #(symbols global dynamic parent), where
>> symbols is an alist of symbols and values, global is a pointer to the
>> global environment (the procedures and such that the language provides
>> are in that environment's symbol list), dynamic is a pointer to the
>> dynamic environment, which is defined as the local root-level one (so,
>> global symbols for the current user), and parent is a pointer to the
>> parent environment.
>> Environments are created when entering a funcall and when entering a
>> let body.
>> The problem with this in terms of compilation is that, unless I make
>> it extremely smart (which I'm frankly not willing to spend the time
>> doing because I'm not a compiler wizard to begin with and this is just
>> a hobby project), the compiler will not be able to do any better than
>> compiling to bytecode and placing the symbol name into the output,
>> while the bytecode interpreter would have to read the symbol name and
>> then look it up through the alists of the environment chain to
>> determine the symbol value.
>> Also, I do not have separate namespaces for variables and functions.
>> What I would prefer to have done (and it's possible to change to
>> this,
>> but involves extensive changes that I don't really have time for, see
>> above) is to have at least a value slot on the symbol and then stored
>> just a list of symbols rather than an alist of (symbol . value) pairs.
>> Essentially, my symbols only have a name and nothing else.  (In fact,
>> other than parsing, printing, and evaluating, they are the exact same
>> underlying C code as for strings.)
>> Contrast with Common Lisp, where symbols have the following slots:
>>   Name
>>   Package
>>   Value
>>   Function
>>   Property list
>> ...possibly more that I'm forgetting in this quick post.
>> Trying to figure out how to implement a compiler for my lisp dialect
>> was one of the stepping stones to grokking CL symbols.
> Wouldn't the Value and Function slots be stacks of values then, to
> allow for lexical variables?
>
> Also, it appears I made the same mistake you did.  Oh, well.  I don't
> see a way to implement first-class environments with the CL method,
> anyway.

I don't either, although I suspect someone who reads this eventually
will. :)
From: Pascal Costanza
Subject: Re: Foreign Function Interfaces
Date: 
Message-ID: <4bcq8hF10u3bsU1@individual.net>
Eli Gottlieb wrote:

> Also, it appears I made the same mistake you did.  Oh, well.  I don't 
> see a way to implement first-class environments with the CL method, anyway.

Both OpenLisp and clisp provide first-class lexical environments (clisp 
only for interpreted code).


Pascal

-- 
3rd European Lisp Workshop
July 3-4 - Nantes, France - co-located with ECOOP 2006
http://lisp-ecoop06.bknr.net/
From: Eli Gottlieb
Subject: Re: Foreign Function Interfaces
Date: 
Message-ID: <awd4g.2108$Gg.1960@twister.nyroc.rr.com>
Pascal Costanza wrote:
> Eli Gottlieb wrote:
> 
>> Also, it appears I made the same mistake you did.  Oh, well.  I don't 
>> see a way to implement first-class environments with the CL method, 
>> anyway.
> 
> 
> Both OpenLisp and clisp provide first-class lexical environments (clisp 
> only for interpreted code).
> 
> 
> Pascal
> 
So how do I use them in clisp?  Didn't even know they were there.

Still, with first-class environments built into the language I can do this:

(define defun (quoted-lambda (name args body) (eval `(define ,name 
(lambda ,args ,body)))))
(define defquoted (quoted-lambda (name args body) (eval `(define ,name 
(quoted-lambda ,args ,body)))))
(defquoted macro (args body) (eval `(quoted-lambda ,args (eval ,body 
(parent-env (current-env) 'caller))) (parent-env (current-env) 'caller)))
(defquoted defmacro (name args body) (eval `(define ,name (macro ,args 
,body))))
(defmacro if (condition then &optional else) `(cond (,condition ,then) 
(t ,else)))
;This version of list guarantees a freshly consed result.
(defun list (&rest items) (if items (cons (car items) (apply list (cdr 
items)))))
;This version just returns its argument.  If that argument was obtained 
from the use of APPLY, its list structure could be shared.
(defun other-list (&rest items) items)

Noted that a quoted-lambda simply creates a function whose arguments are 
not evaluated prior to being passed in, it's as though they were all 
given one level of quoting.  Defquoted defines a quoted-lambda function 
in the dynamic environment with the given args and body, and the 
environment functions are used to make sure the bindings of name, args 
and body don't interfere with the code passed into those parameters by 
passing them as an optional argument to eval.  If no environment is 
given (as in the def* forms) eval uses the dynamic environment by default.

-- 
The science of economics is the cleverest proof of free will yet 
constructed.
From: Pascal Costanza
Subject: Re: Foreign Function Interfaces
Date: 
Message-ID: <4bdvsvFvemuhU1@individual.net>
Eli Gottlieb wrote:
> Pascal Costanza wrote:
>> Eli Gottlieb wrote:
>>
>>> Also, it appears I made the same mistake you did.  Oh, well.  I don't 
>>> see a way to implement first-class environments with the CL method, 
>>> anyway.
>>
>>
>> Both OpenLisp and clisp provide first-class lexical environments 
>> (clisp only for interpreted code).
>>
>>
>> Pascal
>>
> So how do I use them in clisp?  Didn't even know they were there.

See http://clisp.cons.org/impnotes.html#eval-environ


Pascal

-- 
3rd European Lisp Workshop
July 3-4 - Nantes, France - co-located with ECOOP 2006
http://lisp-ecoop06.bknr.net/
From: Eli Gottlieb
Subject: Re: Foreign Function Interfaces
Date: 
Message-ID: <H3p4g.4499$TT.935@twister.nyroc.rr.com>
Pascal Costanza wrote:
> Eli Gottlieb wrote:
> 
>> Pascal Costanza wrote:
>>
>>> Eli Gottlieb wrote:
>>>
>>>> Also, it appears I made the same mistake you did.  Oh, well.  I 
>>>> don't see a way to implement first-class environments with the CL 
>>>> method, anyway.
>>>
>>>
>>>
>>> Both OpenLisp and clisp provide first-class lexical environments 
>>> (clisp only for interpreted code).
>>>
>>>
>>> Pascal
>>>
>> So how do I use them in clisp?  Didn't even know they were there.
> 
> 
> See http://clisp.cons.org/impnotes.html#eval-environ
> 
> 
> Pascal
> 
Pity it seems to be uncompilable.

-- 
The science of economics is the cleverest proof of free will yet 
constructed.
From: Pascal Costanza
Subject: Re: Foreign Function Interfaces
Date: 
Message-ID: <4ben3hF1156q6U1@individual.net>
Eli Gottlieb wrote:
> Pascal Costanza wrote:
>> Eli Gottlieb wrote:
>>
>>> Pascal Costanza wrote:
>>>
>>>> Eli Gottlieb wrote:
>>>>
>>>>> Also, it appears I made the same mistake you did.  Oh, well.  I 
>>>>> don't see a way to implement first-class environments with the CL 
>>>>> method, anyway.
>>>>
>>>> Both OpenLisp and clisp provide first-class lexical environments 
>>>> (clisp only for interpreted code).
>>>>
>>>> Pascal
>>>>
>>> So how do I use them in clisp?  Didn't even know they were there.
>>
>> See http://clisp.cons.org/impnotes.html#eval-environ
>>
>> Pascal
>>
> Pity it seems to be uncompilable.

...but it's good enough to play around with this. OpenLisp provides the 
same constructs, but if I understand correctly, can still be compiled.

Note, however, that it's pretty hard to impossible anyway to do decent 
compilation once you introduce first-class lexical environments. Lookup 
of variables has to go through an environment structure (an alist or a 
hashtable) and this is slower than lexical addressing. Due to macros, a 
capture of a lexical environment can happen almost anywhere (as part of 
the code that a macro expands to).

The kind of reflection that first-class environments provide can also be 
achieved in a relatively straightforward way with different means. 
OOP-style objects or structs can, for example, be used to group state 
and pass it around. If you really want more seamless access to a lexical 
environment, you can also use plain closures, roughly like this:

(let ((a b c))
   (lambda (op var &optional value)
     (ecase op
       (get (ecase var (a a) (b b) (c c)))
       (set (ecase var
              (a (setq a value))
              (b (setq b value))
              (c (setq c value)))))))

The overhead that is introduced by looking up a variable in an ecase 
form is probably roughly the overhead you would get by looking up 
variables in a first-class lexical environment.

Compare this to the use of a struct:

(defstruct env a b c)

(let ((env (make-env :a 0 :b 1 :c 2)))
   env)

If you get such an environment object you can access its slots like this:

(env-a env)
(setf (env-b env) 42)

Such access to slots in structs (or OOP-style objects) is very likely 
much faster than access to variables in first-class environments.


Pascal

-- 
3rd European Lisp Workshop
July 3-4 - Nantes, France - co-located with ECOOP 2006
http://lisp-ecoop06.bknr.net/
From: Eli Gottlieb
Subject: Re: Foreign Function Interfaces
Date: 
Message-ID: <HBu4g.4513$Gg.1240@twister.nyroc.rr.com>
Pascal Costanza wrote:
> Eli Gottlieb wrote:
> 
>> Pascal Costanza wrote:
>>
>>> Eli Gottlieb wrote:
>>>
>>>> Pascal Costanza wrote:
>>>>
>>>>> Eli Gottlieb wrote:
>>>>>
>>>>>> Also, it appears I made the same mistake you did.  Oh, well.  I 
>>>>>> don't see a way to implement first-class environments with the CL 
>>>>>> method, anyway.
>>>>>
>>>>>
>>>>> Both OpenLisp and clisp provide first-class lexical environments 
>>>>> (clisp only for interpreted code).
>>>>>
>>>>> Pascal
>>>>>
>>>> So how do I use them in clisp?  Didn't even know they were there.
>>>
>>>
>>> See http://clisp.cons.org/impnotes.html#eval-environ
>>>
>>> Pascal
>>>
>> Pity it seems to be uncompilable.
> 
> 
> ...but it's good enough to play around with this. OpenLisp provides the 
> same constructs, but if I understand correctly, can still be compiled.
> 
> Note, however, that it's pretty hard to impossible anyway to do decent 
> compilation once you introduce first-class lexical environments. Lookup 
> of variables has to go through an environment structure (an alist or a 
> hashtable) and this is slower than lexical addressing. Due to macros, a 
> capture of a lexical environment can happen almost anywhere (as part of 
> the code that a macro expands to).
> 
> The kind of reflection that first-class environments provide can also be 
> achieved in a relatively straightforward way with different means. 
> OOP-style objects or structs can, for example, be used to group state 
> and pass it around. If you really want more seamless access to a lexical 
> environment, you can also use plain closures, roughly like this:
> 
> (let ((a b c))
>   (lambda (op var &optional value)
>     (ecase op
>       (get (ecase var (a a) (b b) (c c)))
>       (set (ecase var
>              (a (setq a value))
>              (b (setq b value))
>              (c (setq c value)))))))
> 
> The overhead that is introduced by looking up a variable in an ecase 
> form is probably roughly the overhead you would get by looking up 
> variables in a first-class lexical environment.
> 
> Compare this to the use of a struct:
> 
> (defstruct env a b c)
> 
> (let ((env (make-env :a 0 :b 1 :c 2)))
>   env)
> 
> If you get such an environment object you can access its slots like this:
> 
> (env-a env)
> (setf (env-b env) 42)
> 
> Such access to slots in structs (or OOP-style objects) is very likely 
> much faster than access to variables in first-class environments.
> 
> 
> Pascal
> 
Using the lambdas to capture variables works more efficiently, but only 
for variables specified at time of writing.  First-class lexical 
environments allow lookup of any variable that environment was able to 
see, without having to know what it was/is ahead of time.

And who says variable lookup in a lexical environment has to go through 
a Lisp hash table or alist?  I store and look up bindings in mine at the 
Pascal level (going to add an optimized structure like a hash table for 
them one of these days), and the expressive power is still the same.

Actually, if your lexical environment system has a new-env function to 
create an empty environment (or a binding to an empty environment in the 
dynamic/global environment), you can use that, let forms, and 
evaluation-in-given-environment to build the struct and object system.

;Assuming blithely for the moment that a class is just a list of slot 
names stored as symbols.
(defun allocate-slots (slots)
   (eval
     `(let ,(mapcar list slots)
       (current-env))
     (new-env)))

This returns an environment object with the given slots.  Note that the 
"list" would read "#'list" in CL.
-- 
The science of economics is the cleverest proof of free will yet 
constructed.
From: Pascal Costanza
Subject: Re: Foreign Function Interfaces
Date: 
Message-ID: <4bkreoF11psbkU1@individual.net>
Eli Gottlieb wrote:
> Pascal Costanza wrote:
>> Eli Gottlieb wrote:
>>
>>> Pascal Costanza wrote:
>>>
>>>> Eli Gottlieb wrote:
>>>>
>>>>> Pascal Costanza wrote:
>>>>>
>>>>>> Eli Gottlieb wrote:
>>>>>>
>>>>>>> Also, it appears I made the same mistake you did.  Oh, well.  I 
>>>>>>> don't see a way to implement first-class environments with the CL 
>>>>>>> method, anyway.
>>>>>>
>>>>>>
>>>>>> Both OpenLisp and clisp provide first-class lexical environments 
>>>>>> (clisp only for interpreted code).
>>>>>>
>>>>>> Pascal
>>>>>>
>>>>> So how do I use them in clisp?  Didn't even know they were there.
>>>>
>>>>
>>>> See http://clisp.cons.org/impnotes.html#eval-environ
>>>>
>>>> Pascal
>>>>
>>> Pity it seems to be uncompilable.
>>
>>
>> ...but it's good enough to play around with this. OpenLisp provides 
>> the same constructs, but if I understand correctly, can still be 
>> compiled.
>>
>> Note, however, that it's pretty hard to impossible anyway to do decent 
>> compilation once you introduce first-class lexical environments. 
>> Lookup of variables has to go through an environment structure (an 
>> alist or a hashtable) and this is slower than lexical addressing. Due 
>> to macros, a capture of a lexical environment can happen almost 
>> anywhere (as part of the code that a macro expands to).
>>
>> The kind of reflection that first-class environments provide can also 
>> be achieved in a relatively straightforward way with different means. 
>> OOP-style objects or structs can, for example, be used to group state 
>> and pass it around. If you really want more seamless access to a 
>> lexical environment, you can also use plain closures, roughly like this:
>>
>> (let ((a b c))
>>   (lambda (op var &optional value)
>>     (ecase op
>>       (get (ecase var (a a) (b b) (c c)))
>>       (set (ecase var
>>              (a (setq a value))
>>              (b (setq b value))
>>              (c (setq c value)))))))
>>
>> The overhead that is introduced by looking up a variable in an ecase 
>> form is probably roughly the overhead you would get by looking up 
>> variables in a first-class lexical environment.
>>
>> Compare this to the use of a struct:
>>
>> (defstruct env a b c)
>>
>> (let ((env (make-env :a 0 :b 1 :c 2)))
>>   env)
>>
>> If you get such an environment object you can access its slots like this:
>>
>> (env-a env)
>> (setf (env-b env) 42)
>>
>> Such access to slots in structs (or OOP-style objects) is very likely 
>> much faster than access to variables in first-class environments.
>>
>> Pascal
>>
> Using the lambdas to capture variables works more efficiently, but only 
> for variables specified at time of writing.  First-class lexical 
> environments allow lookup of any variable that environment was able to 
> see, without having to know what it was/is ahead of time.

You can achieve the same effect by using a code walker. After all, the 
lexical environment is by definition quite static. I am not convinced 
that you gain a lot by being able to access arbitrary bindings in a 
first-class lexical environment.

> And who says variable lookup in a lexical environment has to go through 
> a Lisp hash table or alist?  I store and look up bindings in mine at the 
> Pascal level (going to add an optimized structure like a hash table for 
> them one of these days), and the expressive power is still the same.

What you want for performance is lexical addressing, that is, fixed 
offsets that can be used relative to the base address of a stack frame. 
Since your lexical environments can potentially come from anywhere in 
code like (eval something some-environment), you cannot use fixed 
offsets anymore, so you will have to do a translation from variable 
names to offsets at runtime. This is the runtime overhead that I am 
talking about here.

> Actually, if your lexical environment system has a new-env function to 
> create an empty environment (or a binding to an empty environment in the 
> dynamic/global environment), you can use that, let forms, and 
> evaluation-in-given-environment to build the struct and object system.
> 
> ;Assuming blithely for the moment that a class is just a list of slot 
> names stored as symbols.
> (defun allocate-slots (slots)
>   (eval
>     `(let ,(mapcar list slots)
>       (current-env))
>     (new-env)))

I don't see how this helps you (or what this helps you with).


Pascal

-- 
3rd European Lisp Workshop
July 3-4 - Nantes, France - co-located with ECOOP 2006
http://lisp-ecoop06.bknr.net/
From: Eli Gottlieb
Subject: Re: Foreign Function Interfaces
Date: 
Message-ID: <ajd5g.5903$TT.131@twister.nyroc.rr.com>
Pascal Costanza wrote:
> Eli Gottlieb wrote:
> 
>> Pascal Costanza wrote:
>>
>>> Eli Gottlieb wrote:
>>>
>>>> Pascal Costanza wrote:
>>>>
>>>>> Eli Gottlieb wrote:
>>>>>
>>>>>> Pascal Costanza wrote:
>>>>>>
>>>>>>> Eli Gottlieb wrote:
>>>>>>>
>>>>>>>> Also, it appears I made the same mistake you did.  Oh, well.  I 
>>>>>>>> don't see a way to implement first-class environments with the 
>>>>>>>> CL method, anyway.
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> Both OpenLisp and clisp provide first-class lexical environments 
>>>>>>> (clisp only for interpreted code).
>>>>>>>
>>>>>>> Pascal
>>>>>>>
>>>>>> So how do I use them in clisp?  Didn't even know they were there.
>>>>>
>>>>>
>>>>>
>>>>> See http://clisp.cons.org/impnotes.html#eval-environ
>>>>>
>>>>> Pascal
>>>>>
>>>> Pity it seems to be uncompilable.
>>>
>>>
>>>
>>> ...but it's good enough to play around with this. OpenLisp provides 
>>> the same constructs, but if I understand correctly, can still be 
>>> compiled.
>>>
>>> Note, however, that it's pretty hard to impossible anyway to do 
>>> decent compilation once you introduce first-class lexical 
>>> environments. Lookup of variables has to go through an environment 
>>> structure (an alist or a hashtable) and this is slower than lexical 
>>> addressing. Due to macros, a capture of a lexical environment can 
>>> happen almost anywhere (as part of the code that a macro expands to).
>>>
>>> The kind of reflection that first-class environments provide can also 
>>> be achieved in a relatively straightforward way with different means. 
>>> OOP-style objects or structs can, for example, be used to group state 
>>> and pass it around. If you really want more seamless access to a 
>>> lexical environment, you can also use plain closures, roughly like this:
>>>
>>> (let ((a b c))
>>>   (lambda (op var &optional value)
>>>     (ecase op
>>>       (get (ecase var (a a) (b b) (c c)))
>>>       (set (ecase var
>>>              (a (setq a value))
>>>              (b (setq b value))
>>>              (c (setq c value)))))))
>>>
>>> The overhead that is introduced by looking up a variable in an ecase 
>>> form is probably roughly the overhead you would get by looking up 
>>> variables in a first-class lexical environment.
>>>
>>> Compare this to the use of a struct:
>>>
>>> (defstruct env a b c)
>>>
>>> (let ((env (make-env :a 0 :b 1 :c 2)))
>>>   env)
>>>
>>> If you get such an environment object you can access its slots like 
>>> this:
>>>
>>> (env-a env)
>>> (setf (env-b env) 42)
>>>
>>> Such access to slots in structs (or OOP-style objects) is very likely 
>>> much faster than access to variables in first-class environments.
>>>
>>> Pascal
>>>
>> Using the lambdas to capture variables works more efficiently, but 
>> only for variables specified at time of writing.  First-class lexical 
>> environments allow lookup of any variable that environment was able to 
>> see, without having to know what it was/is ahead of time.
> 
> 
> You can achieve the same effect by using a code walker. After all, the 
> lexical environment is by definition quite static. I am not convinced 
> that you gain a lot by being able to access arbitrary bindings in a 
> first-class lexical environment.

Because everyone loves writing code walkers, loves having second-class 
compile-time macros that often require gensyms, and loves coming up with 
complicated macros of the aforementioned sort for the smallest task.

> 
>> And who says variable lookup in a lexical environment has to go 
>> through a Lisp hash table or alist?  I store and look up bindings in 
>> mine at the Pascal level (going to add an optimized structure like a 
>> hash table for them one of these days), and the expressive power is 
>> still the same.
> 
> 
> What you want for performance is lexical addressing, that is, fixed 
> offsets that can be used relative to the base address of a stack frame. 
> Since your lexical environments can potentially come from anywhere in 
> code like (eval something some-environment), you cannot use fixed 
> offsets anymore, so you will have to do a translation from variable 
> names to offsets at runtime. This is the runtime overhead that I am 
> talking about here.

'Tis true, alas.

> 
>> Actually, if your lexical environment system has a new-env function to 
>> create an empty environment (or a binding to an empty environment in 
>> the dynamic/global environment), you can use that, let forms, and 
>> evaluation-in-given-environment to build the struct and object system.
>>
>> ;Assuming blithely for the moment that a class is just a list of slot 
>> names stored as symbols.
>> (defun allocate-slots (slots)
>>   (eval
>>     `(let ,(mapcar list slots)
>>       (current-env))
>>     (new-env)))
> 
> 
> I don't see how this helps you (or what this helps you with).
> 
> 
> Pascal
> 
Remember the bit above where I defined a macro as an evaluation of the 
body form in the caller's environment?  In CL, macros are both 
second-class citizens and have to be built into the language.  In my 
Lisp, macros are first-class and are defined as special case of a 
function.  Will you consider that, at least, an increase in expressive 
power?

Here's a version of Peter Seibel's "doprimes" macro (from PCL chapter 8) 
that requires absolutely no gensyms because of how macros work in my Lisp:
> (defmacro doprimes (var-start-end &rest body)
>   (let ((var (car var-start-end)) (start (eval (cadr var-start-end) (caller-env))) (end (eval (caddr var-start-end) (caller-env))))
>     `(do ((,var (next-prime ,start) (next-prime (+1 ,var))))
>          ((> ,var ,end))
>        ,@body)))
Note how there's no need for either gensym or the ending-value variable. 
  The macro is called at runtime, and can thus evaluate both start and 
end in the appropriate order /outside the quasiquote expression/.  This 
means the do loop and body never see the start or end bindings, thus 
doing away with gensyms.

Sorry about the argument list, though.  I haven't taught the thing to 
deconstruct lists quite yet.
-- 
The science of economics is the cleverest proof of free will yet 
constructed.
From: Eli Gottlieb
Subject: Re: Foreign Function Interfaces
Date: 
Message-ID: <4td5g.5073$Gg.392@twister.nyroc.rr.com>
Eli Gottlieb wrote:
> Because everyone loves writing code walkers, loves having second-class 
> compile-time macros that often require gensyms, and loves coming up with 
> complicated macros of the aforementioned sort for the smallest task.

Adendum to Usenet posting: Also, having first-class environments allows 
my to trivially define a locative (which will never go null, it counts 
for garbage collection/reference counting):

(defun locative (symbol)
   (list symbol (caller-env)))
(defun dereference (loc)
   (eval (car loc) (cadr loc)))
-- 
The science of economics is the cleverest proof of free will yet 
constructed.
From: Pascal Costanza
Subject: Re: Foreign Function Interfaces
Date: 
Message-ID: <4bn4laF123oa3U1@individual.net>
Eli Gottlieb wrote:
> Pascal Costanza wrote:
>> Eli Gottlieb wrote:
>>
>>> Using the lambdas to capture variables works more efficiently, but 
>>> only for variables specified at time of writing.  First-class lexical 
>>> environments allow lookup of any variable that environment was able 
>>> to see, without having to know what it was/is ahead of time.
>>
>> You can achieve the same effect by using a code walker. After all, the 
>> lexical environment is by definition quite static. I am not convinced 
>> that you gain a lot by being able to access arbitrary bindings in a 
>> first-class lexical environment.
> 
> Because everyone loves writing code walkers, loves having second-class 
> compile-time macros that often require gensyms, and loves coming up with 
> complicated macros of the aforementioned sort for the smallest task.

What tasks do you have in mind?

>>> Actually, if your lexical environment system has a new-env function 
>>> to create an empty environment (or a binding to an empty environment 
>>> in the dynamic/global environment), you can use that, let forms, and 
>>> evaluation-in-given-environment to build the struct and object system.
>>>
>>> ;Assuming blithely for the moment that a class is just a list of slot 
>>> names stored as symbols.
>>> (defun allocate-slots (slots)
>>>   (eval
>>>     `(let ,(mapcar list slots)
>>>       (current-env))
>>>     (new-env)))
>>
>> I don't see how this helps you (or what this helps you with).
>>
>>
>> Pascal
>>
> Remember the bit above where I defined a macro as an evaluation of the 
> body form in the caller's environment?  In CL, macros are both 
> second-class citizens and have to be built into the language.  In my 
> Lisp, macros are first-class and are defined as special case of a 
> function.  Will you consider that, at least, an increase in expressive 
> power?

Yes, it is an increase in expressive power, but it comes at a cost. 
Basically, your language becomes mostly not compilable anymore. Since 
you don't know what a first-class macro will do to some piece of code, 
you cannot compile that piece of code anymore, but you have to defer 
this to runtime.

> Here's a version of Peter Seibel's "doprimes" macro (from PCL chapter 8) 
> that requires absolutely no gensyms because of how macros work in my Lisp:
>> (defmacro doprimes (var-start-end &rest body)
>>   (let ((var (car var-start-end)) (start (eval (cadr var-start-end) 
>> (caller-env))) (end (eval (caddr var-start-end) (caller-env))))
>>     `(do ((,var (next-prime ,start) (next-prime (+1 ,var))))
>>          ((> ,var ,end))
>>        ,@body)))
> Note how there's no need for either gensym or the ending-value variable. 
>  The macro is called at runtime, and can thus evaluate both start and 
> end in the appropriate order /outside the quasiquote expression/.  This 
> means the do loop and body never see the start or end bindings, thus 
> doing away with gensyms.
> 
> Sorry about the argument list, though.  I haven't taught the thing to 
> deconstruct lists quite yet.

Check out literature on reflection and especially 3-Lisp - they 
basically already had such a model. If you can, grab a copy of the book 
"Meta-Level Architectures and Reflection" by Maes & Nardi, it has an 
excellent overview article by Jim des Rivieres about these things.

Basically, 3-Lisp defines an nlambda form that takes unevaluated 
arguments as s-expressions, the environment in which the function was 
called and a continuation. With this you can implement all kinds of 
control structures. An if-statement would look like this:

(define if (nlambda (args env cont)
              (cont (cond ((eval (first args) env)
                           (eval (second args) env))
                          (t (eval (third args) env))))))

[Don't rely on the syntactic details here, I am reconstructing this 
without having the book at hand.]


I am not sure what this all buys you - there are already quite decent 
reflective features in Common Lisp which can be implemented very 
efficiently at the same time. Just my 0.02�.


Pascal


-- 
3rd European Lisp Workshop
July 3-4 - Nantes, France - co-located with ECOOP 2006
http://lisp-ecoop06.bknr.net/
From: Eli Gottlieb
Subject: Re: Foreign Function Interfaces
Date: 
Message-ID: <2Ht5g.17292$ZQ3.14826@twister.nyroc.rr.com>
Pascal Costanza wrote:
> I am not sure what this all buys you - there are already quite decent 
> reflective features in Common Lisp which can be implemented very 
> efficiently at the same time. Just my 0.02�.
> 
> 
> Pascal
> 
> 
Are these reflective features of a Common Lisp /implementation/ or 
reflective features of Common Lisp /the language/?

-- 
The science of economics is the cleverest proof of free will yet 
constructed.
From: Pascal Costanza
Subject: Re: Foreign Function Interfaces
Date: 
Message-ID: <4c5vgmF14h2s2U1@individual.net>
Eli Gottlieb wrote:
> Pascal Costanza wrote:
>> I am not sure what this all buys you - there are already quite decent 
>> reflective features in Common Lisp which can be implemented very 
>> efficiently at the same time. Just my 0.02�.
>>
>> Pascal
>>
> Are these reflective features of a Common Lisp /implementation/ or 
> reflective features of Common Lisp /the language/?

It's hard to answer this question since you haven't responded to my 
question what the tasks are that you have in mind. (or I have missed 
your response)

Some of the reflective features are already part of the language 
specification, some are semi-standard and some are implementation-specific.


Pascal

-- 
3rd European Lisp Workshop
July 3-4 - Nantes, France - co-located with ECOOP 2006
http://lisp-ecoop06.bknr.net/
From: Joerg Hoehle
Subject: Re: Foreign Function Interfaces
Date: 
Message-ID: <uodyd3ajh.fsf@users.sourceforge.net>
Eli Gottlieb <···········@gmail.com> writes:

> First-class lexical 
> environments allow lookup of any variable that environment was able to 
> see, without having to know what it was/is ahead of time.

That is at odds with many an optimisation that typical compilers do:
 + prove that a variable's value has so limited lifetime that it can
   be put to a register
 + prove that scope is limited so the storage cell can be reused for
   another object

Providing first class environment to be able to MODIFY variables looks
like gcc -O0 = disable all optimizations.  Then play with gdb.
In CLISP, this translates to: "use the interpreter, not the compiler."

However, many people want a compiler.  Are they all fools looking for
a false graal called "performance"?


> requires absolutely no gensyms because of how macros work in my Lisp:
> > (defmacro doprimes (var-start-end &rest body)
> >   (let ((var (car var-start-end)) (start (eval (cadr var-start-end) (caller-env))) (end (eval (caddr var-start-end) (caller-env))))
> >     `(do ((,var (next-prime ,start) (next-prime (+1 ,var))))
> >          ((> ,var ,end))
> >        ,@body)))
> Note how there's no need for either gensym or the ending-value variable. 

In my perception, GENSYM is a good enough solution to variable capture
on a historic path that lead to lexical scoping and compiler optimizations.

Your introducing EVAL is anti-news.  News taken backwards.
For a humorous example, read Emacs' ANTINEWS file (found in every distro).
E.g. "Removed the garbage collector because nobody understood it" :-)
EVAL is precisely what Lispers went away from, thirty years ago
already, for most uses.
Your work looks to me like a proof that history goes in circles.

Yet maybe there's a niche market for "simple Lisps"?

Regards,
	Jorg Hohle
Telekom/T-Systems Technology Center
From: Eli Gottlieb
Subject: Re: Foreign Function Interfaces
Date: 
Message-ID: <WOu6g.22877$ZQ3.15221@twister.nyroc.rr.com>
Joerg Hoehle wrote:
> Eli Gottlieb <···········@gmail.com> writes:
> 
> 
>>First-class lexical 
>>environments allow lookup of any variable that environment was able to 
>>see, without having to know what it was/is ahead of time.
> 
> 
> That is at odds with many an optimisation that typical compilers do:
>  + prove that a variable's value has so limited lifetime that it can
>    be put to a register
>  + prove that scope is limited so the storage cell can be reused for
>    another object
> 
> Providing first class environment to be able to MODIFY variables looks
> like gcc -O0 = disable all optimizations.  Then play with gdb.
> In CLISP, this translates to: "use the interpreter, not the compiler."
> 
> However, many people want a compiler.  Are they all fools looking for
> a false grail called "performance"?
> 

No, they are not fools to desire performance.  I'm just not designing 
for them, I'm designing for a guy who wants to sit at his machine and 
hack, rather than write Yet Another Brilliant Web Application.  If you 
want a dialect for YABWA, go nag Paul Graham.

> In my perception, GENSYM is a good enough solution to variable capture
> on a historic path that lead to lexical scoping and compiler optimizations.
> 
> Your introducing EVAL is anti-news.  News taken backwards.
> For a humorous example, read Emacs' ANTINEWS file (found in every distro).
> E.g. "Removed the garbage collector because nobody understood it" :-)
> EVAL is precisely what Lispers went away from, thirty years ago
> already, for most uses.
> Your work looks to me like a proof that history goes in circles.

Precisely what necessitates adding things to the language *just* to get 
around ever (horror of horrors!) calling eval?

> 
> Yet maybe there's a niche market for "simple Lisps"?
> 
> Regards,
> 	Jorg Hohle
> Telekom/T-Systems Technology Center
Market?  I'm supposed to be oriented towards a market now?

-- 
The science of economics is the cleverest proof of free will yet 
constructed.
From: Ari Johnson
Subject: Re: Foreign Function Interfaces
Date: 
Message-ID: <m2aca65m7d.fsf@hermes.theari.com>
Eli Gottlieb <···········@gmail.com> writes:

> Also, it appears I made the same mistake you did.  Oh, well.  I don't
> see a way to implement first-class environments with the CL method,
> anyway.

Speaking of making the same mistake that I did, if you'd like a copy
of my Lisp system let me know.  It sounds like you're already far
beyond anything I did with it, but the offer's there if you'd like it.
From: Eli Gottlieb
Subject: Re: Foreign Function Interfaces
Date: 
Message-ID: <%5p4g.4500$TT.1256@twister.nyroc.rr.com>
Ari Johnson wrote:
> Eli Gottlieb <···········@gmail.com> writes:
> 
> 
>>Also, it appears I made the same mistake you did.  Oh, well.  I don't
>>see a way to implement first-class environments with the CL method,
>>anyway.
> 
> 
> Speaking of making the same mistake that I did, if you'd like a copy
> of my Lisp system let me know.  It sounds like you're already far
> beyond anything I did with it, but the offer's there if you'd like it.
How far did you get along with it?  Your previous post stated that for 
writing autopilot programs it was extremely successful!

-- 
The science of economics is the cleverest proof of free will yet 
constructed.
From: Ari Johnson
Subject: Re: Foreign Function Interfaces
Date: 
Message-ID: <m2vest4wni.fsf@hermes.theari.com>
Eli Gottlieb <···········@gmail.com> writes:

> Ari Johnson wrote:
>> Eli Gottlieb <···········@gmail.com> writes:
>> 
>>>Also, it appears I made the same mistake you did.  Oh, well.  I don't
>>>see a way to implement first-class environments with the CL method,
>>>anyway.
>> Speaking of making the same mistake that I did, if you'd like a copy
>> of my Lisp system let me know.  It sounds like you're already far
>> beyond anything I did with it, but the offer's there if you'd like it.
> How far did you get along with it?  Your previous post stated that for
> writing autopilot programs it was extremely successful!

It's very workable and, other than adding a bytecode compiler, somehow
making it thread-safe, adding data types[1], or a couple of other
improvements, I can't think of how to make it more useful for the
purposes it serves.

The system it's plugged into adds a few data types and quite a few
procedures to make it all work.  But it's a fairly decent minimalist
scripting/extension language for places you want to have one but don't
want to give its users dangerous powers like being able to open files
on disk and so forth (which is why I didn't use Guile or even Ruby for
this purpose).

E-mail me if you're interested in a copy.  It's only about 4450 lines
of C.

[1] - It has int, float, symbol, string, vector, procedure (coded in
C), macro (coded in C), closure (coded in lisp), usermacro (coded in
lisp), error (throw your own), stream (with no way to make a new one
in lisp - but only because I deliberately did not provide functions
for that), and space for 2^29 user-defined types - it could stand to
add a bignum type and structs or OOP.