Re: Designing Lisp from scratch

[email protected] Sun, 18 Mar 2007 22:30:59 EDT
Newsgroups gmane.comp.lang.lightweight
Message-ID <[email protected]>
 I'm happy that you brought these things up, as  it can gradually help me 
sharpen my explanations in case I later want to write a  formal paper about it.  
And it can help me see what might be missing in  what I've done.  
 
 
 

I was hoping to checkmark each item you mentioned, but it turned out to be  
more than I could chew in one sitting.  I'm not a native Scheme / Lisp /  
functional language programmer.  I'll have to spend more time mulling over  some of 
those ideas.  In any event, let me comment on what I can for  now.
 
First though, some background info.  What I implemented was a version  of 
Common Lisp, which I constructed gradually as I read through Colin Allen's  Lisp 
Primer tutorial found online at mypage.iu.edu/~colallen/lp (I included  much, 
but not everything there).  I had previously read through other Lisp  
documentation, which I also used as reference.  I used the GNU Common Lisp  
interpreter to compare results with my interpreter. 
 
Why did I choose CL instead of Scheme?  Well had I done Scheme, the  question 
might have been why I implemented Scheme instead of CL.  I  probably chose CL 
because I found better tutorials for it, and figured that  there might be 
more CL practitioners than Schemers.  Perhaps with the  exception of 
continuations, I think the differences between the two dialects are  superficial enough 
that anyone can easily modify my CL implementation and turn  it into Scheme.  
Scheme being minimalist and smaller than CL, I'd imagine  that it might actually 
be even easier to implement than CL.
 
There are various possible ways you could implement Lisp with uCalc.   
However, I've chosen a way that would be easiest for me to quickly implement,  and 
easy for users unfamiliar with uCalc to follow.  Efficiency and  optimizations 
were the very least of my concerns (though you wouldn't be able to  tell if 
you're only running snippets of code like those found in  tutorials).  On the 
other hand my Basic implementation is more efficient,  but I had to write a 
separate file with a line-by-line explanation of the code  to help people better 
understand it.
 
The Language Builder is designed to be capable of executing code at maximal  
speed.  However, the actual language design implementations and  optimizations 
are left to the programmer.
 
> - LISP-style macro programming
 
This one is directly supported in my Lisp implementation.  In fact,  though 
this might seem like one of the more challenging constructs, it turned  out to 
be a very straightforward thing to implement.
 
Notice that I said it's supported by my implementation of Lisp.  The  
Language Builder itself does not support LISP-style macro programming.  Nor  does it 
support S-expressions, higher order functions, anonymous lambda  functions, 
etc...  It only provides you with the building blocks that you  can easily put 
together to construct such abstractions.
 
> - generic programming
 
Directly supported.  Looking this up in Wikipedia, I found there might  be 
several variants of meaning attached to this expression.  So I'll  discuss 
several different ways in which I think uCalc supports generic  programming.
 
It mentions how you can create new Forth compiler keywords and  
implementations on the fly.  I have a Forth implementation.  And the  whole Forth language, 
including the "compiler keywords" (though mine is  interpreted), is defined 
on the fly. You can likewise continue to implement new  keywords, either using 
the conventional Forth syntax, now that the language is  defined, or using the 
same language builder methods that were used to create  Forth (all still done 
on the fly).
 
An example in Wikipedia is given of a template that swaps two variables of  
any type that are passed by reference.  As mentioned before, the language  
builder doesn't have any "built-in" functions.  But I have a library of  common 
methods to pick from so that you don't necessarily have to start from  scratch.  
One library method ("template") allows you to assign a value to a  variable, 
without knowing in advance what kind of type the variable has.   The variable 
argument is not passed by "reference" but by "handle".  With a  handle, not 
just the variable's address, but also everything else associated  with it is 
accessible (its name, datatype etc...).  This "template" doesn't  know how to 
actually assign a value.  When you define a data type, you tell  that type how to 
assign data to it.  So the variable assignment method  simply relies on the 
data assignment code that was defined for the given data  type.
 
Something somewhat similar to the array example can be done as well.   For 
instance there's a uCalc "template" (again not "built-in" but defined in a  
plain text code file) for defining arrays (I didn't include arrays in Lisp  
though).  This will work with almost any data type.
 
Parametric polymorphism is possible in this way:  When you define a  data 
type, you define how it allocates, stores, retrieves data, etc... Your  routine 
will call the appropriate method for the data type of the argument  without 
having to know the details of how that method is implemented.  Type  safety can 
be automatically enforced (or suppressed).
 
>- functional reactive programming
 
I looked at a paper by Ignatoff, Cooper, and Krishnamurthi, regarding  
Functional Reactive languages, which also talks about FrTime.  I got a  sense that 
it was a great challenge to expand a language like Scheme beyond its  normal 
syntactic boundaries to make it support abstractions for dealing with  values 
that change over time.  I may completely be missing the boat, but  from examples 
like the ones dealing with seconds, it looked like it would not  require any 
special effort at all to implement this in uCalc.  That's  because uCalc does 
not start with a Scheme syntax, or imperative style, or any  particular 
paradigm.  It does not favor one style over another.  The  result is that it's very 
easy to mix-and-match various paradigms that normally  wouldn't be found in 
the same language.
 
>- meta object protocols
 
This may not be exactly the same, but everything that you can define in  
uCalc has a handle.  And each item with a handle has properties that you  can 
inspect, and in many cases change.  Depending on the type item, the  properties 
might for instance be the item's name, value, address, data type,  syntax, 
related items, thread, etc...
 
>- tail call optimization
 
I didn't find a way to implement this yet.  However, I suspect that if  I do, 
it will not involve changing anything in the Language Builder  itself.  
Instead it would simply involve finding the right end-user code to  do it.

>- continuations
 
I did not fully grasp the concept of continuations yet.  It seems kind  of 
complicated and esoteric to me.  But I suspect that if I do finally get  it, it 
would also involve applying the right code instead of modifying  uCalc.  And 
of course, anyone reading this is welcome to download uCalc to  see if they 
could figure out a way to implement continuations.
 
Daniel  Corbier
uCalc Language Builder
www.ucalc.com

 
In a message dated 3/13/07 6:36:38 PM Eastern Standard Time,  
[email protected] writes:

>  What do you guys think of this idea?

It depends on the  details but in general I'm always in favor of
general purpose rather than  special purpose tools.  However, some
language concepts are harder to  capture than others, and if they are
not built-in at the fundamental level,  it may not be possible to
implement them later efficiently.  Examples:  Does your system directly
support or indirectly allow:

- tail call  optimization
- continuations
- meta object protocols
- functional  reactive programming
- generic programming
- LISP-style macro  programming

If your system doesn't support efficiently  implementing these
capabilities then it is not fully general purpose.   Many people might
not care, but these are all areas of great interest to me  personally,
so for example I could not use a language building tool that  did not
support them.  I suspect many people on this list would feel  similarly
and not be interested until / unless some of these advanced  features
become available.

A good rule of thumb is,  can you implement Scheme, as opposed to just
LISP?  A system that is  the equal or a superset of Scheme's basic
features is interesting, and a  system with less than that is not so
interesting.  I speak only for  language geeks -- the rest of the world
may have much use for systems that  have capabilities similar to LISP;
see Python, Perl & JavaScript for  successful examples of that.

CLOS, the LISP macro system,  and FrTime are also interesting tests.  A
system that can implement  any of those also gets an "A"  for
capability.









************************************** AOL now offers free email to everyone. 
 Find out more about what's free from AOL at http://www.aol.com.