From: Blake McBride
Subject: Program which converts Common Lisp into a LISP1 Lisp
Date: 
Message-ID: <13nlsh6l6c05hd4@news.supernews.com>
Lisp1 is an ANSI Common Lisp program I wrote that makes Common Lisp 
systems operate as LISP1 Lisp dialects with virtually no overhead. 
LISP1 means that functions are treated just like variable values.  They 
can be assigned to, passed around, and localized just like variables. 
No special functions or added complexity is needed.  (Scheme is a LISP1 
Lisp.)  The underlying lisp compiler and saving of lisp images and 
executables is retained.

It has been tested with CLISP and SBCL.

Get it at:  http://blake.mcbride.name

Blake McBride
·····@mcbride.name

From: Pascal Costanza
Subject: Re: Program which converts Common Lisp into a LISP1 Lisp
Date: 
Message-ID: <5u18rmF1g1sueU1@mid.individual.net>
Blake McBride wrote:
> 
> Lisp1 is an ANSI Common Lisp program I wrote that makes Common Lisp 
> systems operate as LISP1 Lisp dialects with virtually no overhead. LISP1 
> means that functions are treated just like variable values.  They can be 
> assigned to, passed around, and localized just like variables. No 
> special functions or added complexity is needed.  (Scheme is a LISP1 
> Lisp.)  The underlying lisp compiler and saving of lisp images and 
> executables is retained.
> 
> It has been tested with CLISP and SBCL.
> 
> Get it at:  http://blake.mcbride.name

You're implementing this as a separate evaluator / compiler. That's too 
complicated and not necessary, you can also embed this idea by providing 
a bunch of macros.

The rough idea is this:

