I'm not sure what you find incomprehensible about the first example. The syntax is pretty standard. The only exotic thing is `$`, which is basically just like putting brackets around the rest of the line. Here's the first example roughly translated to Python:
def main():
x = 2
[x] = ["foo"]
y = 3
[y] = ["bar"]
print(x + y)
Seems about the same level of comprehensibility to me. Is there anything in particular you find difficult to understand?
The second example is expanded out and not how a person would normally write it, but if you're familiar with the basic concepts it's using, it shows why it works very clearly; think of it like assembler.
I can hear them and tell that they're different accents, but I don't really distinguish them, I would call them both "British" and I wouldn't know which one's more posh.
Usually that effort should go toward naming functions rather than their results, though, and if the functions have good names, the results don't need them. In this example, `other_function` could have been named `get_user_data`, `new_function` could have been called `extract_user_details`, whatever.
Once you have good function names, which you should generally be spending a lot more effort on than good local variable names, you won't find any value in adding variables like `var foo = get_foo()`.
> Clojure has cons, car, cdr which you can use in the classic Lisp sense. The only thing you CAN'T do is have a dotted pair or dotted list in the last cons cell.
So, it doesn't have them in the classic Lisp sense. Conses are just pairs. Using them as such isn't exotic. (cons 1 2) being an error in Clojure isn't a minor thing, it's very unique compared to other Lisps. It has a very different definition of cons.
Yes. Clojure doesn't have cons cells in the traditional sense. But as long as you don't need dotted cdrs, you can "think" of using cons, car, cdr in the ordinary way. You can use existing lisp idioms of recursively taking apart, editing and rebuilding a complex form.
That isn't how that defun would normally be formatted, though. Lisp knows that the 'body' part starts with the 3rd argument (the same way Clojure knows it starts with the second), so it indents the lambda list farther right (if it doesn't fit on the first line, otherwise it would go there).
For my eyes, [] aren't distinct enough from () to make the second style preferable. I'd rather have indentation to set it apart.
I just made them consistent. It certainly helps me visually. Also a list implies you intend to evaluate it by executing a function. A vector implies you do not intend to call a function.
Yeah, it's definitely a taste thing, but as the first style isn't used in Lisp, comparing its readability doesn't really make sense. Indentation is important to reading Lisp. Indenting it in an odd way makes it harder to parse. It's a bit like giving
def
foo(x)
bar(x)
end
as an example of Ruby syntax being overly homogeneous.
A Lisp programmer reads those structural patterns, not the delimiters.
Lisp programming is more about thinking of trees of code and their possible manipulation - even independent of a visual notation and especially independent of the exact delimiter used.
The delimiters are in shape recognition much less important than the shape itself.
"A Lisp programmer" ... Sheesh, I am a lisp programmer, man, and I assure you I know what trees of code independent of visual notation is. You're making a point that doesn't need to be made here. It's this kind of phrasing that really turns off people from the lisp community.
I wrote it that way so it's easier for non-lisp programmers to compare with what they're more used to as well.
In Forth, the interpreter reads tokens. By default, each token is read and then executed. There is a token that switches the interpreter into "compiling" mode. When in compiling mode, each token is read and then used to instruct the compiler to emit code representing the token. There is a traditional and beautiful interplay [0] between the Forth interpreter and its initial stream of tokens, as the tokens customize the interpreter and compiler by augmenting their behaviors.
The main contrast that I would draw between Forths and Lisps is syntax. Forths don't really have syntax; they have token-parsing streams. Lisps are extremely tree-oriented, but Forths are stack-oriented.
Forth has two singleton stacks, and each has a DSL. Sometimes I wonder what Forth would be like with stacks as a first-class type. Maybe actors each with their own stack …