
Show HN: a Lisp that uses JSON instead of S-expressions (in .js) - jes5199
https://github.com/jes5199/brid.js
======
arethuza
I really like Lisp (I was even paid to develop in it for 6 years) and these
days I love JSON because of its Lisp-ish nature - but those expressions look
_damn_ ugly to me.

~~~
akkartik
You could lose the quotes around strings, but you'd still have the commas.

Maybe start with lisp and just add {key: value key2: value2} syntax for
tables? It'd be useful to get ruby-style keyword args for free, at least.

I spend a lot of time thinking about keyword args because I've been working on
a lisp interpreter that supports them. Here's a webserver that is nice to read
because of a crucial keyword arg (it starts with a colon):

[http://github.com/akkartik/wart/blob/460565a2e0/064http-
serv...](http://github.com/akkartik/wart/blob/460565a2e0/064http-
serve.wart#L10)

Like in python the keyword arg is always optional. You could delete it from
this definition and it would behave the same.

In conclusion: please try to include python-style keyword args in your next
language. You never know when they'll come in handy.

~~~
anghyflawn
What's wrong with Common Lisp's keyword arguments? I'm not being snarky, just
asking. I'd say CL works at least as well as Python in this respect.

~~~
akkartik
No, in Common Lisp you can't mix a keyword arg for a non-keyword param, or
vice versa.

~~~
sedachv
You can do (&rest all-args &key keyword1 (keyword 2 default2)) and then try to
figure out all-args in the function body.

How does Python handle mixing order of specifying keyword args positionally
and with a keyword?

~~~
akkartik
Python requires all args following a keyword arg to be keyword args:

    
    
      >>> def foo(a=0, b=1, c=2): return [a, b, c];
      ... 
      >>> foo(34)
      [34, 1, 2]
      >>> foo(b=34)
      [0, 34, 2]
      >>> foo(b=34, 35)
      File "<stdin>", line 1
      SyntaxError: non-keyword arg after keyword arg
    

I chose instead to simply bind args by position after keyword args have been
taken:

    
    
      wart> (foo :b 34 35)
      (35 34 2)

------
gruseom
I still think there's room for experimenting with a Lisp that has the hashmap
(a.k.a. dictionary, associative array, property bag) as its organizing
principle rather than the list. There's nothing better than hashmaps for
exploratory programming. If there is something to be gained from building a
Lisp in terms of them (from the ground up; I don't mean support for object
literals), I'd like to know what it is. This has little to do with syntax.

~~~
lisper
This presents a very thorny language design problem. Lists have this very nice
property that they are _ordered_ , which lets you attach implied semantics to
the _position_ of an element, e.g.:

(defun foo (a b c) ...)

We know this is a function defining because the symbol DEFUN is in the FIRST
position of the list.

Associative arrays are unordered, so you have to explicitly label everything:

{ top-level-form : defun, arguments : { 1 : a, 2 : b, 3 : c }, ... }

Or something like that. You can see where that would get annoying.

Exercise for the reader: what happens if you base a Lisp-like language on
vectors instead of cons cells?

~~~
gruseom
Could you allow (a b c) as a synonym for { 0 a 1 b 2 c }? That's more or less
how JS deals with this, though JS feels messy under the hood.

 _what happens if you base a Lisp-like language on vectors instead of cons
cells?_

I want to know that too! One thing is that you lose cons and cdr (except by
copying the vector), so you lose the ability to do most of the classic Lisp
things efficiently. You must have something in mind other than this?

~~~
lisper
> Could you allow (a b c) as a synonym for { 0 a 1 b 2 c }?

Yes, of course, but all you've done is re-invent vectors.

> you lose cdr (except by copying the rest of the vector)

Copying the rest of the vector is not semantically equivalent to CDR unless
you are being purely functional. But you can actually implement CDR using
displaced vectors.

> You must have something in mind other than this?

Could be :-)

Try writing EVAL for a vector-based Lisp and see what happens. In particular,
when you're done, make a list of all the primitives you needed to employ in
order to do it. There's a deep insight at the end of this process. (No, I'm
not going to tell you what it is.)

