Show HN: a Lisp that uses JSON instead of S-expressions (in .js)
github.com
github.com
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...
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.
Or perhaps using some CLOS magic do to do this behind the scenes, e.g. no-applicable-method
http://www.lispworks.com/documentation/HyperSpec/Body/f_no_a...
[NB It's been a long time since I did much Lisp]
I wasn't aware of no-applicable-method; thanks for that pointer.
How does Python handle mixing order of specifying keyword args positionally and with a keyword?
>>> 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)This is how Clojure hacks around keyword args, and altho destructuring kind of makes up for it, it's not that pretty. (It's not pretty in Ruby either) Hash table literals are a nice addition to Lisp but I think it's kind of ugly to use them for keyword args.
(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?
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?
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.)
True, but only as a device to keep the playing field open for any new benefits that might spring from universal hashmaps. What are they? I don't know, that's the question. Maybe there aren't any, but that itself would be interesting as a negative result (the L in Lisp is there for a reason).
What I'd really like to know is what would complete this sequence: list:Lisp, array:APL, stack:Forth, hashmap:?. That would be really interesting, no? And no one seems to be working on it, which is surprising given the ubiquity of hashmaps in modern languages (especially JS, but also Python, Lua, etc).
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.
Follow-up exercise: do you need numbers to build a Lisp out of associative arrays? (Hint: this is not a trivial question to answer.)
Yes, that's one thing. But do you really need CDR?
> You could represent a list as a naked array of lisp pointers, but then cons gets expensive.
Actually, it's much worse than that. CONS actually becomes impossible. (Think about it.) But maybe there's something else that you can use instead of CONS?
> And good luck garbage collecting the vectors
Why would that be a problem? Extant Lisps collect vectors just fine.
But they don't permit pointers inside the vectors, do they? I think if you permit internal pointers so you can have copyless cdr, computing reachability would get really expensive.
(a (b (c . nil))
^ ^
| |
| |
A B
If you implement lists as vectors with car/cdr (I'm still thinking about your other questions) and choose to have cdr not copy results out of the original cell, you can end up in the (rope-like) situation above with pointer B (value (b c)) in addition to pointer A (value (a b c)). But that makes GC inefficient. For a vector to be GC'd you have to know what internal pointers it has, and then you have to make the choice to copy them out if they're 'toward the end', or to leave the vector uncollected.(ignore pointers to a, b, and c.)
(defun foo (a b c))
could accept a map of variable names (foo {a: 1, b: 2, c: 3})That's not true in general, is it? It's just hash maps that are unordered. You can use a tree to represent an associative array (so the order of keys is found by a tree traversal), or a "worse" method like an association list (linked list). You can also just store a linked list of keys along with your hash map.
AFAIK, the only two ways to preserve positionality as part of an associative array are (1) to store as a postional list of key-value pairs and use linear search to find matching keys, or (2) to use an additional data structure as an index, either by storing as a positional list and having a additional map from key value into the positions, or by storing as a map and having an additional list of keys stored in positional ordering.
In a hashmap based lisp, I'd expect defun to look something like
(define-function: (foo-with-a: a b: b c: c) with-body: ...)
Of course, since you're using an unordered representation, one could instead say (with-body: ... define-function: (c: c b: b foo-with-a: a)), which is significantly more confusing. This also means you probably can't do implicit progn.
progn in general will probably be unpleasant, unfortunately, unless one includes syntactic sugar for ordered sequences, which might defeat the purpose of an associative-array-based Lisp.
The first thing I've noticed about a vector-based Lisp is that you actually need primitive integers so that you can do indexing, which isn't the case with cons-cell based Lisps.
I've been thinking about this in terms of a self-hosted Parenscript. What I see is a lot more pattern matching and map/reducing. Not altogether a bad thing.
"They are typically represented in text by parenthesized, whitespace-separated sequences" - S-expression, Wikipedia, emphasis added.
(Mexp used []..out)
else if(x[0] == 'quote'){ return x[1];
So why not just skip that extra verbosity? What am I missing?
["map", ....]
I don't see any `{ }`, etc.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.
We don't usually see yet another Brainfuck interpreter, or yet another Fibonacci queue implementation on HN's front page, so why LISP?
This project is exercising (proving? refuting?) that claim. I recognize that this isn't the most ambitious project in the world, but it was a Thanksgiving-weekend hack.
I'm thrilled that it got the 20 votes necessary to get it on the front page of HN.
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?
)
> 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
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."
I have a motorcycle, but I'm still interested in not only other motorcycles, but also bicycles. I don't think this makes me a pretentious douche.