First, I don't see how any attempts to "deal with" the S-expression syntax in Lisp are going to be particularly successful. Many of the strengths of Lisp are emergent properties of it having an unambiguous, consist, arbitrarily nestable prefix syntax. Lisp really is not Lisp without it. (Similarly, much of the expressive power in Forth comes from using postfix syntax and the stack for argument passing.)
Second, I strongly disagree with the post that OCaml has "the worst imaginable syntax". It's syntax could be nicer (a couple imports from Haskell syntax and a "...to end of line" comment marker would go a long way), but for being such a powerful multi-paradigm language, it has nowhere near as many edge cases as C++ or Perl. It seems to have been designed with a priority on reducing ambiguity (which has the benefit of making compilation just about instantaneous).
You can also add your own syntax forms (Lisp macros, but a little harder due to transforming a typed AST rather than S-expressions) with camlp4, though I have not personally done this (yet!).
I started writing a Lisp interpreter in OCaml this weekend. I'm experimenting with adding infix read macros (e.g. . for function composition) to the language, among other things, and I have been thinking about this a lot lately.
"it has nowhere near as many edge cases as C++ or Perl."
Understand that comparing to Perl and C++ for syntax is like comparing some smell to that of rotten eggs. If you would like to compare syntax, use LISP or Python or for functional languages, Haskell etc. Don't start at the bottom and say that "X" is better.
And yet huge quantities of code have been written by productive hackers in both of those languages. Which is sort of the point of the article: the "micro" qualities of the syntax of a language are irrelevant. You get used to them quickly and forget about them. Arguing for one language over another on the basis of how the syntax looks is basically worthless.
That doesn't refute your point that LISP derives "macro" functionality from its syntax that doesn't really have anything to with the way it looks or types. Arguing for LISP due to its expressive macros is fine, but nitting about all those parentheses isn't useful. Arguing against perl for the "smell" of its odd reference syntax is likewise silly, but pointing out that that syntax allows neat autovivification tricks and more expressive scripts is cool.
Arguing for one language over another on the basis of how the syntax looks is basically worthless.
Agreed, with an exception for when frequently used constructs are needlessly verbose or awkward. Something really minor, like the Python slicing notation, can make something so convenient that you find new uses for it. This is big. (For example, someStr[1:-1] means, "drop the first and last char".) It works the same for every ordered collection (lists, strings, tuples), so it's easy to remember. Dictionaries also support dictname[index] notation, but aren't ordered, so slicing is meaningless. (Lua seems to do something similar with its "tables".)
I'm not especially fond of the Lisp parenthesis, but I don't know of a better solution for a prefix-notation, nesting syntax. (Switching parenthesis for another paired symbol, e.g. curly braces, would just be a meaningless detail.) Postfix/stack languages can drop them, though.
Perl is sort of in-between; on the one hand, it is trying to build on the considerable power in the terse syntaxes like sed and awk, which are remarkable for quick scripts, but it is also trying to be usable for mid-to-large projects, which need to be relatively clean or they will become an unmaintainable mess. The latter is true for any language, of course, but it seems like good habits are harder to stick to in Perl.
Lua tables have two parts - the ordered part with indices 1 ... n and the other part is everything else. You can iterate over a table in various ways. pairs() is an iterator over the entire table in an undefined order. ipairs() gives the ordered integer keys from 1 to #t (#t gives the max integer key of a table t).
My favorite aspect of Lua tables is that attribute-style access is exactly equivalent to dict-style access.
At the repl:
> tab = {} -- allocate a new table "tab"
> tab.string = "hello!"
> =tab.string == tab['string']
true
Also, you can index a Lua table by any other value. Functions, strings, tables, and booleans are all valid keys. nil is the only invalid key.
Fair enough, but OCaml is a multi-paradigm language (which just happens to have an excellent functional language built in). OCaml's version of the C++ STL is much cleaner, for example.
Python supports functional programming somewhat, but it has an uneasy relationship to the rest of the language (i.e., Python lambdas are quite weak, apparently for parsing reasons), and Guido has said it will probably get cut eventually. It's a pretty good syntax overall, though I dislike having to explicitly specify "self" so much in classes.
Common Lisp (more so than Scheme) is also multi-paradigm, but that's already covered here; I think it's a better syntax overall, but I would love to see the features of ML's type system integrated with it.
I would compare OCaml to Oz/Mozart as well, but I don't have any significant experience with it.
To introduce programmers used to a C-like syntax to Lisp, I like to show how s-expressions are really just ASTs. Write a small function in C, show what the AST for it looks like, and then show the Lisp verison. The mapping should be obvious.
I've seen plenty of introductions to Lisp talk about the code-data equivalence, but most don't explicitly say that writing Lisp is the same as writing your programs directly as ASTs.
Second, I strongly disagree with the post that OCaml has "the worst imaginable syntax". It's syntax could be nicer (a couple imports from Haskell syntax and a "...to end of line" comment marker would go a long way), but for being such a powerful multi-paradigm language, it has nowhere near as many edge cases as C++ or Perl. It seems to have been designed with a priority on reducing ambiguity (which has the benefit of making compilation just about instantaneous). You can also add your own syntax forms (Lisp macros, but a little harder due to transforming a typed AST rather than S-expressions) with camlp4, though I have not personally done this (yet!).
I started writing a Lisp interpreter in OCaml this weekend. I'm experimenting with adding infix read macros (e.g. . for function composition) to the language, among other things, and I have been thinking about this a lot lately.