
Show HN: Superset of Lisp and Lua Programming Language, a la JSX - meric
https://github.com/meric/l2l
======
chubot
This looks interesting... one of my pet peeves is writing imperative code in
functional languages like Lisp or OCaml. For example, hand-written lexers and
parsers are heavily stateful and don't really benefit from the functional
style, even though they are pure functions from the outside.

It just feels and reads a lot worse than doing it in say Python. So you could
make a program clearer by writing the functional parts in one syntax and the
imperative parts in another syntax.

~~~
59nadir
Have you ever used parser combinators? They're the absolute best way of
parsing anything that I've ever tried. Parsing anything in Python definitely
is much worse.

Also, I'd like second the other posters suggestion that most Lisps have many
ways of writing imperative code and that it really is no different than your
average C-like in that respect.

~~~
chubot
I'll take another look at parser combinators. I keep hearing people talking
about them, but I had never seen them used for anything big. Now that I check
again, I see that the ShellCheck lexer/parser in Haskell is written with
Parsec, and it seems to do a pretty good job, and has good places to insert
error messages and so forth.

Do you have any other examples of a production quality parser done with parser
combinators?

The Lisp parser I was thinking about was Julia, which is bootstrapped in
femtolisp. It looks like straight imperative code in Lisp to me.

I'm mainly concerned large parsers, like bash, Julia, Ruby, or C. You can
write a small parser with any technology. FWIW I have a lot of posts about
parsing here, towards the beginning of the blog:
[http://www.oilshell.org/blog/](http://www.oilshell.org/blog/)

EDIT: What's the benefit of parser combinators over recursive descent in
Python or say Java? Is it just that it's point-free so you don't have to
explicitly pass the input around?

I suppose if I saw the same parser written in parser combinators and recursive
descent it would be easy to tell what the benefit is, if any.

~~~
meric
Well I use a parser combinator to build the Lua parser here.

[https://github.com/meric/l2l/blob/master/l2l/lua.lua#L429](https://github.com/meric/l2l/blob/master/l2l/lua.lua#L429)

The parser generated is recursive descent.

------
nikki93
Woah could you run this over Love 2D? Could also be fun with
[https://github.com/nikki93/cgame](https://github.com/nikki93/cgame) (game
live coding + live editing environment).

~~~
meric
That looks great I will give it a go sometime!

------
mark_l_watson
Cool looking project!

This will sound like a nit-pick, but I don't intend any real criticism here:
the syntax does not look good to me. I have lots of Common Lisp and Scheme
experience, and also a few years of using Clojure. It is easy for me to switch
between reading and writing code in those three languages, but I would need a
while to get used to this language's syntax.

~~~
meric
Thanks :-)

What are the syntax features most jarring to you? I suspect it's the ones
that's been ported from Lua but I'm not sure.

~~~
zem
for me it was the quoting/unquoting. i'd rather see something like {} to
introduce a block of lua code and #{} to introduce lisp code within the lua
block.

------
Johnny_Brahms
I don't understand this clojurism of not making let-expression bindings adhere
to the "parenthesise everything" of regular lisps. Why make let special? Why
have a parser exception for some things?

It is just a cosmetic thing,but it bormthers my otherwise so paren-friendly
eyes.

~~~
abecedarius
I dislike it, too, but if tweaks like that help a new generation get into
Lisp, then _shrug_. And the parens in the original LET form really are a bit
much.

In my own Lisp you go like

    
    
        (let a 42)
        (let b (+ a 1))
        (blorgle a b)

~~~
dTal
That looks more like (define) than (let). When do the bindings fall back out
of scope, if not when the let-form ends? And can you do multiple bindings?

~~~
abecedarius
Yes, it's pretty much like Scheme define but with pattern matching (and
correspondingly without the (define (do-it) ...) shorthand; you say (to (do-
it) ...) instead).

They go out of scope at the end of a scope block, as usual; but conditionals
introduce subscopes for the different branches. There's a (hide ...) macro I
use occasionally.

To bind multiple things at once, there's the pattern matching, e.g.

    
    
        (let `(,x ,y) point)
    

(Not sure if that's what you're asking about.)

It's always bugged me in Scheme how binding forms are repeated, one type like
DEFINE and another like LET, and DEFINE behaving not quite the same at top
level vs. internally.

(Added: Another little nit that to me grew over the years is that Scheme is
just kind of verbose. You don't want to see shorter, clearer code in Python.)

------
zengid
Why?

~~~
meric
I couldn't help it.

Take a look at map/filter/reduce loop collapsing, and function inlining using
AST analysis. It makes the code go really fast in LuaJIT.
[https://github.com/meric/l2l/#zero-cost](https://github.com/meric/l2l/#zero-
cost)

That kind of abstraction can be written as an extension module and imported as
easily in the language as if it were another Lua module.

~~~
zengid
Cool! I'm not literate in Lua so the context-switching is rough on my eyes,
but I think it's a neat synthesis none the less!

~~~
meric
Hmm, that's an interesting concern....and thanks for taking a look. :-)

