[erlang-questions] Lisp syntax for Erlang

YC yinso.chen@REDACTED
Wed Dec 5 21:03:16 CET 2007


On Dec 4, 2007 6:33 PM, Robert Virding <rvirding@REDACTED> wrote:

> I have tried to be clear, but obviously not succeeded. I am going to do a
> lisp syntax for Erlang, not implement CL or Scheme which, by the way, is
> *very* difficult on the BEAM today. That is the main problem as I have to
> invent lisp constructions which match into Erlang.
>
> What I want is something which *is* lisp even though it a lisp which has
> been designed to work seamlessly together with *normal* Erlang. So it is
> more than just wrapping ( ... ) around expressions after converting them
> into prefix form. So, for example, there are no syntactic variables, you
> quote things which you don't want to evaluate. So to comment some of you
> examples:
>

Sorry - my turn of being unclear - to me a lispy syntax for erlang is *not
necessarily* a lisp, and hence why I made the distinction.  I know you are
not implementing CL or Scheme, hence I raise the point of either following
erlang's design or leverage their (CL or scheme's) designs (which you mostly
have done except a few places).  But fair enough - you want a lisp that
compiles to erlang.

%% Erlang => ErlangInLisp
> > A + 1, => (+ A 1)
> > A = 5. => (= A 5).
> >
>
> This will become a (let ((a  5)) ... ). Let will be extended to match
>

I like the (let ...) form as well.  I did find I write assignment code
because the order is important, so (let* ...) form might be necessary as
well - but that could be just me.


> [foo | bar] => (| foo bar)
> >
>
> (cons 'foo 'bar)
>

> Pid ! Data => (! Pid Data)
> >
>
> (send pid data)    ;Using symbols can sometimes be harder to read
>

If you offer macro it's fine either way - I think termite uses ! for send.
I do like erlang/haskell here for their terse syntax - cons gets unwieldy if
there are many of them - .e.g (cons 'a (cons 'b (cons 'c 'd))) vs [a,b,c |
d].

As yours but quoted:
> (case a
>   ('foo #('bar))
>   ('bar #('foo 'bar)))
>

The one I wrote was scheme's version.  It can match multiple bindings with
one clause, but that can make it harder to transform into erlang.


>
> foo(1) -> 2; foo(abc) -> {foo, bar}. => (defun foo ((1) 2) ((abc) #(foo
> > bar)))
> >
>
> I was more into:
>
> (defun foo (arg)
>   (case arg
>     (1 2)
>     (abc '#(foo bar))))
>

To me this is where the basic lisp language doesn't offer as much as
erlang.  Ability to match on the function head is a very nice syntactic
sugar - it *just* look better than case statements, especially with
recursions.

In scheme with pattern matching lib (below is PLT scheme) one can write

(require (lib "match.ss"))
(define foo
  (match-lambda ;; or match-lambda* that can have different arities
    (1 2)
    ('abc #(foo bar))))

So with macros you can get pattern matching back, but why hide it in the
first place?


> One feature of lisp we must keep is that code has he same form as data,
> *is* data. That means that if we keep the Camel casing for variables then
> they have to parse to something other than symbols. If they don't then we
> will forever be parsing symbol names to discern what they are. That is why I
> would prefer to use the lisp convention of evaluating everything *except*
> that which is quoted. That means even using quotes in patterns.
>

Given you want a lisp instead of just lispy syntax - it makes sense.

I do think it's about symbol lookup rather than parsing.  Erlang uses
upper/lower case to distinguish between which symbol table you need to
lookup - that's a shorthand, I guess.  You can certainly have only one
symbol table for the most current bindings without distinguish between cases
or keywords - that's closer to a lisp/1 :)

My current working model is:
>
> mod:fun(<arg1>, <arg2>, <arg3>)  ==>  (module-call 'mod 'fun <arg1> <arg2>
> <arg3>)
> Mod:fun(<arg1>, <arg2>, <arg3>)  ==>  (module-call mod 'fun <arg1> <arg2>
> <arg3>)
> Mod:Fun(<arg1>, <arg2>, <arg3>)  ==>  (module-call mod fun <arg1> <arg2>
> <arg3>)
>
> with (: mod fun <arg1> <arg2> <arg3>) as a macro for the 1st most common
> case. It smiles at you because it feels good to be so helpful.
>

This is where I think the module-call style overlaps with apply/3.

Consider the following calls

Direct local call:             fun1(A1, A2, A3).
Direct module call:         mod:fun1(A1, A2, A3).
Indirect (Fun) local call:  F1 = fun fun1/3, F1(A1, A2, A3).
Indirect module call:       F1 = fun mod:fun1/3, F1(A1, A2, A3).
Apply/2 local:                apply(fun fun1/3, [A1, A2, A3]).
Apply/3 module:            apply(mod, fun1, [A1, A2, A3]).

In all but one case (apply/3), we are working with the function object
directly (either with a direct syntax or creating a Fun reference).  I.e.,
the only place we lookup the function via atoms and evaluate it at the same
time is in apply/3.

The (module-call ...) is basically equivalent to apply/3 - you pass in atom
for mod & fun and with that it looks up the function object AND evaluate the
function at the same time.

That's why I said it's tedious to do so for all module calls as it basically
means we are writing apply for all module calls.

To map against erlang - your lisp can "lookup and return" the function
object for use, say:

(fun 'fun1) ;; returns local #<function: fun1>
(: fun1) ;;; shorthand - the same as fun1, so this form is unnecessary
(fun 'mod 'fun1) ;;; returns #<function: mod fun1>
(: mod fun1) ;; for short hand as you say
;;; honestly - mod:fun1 isn't that bad if you allow : to be a package
separator as in CL. I generally end up faking it in scheme anyways.

Then the above becomes:

(fun a1 a2 a3) ;;; same for indirect call
((: mod fun1) a1 a2 a3) ;; same for indirect call
(apply (: mod fun1) (list a1 a2 a3)) ;;; apply/2
(apply 'mod 'fun1 (list a1 a2 a3)) ;;; apply/3

It looks similar but has a different semantic and IMHO more closely
correspond to erlang.

Lastly - I think your idea is interesting and the above are my 2 cents of
input to your goal, hopefully it helps more than it hurts :)

p.s. did you see Mark Feely's scheme to erlang? It might provide some
inspirations.
http://www.erlang.org/pipermail/erlang-questions/2007-June/027057.html

Cheers,
yc
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20071205/937caf9f/attachment.htm>


More information about the erlang-questions mailing list