
Lisp with maps instead of lists - jefffoster
http://will.thimbleby.net/misc-an-experimental-language/
======
sambeau
I've been working on something similar for the last few years. It's a neat
idea that has some interesting properties: a code block is a triple: code,
value and map (and quite possibly a closure so that it can be repeatedly re-
evaluated). You can easily build complex iterative lazy structures as well as
all the ordinary things like for-loops, function calls etc using the same
basic structures.

It's a similar idea, in many ways, to the way Javascript does objects: run
some code get a map back. Where it gets interesting is that you can choose to
use the evaluated value and the scope that was generated in evaluating it.
Objects, maps, code, scope, closures and lazy evaluation become the same
thing: you declare a block of code, you evaluate it into a closure (with scope
and a stack) you query it for results, rinse-repeat.

A for-loop becomes a function that takes two blocks: one that lazily generates
values in and one that lazily consumes them. It is the two closures that
remember their state - not the for-loop function. The 'for-function' just
passes the current value to the second block to use it.

Javascript, REBOL and Lua do have these capabilities but none have the
elegance (nor simplicity) of Lisp. I'd love to see a language that does.

------
gruseom
It may be a toy language, but it's a serious idea, one I've often wondered
about. I work a lot with both Common Lisp and Javascript and the one killer JS
feature that I miss in CL is its maps, or rather its use of the map as its
organizing principle. This particularly shines for exploratory programming,
since it frees you from having to work very hard when adding, removing, or
reordering information in your program: it's trivial to stuff a property into
a JS map and trivial to get it back. Since nearly everything is a map, nearly
everything has this flexibility. CL's plists seem like they ought to serve
this purpose, but they don't (compared to JS) because plists are conses and
their identity changes when you prepend new properties to them; also, all null
plists are the same, which turns out to be surprisingly restrictive (again
compared to JS).

On my project we ended up adding a JS-style property operator to CL and using
JS-style maps wherever we wanted this flexibility, which was nearly
everywhere. It just compiles to CL hashtables under the hood. This is so
valuable, it's natural to wonder what a Lisp with the map as its organizing
principle would look like.

~~~
cgrand-net
In Clojure, the default collection for data modeling is the map (and has
literal support). Unlike javascript, properties are namespaced so you can
extend someone else map without fearing a nameclash.

Records (which are objects with a user defined types) are maps too so the
upgrade is easy (and yes you can add you own fields to an object).

~~~
gruseom
Sure, but maps are still bolted on. That's convenient, but it's not
interesting. The interesting question is, what would a language that is to
maps as Lisp is to s-expressions look like? The OP is the first person I know
of who's tried to answer that.

It's an important question because maps are flexible and flexibility is
important for exploratory programming, which is nearly all programming. If
there exists a language that is as regular and programmable as Lisp but
organized around maps rather than lists, that would be a big deal.

------
edw
It's difficult to gauge how serious this proposal slash thought experiment is.
The nice thing about a pair is the way it naturally lends itself to iterative
processing: There's the CAR and the CDR, the first and the rest. (Are the keys
in these maps ordered?)

Not all data is complex enough to merit a map: modeling e.g. a list using
lists is perverse in that you're using degenerate single-item maps to model
what is a simpler data structure.

And what does a lisp based on maps look like, if this language preserves the
homoiconic nature of lisp?

The argument by analogy that a lisp "should" have a "better" data structure
than a cons cell because lisp lambdas support multiple arguments, unlike pure
lambda calculus, doesn't hold water. Lisps--and even Scheme, which is often
incorrectly taken to have as a design goal to be minimalistic to the point of
consisting of axiomatic primitives--do not deal in pedantic adherence to
theory. Limiting lambdas to a single argument is pointless whereas a cell
happens to be minimal yet extremely useful in practice.

Other have written lisps atop vectors as the primitive data type. That's an
idea that makes more sense: it's a generalization of the pair to arbitrary
length.

~~~
jasonwatkinspdx
_" The nice thing about a pair is the way it naturally lends itself to
iterative processing: There's the CAR and the CDR, the first and the rest."_

While elegant, the convention of cons cells as lists is increasingly going to
be a flaw, because using linear recursion to process a list often obscures
parallelism vs using a binary divide/conquer description of algorithms. See
recent talks by Guy Steel on lisps organized as concatenation trees.

Also, I think Lua is a good existential example that organizing a language on
top of a single MAP data structure can be quite sensible.

~~~
edw
I don't disagree that the pair is far free the be-all end-all of primitive
data structures. On the contrary, when I'm programming in Clojure, most of my
data structures are made out of hashes and vectors.

And most definitely, the need to walk a linked list inhibits parallel thinking
(and, just as importantly parallel execution) and so we shouldn't avoid baking
richer data structures into lisps. Again, Clojure does this and even Scheme
does too, with R6RS with hashes as well as the more established vectors,
because, again, Scheme is not about axiomatic minimalism. But to make a hash
_the_ fundamental data structure out of which everything else is constructed
would be crazy.

There's plenty of room on the world for atoms, pairs, vectors, hashes, and
maybe even primitive sets. What I don't know is if this proliferation of
primitive types would cause other problems because we'd wind up dedicating so
many bits in a pointer to tags to signal a type that we'd restrict the range
of atoms too much. But hey, we're living in a 64 bit world now, right?

~~~
jasonwatkinspdx
_"But to make a hash the fundamental data structure out of which everything
else is constructed would be crazy."_

A hash can easily model a vector, including sparse vectors. There are
efficient functional implementations such as Clojure's which is based on
Bagwell's Array Mapped Tries.

Functional vectors/arrays are an open research problem.

So I would say maps might be very reasonable as the single structure in a
functional language.

Also, there are many ways to cope with tagging more types than are practically
fit within the low bits of a pointer. The simplest dates all the way back to
MACLISP (no relation to macintosh). The idea is to tag regions of memory that
hold uniform values. This fits very well with modern memory allocators based
on the slab allocator.

------
guygurari
This is interesting. Maps are themselves functions, taking the key as a
parameter and returning its associated value. So when your basic data type is
a map, the language is arguably more "functional" than the usual functions +
lists combination.

~~~
fexl
In Fexl (<http://fexl.com/code>), the basic concept is the function, and data
is built from functions.

------
kawabunga
I've also built something similar that is based on .NET:
<http://code.google.com/p/metalang/>

Maybe we should all team up or something...

------
foobarbazetc
This looks like REBOL. :)

------
fexl
We discussed this same article extensively yesterday at
<http://news.ycombinator.com/item?id=2552180> .

