Not to mention Lisps, especially the new ones, throw obviousness out the window with merry abandon. Let's look at Clojure. You think it's obvious how to operate on Clojure? Here: `(let [a 1, b 2] (+ a b))`. What is that? I've mostly coded in Scheme, I don't know what square brackets are supposed to do. Vectors? How do I manipulate them and what are they doing in my let? And what does the comma do? Oh, nothing? Then why is it there? And if the comma means nothing are you telling me that if I want to list the names that are being defined by this form, I need to extract the even-indexed elements of a vector? Sure I can do that, but don't tell me you care about ease of manipulation.
Anyway, sorry for the rant ;)
I think the point I really want to make here is that sure, s-expressions are quite simple, but if I can explain how s-expressions work in a minute, and how my expressions work in five minutes, this isn't really a matter of ease of manipulation, this is a matter of laziness. If a language's source-to-AST rules can be fully explained in one or two paragraphs or a small table, and can be easily remembered, then that's all that matters. I think that `a b: c` <=> `a(b, c)` is trivial enough that it does not have any meaningful impact on ease of manipulation.
(todo "name" (item ...) (item ...) (item ...)).
Basically the symbol todo is enough of a clue about the structure, and the pure syntax can determine most of the rest, with possibly a modicum of keywords here and there. (todo housework ;; symbols for naming!
(:high "Clean the house")
(:medium "Wash the dishes")
(:medium "Buy more soap")) todo [
housework
high: "Clean the house"
medium: "Wash the dishes"
medium: "Buy more soap"
]
And this is so easy to validate & use via the parse dialect that comes with Rebol.Here's a validation example:
todo-rule: [
set task-name word!
some [
set item-priority set-word!
set item-desc string!
]
]
>> parse [bad] todo-rule
== false
>> parse [incomplete high:] todo-rule
== false
>> parse [incorrect high: "item1" "erggh!"] todo-rule
== false
>> parse [housework high: "foo" medium: "bar" medium: "baz"] todo-rule
== true
With the lisp, it's obvious: There's a list of 5 elements. The last three are 'items', each of which is a list of 3 elements.
The benefit of s-expressions isn't just that they're flexible in what you can write with them, but that they're easy to manipulate programmatically, and their structure is immediately obvious.