~~~
munificent
> In particular, when you're done, make a list of all the primitives you
> needed to employ in order to do it. There's a deep insight at the end of
> this process. (No, I'm not going to tell you what it is.)

Having done this before (<https://github.com/munificent/lark>), all it meant
for me was that numbers and basic integer arithmetic became primitive. The
clever bit about McCarthy's original metacircular interpreter is that it
didn't need any types at all beyond atoms and cons cells: no bools, no ints,
no nothing.

I found it interesting, but I don't know if I reached any deep insight. Maybe
that's just me, or maybe I missed something.

~~~
lisper
I suppose depth is in the eye of the beholder. That's pretty much it: to build
a Lisp out of vectors you need numbers as primitives. To build a Lisp out of
cons cells you don't.

Follow-up exercise: do you need numbers to build a Lisp out of associative
arrays? (Hint: this is not a trivial question to answer.)

~~~
akkartik
Rereading McCarthy's paper yesterday I noticed for the first time that it
didn't need numbers. But I hadn't connected all the dots yet.

------
tantalor
How is this different than S-expressions? It seems equivalent modulo syntax.

"They are _typically_ represented in text by parenthesized, whitespace-
separated sequences" - S-expression, Wikipedia, emphasis added.

~~~
agumonkey
He should call them SMexp.

(Mexp used [].. _out_ )

------
fogus
Any new McCarthy LISP implementation is destined to provoke the programming
equivalent of "git offa mah lawn!"

------
akkartik
Get thee to the arc forum, where the six of us will provide good
entertainment: <http://arclanguage.org/item?id=15422>

------
ktusznio
What is the purpose of the "quote" parameter? The only place it is in the code
is here:

else if(x[0] == 'quote'){ return x[1];

So why not just skip that extra verbosity? What am I missing?

~~~
ohyes
Quote prevents evaluation. If you didn't quote it, x[1] would get evaluated as
code.

------
oconnor0
Does it use more JSON data types than arrays? The only examples are

    
    
      ["map", ....]
    

I don't see any `{ }`, etc.

~~~
benatkin
There is only one other composite data type besides arrays: objects. I don't
think these are being used for invoking functions, but I think it would be
interesting to try.

------
sxephil
Many people seem to confuse lisp's expressiveness with its syntax.

Syntax is just the beginning.

How you abuse it, to get things done is the more important thing. Please take
time to explore this aspect more than those silly fracking parens.

------
xyzzyz
I'm sorry, but I cannot get excited over Yet Another Implementation of
McCarthy's LISP[1]. If your Lisp had _any_ interesting feature, e.g. call/cc,
or object system, or nifty macro system, or something else, then, maybe, but
doing the the same old, trivial thing, again and again, does not seem very
interesting for me.

We don't usually see yet another Brainfuck interpreter, or yet another
Fibonacci queue implementation on HN's front page, so why LISP?

[1] - <http://lib.store.yahoo.net/lib/paulgraham/jmc.lisp>

~~~
raganwald
(cranky

You know, we have the upvote arrow for things that excite you, and the “Go
read something else and comment on it” feature for things that don’t float
your boat.

Clearly this is not spam and it is not off-topic. So:

You asked the OP and/or your fellow HNers why they upvoted this onto the front
page. I ask you, why this comment, what value does it add to my life to read
about how smart and educated you are?

What about all the people who haven’t seen an implementation of McCarthy’s
Lisp? Do they not deserve to find this interesting? Should they turn in their
HN accounts and head over to reddit?

I wrote an implementation of Scheme in Java with macros, tail call
optimization, lambda hoisting, a bunch of stuff. Yet I find this interesting.
Is there something wrong with me?

)

~~~
raganwald
Raganwald, you pretentious douche:

> I wrote an implementation of Scheme in Java with macros, tail call
> optimization, lambda hoisting, a bunch of stuff.

Greenspun’s Tenth Law is widely accepted, demonstrations of it in action add
nothing of value to the programming community. Furthermore, writing a Scheme
in Java is likely to be a project where you learned nothing of interest about
Lisp or about Java.

—signed, Nikolai Bourbaki

~~~
appamatto
Misapplication? I thought the Law was meant to describe accidental
implementations of Lisp rather than overt ones.

In other words, "the complicated system you made _just happens_ to contain a
Lisp, and if you had noticed that requirement in the first place its design
would have been cleaner."

~~~
raganwald
I think you have captured the spirit of the law. The project in question was
the development of a scripting language for something-or-other, so this wasn’t
an accidental implementation of Lisp, it was done with malice aforethought.