(defmacro defglobal (name value)
   (let ((internal-name (copy-symbol name))) ; this can be improved
     `(progn
        (defvar ,internal-name ,value)
        (define-symbol-macro ,name ,internal-name))))

(defmacro defun1 (name (&rest lambda-list) &body body)
   `(progn
      (defglobal ,name (lambda ,lambda-list ,@body))
      (defmacro ,name (&rest args)
        `(funcall ,',name ,@args))))

This is untested, but I used this kind of technique successfully in one 
of my unpublished experiments.


Pascal

-- 
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Blake McBride
Subject: Re: Program which converts Common Lisp into a LISP1 Lisp
Date: 
Message-ID: <477C4060.4040105@mcbride.name>
Pascal Costanza wrote:
> Blake McBride wrote:
>>
>> Lisp1 is an ANSI Common Lisp program I wrote that makes Common Lisp 
>> systems operate as LISP1 Lisp dialects with virtually no overhead. 
>> LISP1 means that functions are treated just like variable values.  
>> They can be assigned to, passed around, and localized just like 
>> variables. No special functions or added complexity is needed.  
>> (Scheme is a LISP1 Lisp.)  The underlying lisp compiler and saving of 
>> lisp images and executables is retained.
>>
>> It has been tested with CLISP and SBCL.
>>
>> Get it at:  http://blake.mcbride.name
> 
> You're implementing this as a separate evaluator / compiler. That's too 
> complicated and not necessary, you can also embed this idea by providing 
> a bunch of macros.
> 
> The rough idea is this:
> 
> (defmacro defglobal (name value)
>   (let ((internal-name (copy-symbol name))) ; this can be improved
>     `(progn
>        (defvar ,internal-name ,value)
>        (define-symbol-macro ,name ,internal-name))))
> 
> (defmacro defun1 (name (&rest lambda-list) &body body)
>   `(progn
>      (defglobal ,name (lambda ,lambda-list ,@body))
>      (defmacro ,name (&rest args)
>        `(funcall ,',name ,@args))))
> 
> This is untested, but I used this kind of technique successfully in one 
> of my unpublished experiments.
> 
> 
> Pascal
> 


I see what you are doing but I can't see why it would be better.  Your 
approach has a bunch of problems that would require a lot of code to 
fix.  In the end, I think you'd end up with a bigger and more convoluted 
  system.

For example:

With what you've show you couldn't do the following:

(defun1 abc (a b)
     (+ a b))

(setq def abc)

(def 5 6)

without making setq more complex.  Nor could you do:

(let ((a 5)
      (b 6)
      (fun (lambda (a b) (+ a b))))
     (fun a b))

without making let more complicated.  The problems go on and on.

My system handles all of this and it's pretty small (< 3K).

Blake McBride
From: Pascal Costanza
Subject: Re: Program which converts Common Lisp into a LISP1 Lisp
Date: 
Message-ID: <5u3p7jF1fnivmU1@mid.individual.net>
Blake McBride wrote:
> Pascal Costanza wrote:
>> Blake McBride wrote:
>>>
>>> Lisp1 is an ANSI Common Lisp program I wrote that makes Common Lisp 
>>> systems operate as LISP1 Lisp dialects with virtually no overhead. 
>>> LISP1 means that functions are treated just like variable values.  
>>> They can be assigned to, passed around, and localized just like 
>>> variables. No special functions or added complexity is needed.  
>>> (Scheme is a LISP1 Lisp.)  The underlying lisp compiler and saving of 
>>> lisp images and executables is retained.
>>>
>>> It has been tested with CLISP and SBCL.
>>>
>>> Get it at:  http://blake.mcbride.name
>>
>> You're implementing this as a separate evaluator / compiler. That's 
>> too complicated and not necessary, you can also embed this idea by 
>> providing a bunch of macros.
>>
>> The rough idea is this:
>>
>> (defmacro defglobal (name value)
>>   (let ((internal-name (copy-symbol name))) ; this can be improved
>>     `(progn
>>        (defvar ,internal-name ,value)
>>        (define-symbol-macro ,name ,internal-name))))
>>
>> (defmacro defun1 (name (&rest lambda-list) &body body)
>>   `(progn
>>      (defglobal ,name (lambda ,lambda-list ,@body))
>>      (defmacro ,name (&rest args)
>>        `(funcall ,',name ,@args))))
>>
>> This is untested, but I used this kind of technique successfully in 
>> one of my unpublished experiments.
>>
>>
>> Pascal
>>
> 
> 
> I see what you are doing but I can't see why it would be better.  Your 
> approach has a bunch of problems that would require a lot of code to 
> fix.  In the end, I think you'd end up with a bigger and more convoluted 
>  system.
> 
> For example:
> 
> With what you've show you couldn't do the following:
> 
> (defun1 abc (a b)
>     (+ a b))
> 
> (setq def abc)
> 
> (def 5 6)
> 
> without making setq more complex.  Nor could you do:
> 
> (let ((a 5)
>      (b 6)
>      (fun (lambda (a b) (+ a b))))
>     (fun a b))
> 
> without making let more complicated.  The problems go on and on.

You're right, but I think you're drawing the wrong conclusions.

Sidenote: 'setq shouldn't introduce a new binding, but only update an 
existing one. You would need a way to announce the variable 'def.

(defmacro define (name value)
   `(progn
      (defglobal ,name ,value)
      (defmacro ,name (&rest args)
        `(funcall ,',name ,@args))))

(define def nil)

(setq def abc)

(def 5 6)

'define is probably the better general defining form than 'defun1.

For 'let, you indeed need your own version, but that's also pretty 
straightforward:

(defmacro let1 ((&rest bindings) &body body)
   `(macrolet ,(loop for (name) in bindings
                     collect `(,name (&rest args)
                                 `(funcall ,',name ,@args)))
      (let ,bindings ,@body)))

> My system handles all of this and it's pretty small (< 3K).

You're implementing your own evaluator. In other words, you're 
implementing a new language. In case that language catches on, you 
sooner or later want to include a foreign function interface to the host 
language, and then you will have the same problems. It may actually be 
worse, because you probably need to add additional machinery for 
handling callbacks.

What I suggest is an embedding in the host language. A foreign function 
interface is then trivial. You 'only' have to be aware of the Lisp-2 
nature of the host language. Defining a 'foreign' function interface to 
an existing Common Lisp function boils down to storing the Common Lisp 
definition in a variable of the embedded Lisp-1 language, roughly like this:

(define + #'cl:+)

[Given the right shadowing of Common Lisp symbols.]


BTW, your approach is very similar to that of Pseudoscheme, as far as I 
can tell.


Pascal

-- 
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Blake McBride
Subject: Re: Program which converts Common Lisp into a LISP1 Lisp
Date: 
Message-ID: <13nprp890dqgqfb@news.supernews.com>
Pascal Costanza wrote:
> 
> 
> BTW, your approach is very similar to that of Pseudoscheme, as far as I 
> can tell.
> 
> 

Perhaps, but I am not interested here in Scheme or mimicking Scheme. 
There are several things I prefer about Common Lisp over Scheme which I 
want to retain (CLOS, packages, ample library, macro system, and the 
fact that nil is treated as false).  The only big think I like about 
Scheme is its LISP1 semantics.  Is we see, there are several ways to 
give CL LISP1 semantics.

I need to think about your approach a little more before I respond further.

Thanks for your input.

Blake McBride
From: Blake McBride
Subject: Re: Program which converts Common Lisp into a LISP1 Lisp
Date: 
Message-ID: <13nslvvfn3b5740@news.supernews.com>
Okay, here is a major flaw with what you are proposing.  Again this is 
something my system can handle.  There are aspects of your system that I 
like, I just can't seem to make the idea actually work.  I also have 
some comments regarding one of your functions.

Your system can't handle:

(defun1 abc (a b)
     (+ a b))

(defun1 def (fun arg)
     (fun arg 55))

(def abc 5)

I don't know how you could fix that with a simple macro.

Another thing.  Your macro:

(defmacro let1 ((&rest bindings) &body body)
   `(macrolet ,(loop for (name) in bindings
                     collect `(,name (&rest args)
                                 `(funcall ,',name ,@args)))
      (let ,bindings ,@body)))

seems like it would really slow the system down because your are doing 
the macrolet for every let variable.  Isn't this being done at runtime? 
  I think this would have a lot of overhead not experienced with my system.

I look forward to your response.

Blake McBride
From: Ron Garret
Subject: Re: Program which converts Common Lisp into a LISP1 Lisp
Date: 
Message-ID: <rNOSPAMon-451D76.09195604012008@news.gha.chartermi.net>
In article <···············@news.supernews.com>,
 Blake McBride <·····@mcbride.name> wrote:

> Okay, here is a major flaw with what you are proposing.  Again this is 
> something my system can handle.  There are aspects of your system that I 
> like, I just can't seem to make the idea actually work.  I also have 
> some comments regarding one of your functions.
> 
> Your system can't handle:
> 
> (defun1 abc (a b)
>      (+ a b))
> 
> (defun1 def (fun arg)
>      (fun arg 55))
> 
> (def abc 5)
> 
> I don't know how you could fix that with a simple macro.

(defmacro defun1 (name args &body body)
  `(progn
     (defun ,name ,args
       (flet ,(mapcar (lambda (arg)
                         `(,arg (&rest args) (apply ,arg args)))
                      args)
         ,@body))
     (defvar ,name #',name)))

rg
From: Michael Weber
Subject: Re: Program which converts Common Lisp into a LISP1 Lisp
Date: 
Message-ID: <7e1a193f-02ab-4beb-8f5b-7d0fbcde8f4e@21g2000hsj.googlegroups.com>
On Jan 4, 6:19 pm, Ron Garret <·········@flownet.com> wrote:
> In article <···············@news.supernews.com>,
>  Blake McBride <·····@mcbride.name> wrote:
> > Your system can't handle:
>
> > (defun1 abc (a b)
> >      (+ a b))
>
> > (defun1 def (fun arg)
> >      (fun arg 55))
>
> > (def abc 5)
>
> > I don't know how you could fix that with a simple macro.

(defmacro with-lisp1-names ((&rest binding-names) &body body)
  `(macrolet ,(loop for name in binding-names
                    collect `(,name (&rest args)
                                    `(funcall ,',name ,@args)))
     ,@body))

(defmacro lambda1 ((&rest args) &body body)
  `(with-lisp1-names ,args
     (lambda ,args ,@body)))

(defmacro defun1 (name args &body body)
  `(define ,name (lambda1 ,args ,@body)))

; Homework: rewrite LET1 and the remaining binding forms with WITH-
LISP1-NAMES.

Compared to Ron's version, DEFUN1 does less work at run-time.  Plus,
it is trivially based on DEFINE, as expected. Contrary to what Blake
asserted, macrolets happen at macro-expansion time, and not run-time.
With the above definition of DEF, a compiler sees something like:

(PROGN
  (DEFVAR #:DEF (LAMBDA (FUN ARG) (FUNCALL FUN ARG 55)))
  (DEFINE-SYMBOL-MACRO DEF #:DEF)
  (DEFMACRO DEF (&REST ARGS) `(FUNCALL #:DEF ,@ARGS)))

What does not work is ((lambda1 (x) (1+ x)) 0), and I see no easy way
to repair that, except with a code walker.


Cheers,
Michael
From: Ron Garret
Subject: Re: Program which converts Common Lisp into a LISP1 Lisp
Date: 
Message-ID: <rNOSPAMon-AB468A.17272504012008@news.gha.chartermi.net>
In article 
<····································@21g2000hsj.googlegroups.com>,
 Michael Weber <·········@foldr.org> wrote:

> On Jan 4, 6:19�pm, Ron Garret <·········@flownet.com> wrote:
> > In article <···············@news.supernews.com>,
> > �Blake McBride <·····@mcbride.name> wrote:
> > > Your system can't handle:
> >
> > > (defun1 abc (a b)
> > > � � �(+ a b))
> >
> > > (defun1 def (fun arg)
> > > � � �(fun arg 55))
> >
> > > (def abc 5)
> >
> > > I don't know how you could fix that with a simple macro.
> 
> (defmacro with-lisp1-names ((&rest binding-names) &body body)
>   `(macrolet ,(loop for name in binding-names
>                     collect `(,name (&rest args)
>                                     `(funcall ,',name ,@args)))
>      ,@body))
> 
> (defmacro lambda1 ((&rest args) &body body)
>   `(with-lisp1-names ,args
>      (lambda ,args ,@body)))
> 
> (defmacro defun1 (name args &body body)
>   `(define ,name (lambda1 ,args ,@body)))
> 
> ; Homework: rewrite LET1 and the remaining binding forms with WITH-
> LISP1-NAMES.
> 
> Compared to Ron's version, DEFUN1 does less work at run-time.  Plus,
> it is trivially based on DEFINE, as expected. Contrary to what Blake
> asserted, macrolets happen at macro-expansion time, and not run-time.
> With the above definition of DEF, a compiler sees something like:
> 
> (PROGN
>   (DEFVAR #:DEF (LAMBDA (FUN ARG) (FUNCALL FUN ARG 55)))
>   (DEFINE-SYMBOL-MACRO DEF #:DEF)
>   (DEFMACRO DEF (&REST ARGS) `(FUNCALL #:DEF ,@ARGS)))
> 
> What does not work is ((lambda1 (x) (1+ x)) 0), and I see no easy way
> to repair that, except with a code walker.

Welcome to Clozure Common Lisp Version 1.1-r7902 (DarwinX8664)!
? ((lambda (x) (1+ x)) 0)
1
? 

;-)

Of course, you can always hack the implementation.  Take a look at:

http://www.flownet.com/ron/lisp/nx1-combination-hook.lisp

or for SBCL:

http://www.flownet.com/ron/lisp/ir1-combination-hook.lisp

(You'll also need:

(defmacro combination-hook (&rest stuff) `(funcall ,@stuff))

I have a CLisp version lying around somewhere if anyone is interested.

rg
From: Pascal Costanza
Subject: Re: Program which converts Common Lisp into a LISP1 Lisp
Date: 
Message-ID: <5ud37uF1hglmuU1@mid.individual.net>
Blake McBride wrote:
> 
> Okay, here is a major flaw with what you are proposing.  Again this is 
> something my system can handle.  There are aspects of your system that I 
> like, I just can't seem to make the idea actually work.  I also have 
> some comments regarding one of your functions.
> 
> Your system can't handle:
> 
> (defun1 abc (a b)
>     (+ a b))
> 
> (defun1 def (fun arg)
>     (fun arg 55))
> 
> (def abc 5)
> 
> I don't know how you could fix that with a simple macro.

Indeed, you can't fix that with a simple macro, but you need a code 
walker for that. However, see 
http://groups.google.be/group/comp.lang.lisp/msg/8fce6ead716e6501

That version may or may have bugs. If it has bugs, I think I have fixed 
them in a later version. Nevertheless, the principle should be clear: 
It's a code walker that's integrated into Common Lisp via *macroexpand-hook*

Code walkers are not portable in general, so they have similar drawbacks 
as languages implemented as separate interpreters or compilers. (They 
are 'just' new languages.)

> Another thing.  Your macro:
> 
> (defmacro let1 ((&rest bindings) &body body)
>   `(macrolet ,(loop for (name) in bindings
>                     collect `(,name (&rest args)
>                                 `(funcall ,',name ,@args)))
>      (let ,bindings ,@body)))
> 
> seems like it would really slow the system down because your are doing 
> the macrolet for every let variable.  Isn't this being done at runtime? 
>  I think this would have a lot of overhead not experienced with my system.
> 
> I look forward to your response.

In interpreted Common Lisp systems, they may (!) be expanded at runtime, 
and then over and over again, but in compiled Common Lisp systems, it's 
guaranteed that all macro invocations are expanded at compile time.


Pascal

-- 
1st European Lisp Symposium (ELS'08)
http://prog.vub.ac.be/~pcostanza/els08/

My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Pascal Costanza
Subject: Re: Program which converts Common Lisp into a LISP1 Lisp
Date: 
Message-ID: <5ue62jF1hainpU1@mid.individual.net>
Pascal Costanza wrote:
> Blake McBride wrote:
>>
>> Okay, here is a major flaw with what you are proposing.  Again this is 
>> something my system can handle.  There are aspects of your system that 
>> I like, I just can't seem to make the idea actually work.  I also have 
>> some comments regarding one of your functions.
>>
>> Your system can't handle:
>>
>> (defun1 abc (a b)
>>     (+ a b))
>>
>> (defun1 def (fun arg)
>>     (fun arg 55))
>>
>> (def abc 5)
>>
>> I don't know how you could fix that with a simple macro.
> 
> Indeed, you can't fix that with a simple macro, but you need a code 
> walker for that. However, see 
> http://groups.google.be/group/comp.lang.lisp/msg/8fce6ead716e6501

Argh, to be more precise: That specific case may be possible to be 
handled with a simple macro, but forms like (((f ...) ...) ...) not. 
It's the latter kind of forms for which you need a code walker.


Pascal

-- 
1st European Lisp Symposium (ELS'08)
http://prog.vub.ac.be/~pcostanza/els08/

My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Ron Garret
Subject: Re: Program which converts Common Lisp into a LISP1 Lisp
Date: 
Message-ID: <rNOSPAMon-47D840.08285607012008@news.gha.chartermi.net>
In article <···············@mid.individual.net>,
 Pascal Costanza <··@p-cos.net> wrote:

> Pascal Costanza wrote:
> > Blake McBride wrote:
> >>
> >> Okay, here is a major flaw with what you are proposing.  Again this is 
> >> something my system can handle.  There are aspects of your system that 
> >> I like, I just can't seem to make the idea actually work.  I also have 
> >> some comments regarding one of your functions.
> >>
> >> Your system can't handle:
> >>
> >> (defun1 abc (a b)
> >>     (+ a b))
> >>
> >> (defun1 def (fun arg)
> >>     (fun arg 55))
> >>
> >> (def abc 5)
> >>
> >> I don't know how you could fix that with a simple macro.
> > 
> > Indeed, you can't fix that with a simple macro, but you need a code 
> > walker for that. However, see 
> > http://groups.google.be/group/comp.lang.lisp/msg/8fce6ead716e6501
> 
> Argh, to be more precise: That specific case may be possible to be 
> handled with a simple macro, but forms like (((f ...) ...) ...) not. 
> It's the latter kind of forms for which you need a code walker.

Or a change to the implementation.

rg