The reason this syntax scares you is simple: it's different.
At the very root, Python syntax is nearly identical to Java, C, etc.
The syntax of Haskell, OCaml, etc, is a deviation from that of Python, Java, etc, but not an incredibly significant one. Perhaps you may find that the syntax of these languages scares you but you think you could probably learn it after a bit of mind-wrangling.
Lisp, on the other hand, is old. It was developed over 10 years before even C came to being! So the syntax is completely different, and requires you to actually learn it instead of just assuming that your knowledge of other programming languages will pull you through.
In summary, it's not a fault in you. It's just that you are used to C-derived and influenced syntaxes, but not to Lisp; and the syntax of Lisp is different enough that you need to actually learn it.
Here's a crash course:
(f a b c) is the same as f(a,b,c).
'(a b c) is kind of like ["a", "b", "c"].
'(1 2 3) is just like [1,2,3]
(defun x (a b c ...) ...) defines a function x(a,b,c).
(+ 1 2 3) is just like +(1,2,3) = 1 + 2 + 3
(setf x 5) is just like x = 5
'(a b ,c) is just like ["a", "b", c]
if L is equal to '(1 2 3), then
`(10 20 ,@L) is like [10, 20, 1, 2, 3]
Now, to be honest, I just showed you nearly 100% of the 'syntax' Lisp has. The rest is already understanding the language (knowing how to def. functions, how to do loops, etc).
By the way, what you might find interesting is that I once showed this to a friend of mine who knew nothing about programming. I showed him how to write a basic program in Java (with a few subroutines and a loop), then how to do it in Lisp. He exclaimed, "Argh! If I can do it like this, then why do I need all those fancy weird words like public and void and what not and braces and... eugh!"
Sorry for that longish post, I hope you found it at least a bit informative. ;)
Very useful! I suppose I was wrong to say the syntax is confusing, because lisp is so syntactically minimalistic. But when I look through lisp code, I can't determine anything with respect to scope. Take, for example, the code in pg's A Plan for Spam:
http://www.paulgraham.com/spam.html
It took me several minutes to weed through this code. Part of that is because I didn't know what, say, apply did, and had to look it up. That's not an issue because you have to do that when learning any new language. But I had to carefully inspect the source bottom-up and break it apart because I couldn't tell what the arguments are on each function call. An IDE that does block highlighting would help a lot, but even then it feels overwhelming, because it only helps me inspect the block that my mouse cursor is currently on.
I guess what I'm saying is, I feel as if the syntactical constructs in other languages are necessary for me to be able to quickly parse a language.
Lisp code is almost always written on multiple lines, with an editor that automatically indents everything. Code in a more familiar language (C?) would also look incomprehensible if ten lines were all smushed together on one.
You still have to learn the idioms (it's a different language!), but it's not just a jumble of parenthesis.
Prefix notation takes some getting used to for arithmetic, but that's neither here nor there. You probably have a bundle of idiosyncratic operator precedence rules memorized (quick, does 3*4+5 equal 27 or 17?), and Lisp doesn't use those, preferring to consistently use parenthetical nesting for everything.
Paul Graham has a peculiar Lisp style which is NOT mainstream. He is succinct, clever, and usually performance-agnostic. He writes expository code like we write one-liners in the repl to quickly test something out.
That example you linked to is confusing because: 1) You don't know the syntax to read it out like a formula, and 2) he uses the names prod and probs which look the same and strain the mind of a newbie.
The way you read "hard" Lisp code, specially one in Graham's style is to read from the last line upwards. The tell-tale is the deep indentation, btw.
Start at the last line, which is the body of MAPCAR, you know mapcar is MAP which applies its first argument function to successive elements of its second-argument, which should be a list.
(mapcar #'(lambda (x)
(- 1 x)) probs)
Make a mental note about the free variable, probs. You can recognize the function as the usual arithmetic step of converting integers to probability values between 0 and 1. The sharp-quote, #', is an archaic style and unnecessary, so let's wrap up these two lines into a function and change the names to be readable.
Look up further and notice the result of this function call, a list, is being reduced to an integer. APPLY applies its first argument, a function, to its second argument, a list. For example, (apply #'+ (list 1 2 3 4)) means sum of the first four digits. C programmers should find this familiar: (apply #'main argv)
Where MAPCAR returns a list, apply returns whatever its function argument is supposed to return. We know the function #'* takes a list of numbers and returns their product. So, the snippet is just multiplying the list of probabilities, or reducing to a scalar.
And here something called prod is being added to our scalar. Hmmm.
Look up a bit and see where that's coming from. The nearest binding form for prod is in the LET body on top. Looks very similar to something we have seen before. Another application of multiplication to the list named probs. This is not a Lisp issue, it's a Bayesian statistics or perhaps a PG issues. You continue reading the paper and discover his formula in English prose. Aha! :-)
You can move code around, tuck it into functions and do whatever you want with it. See if you recognize the code snippet now:
Typically you don't do that; you don't make silly repls and you never ever write a MAIN or any other program entry function. You write libraries, that you use in other libraries, and you orchestrate them all via interactive use and deploy in a custom image.
I'm not sure this is quite correct. My own (admittedly controversial) opinion is that lisp is old, and it's "syntax" is broken because it's nonexistent. Python has it's own problems, but it is less broken. :-)
The raw basic "syntax" in terms of the parens is a bear to read (and write), but you get used to it. It may be different, but that isn't really the problem. Anyone can figure out nested parentheses and escaping. Just as someone else pointed out -- this isn't alien territory .. nested parens/brackets/whatever and literal escaping are common in complex/terse code in any of the popular languages. Possibly Haskell is different, but I find it's terse syntax of juxtaposition more inscrutable than lisp, for the most part.
The problem is that in practical terms, the lisp syntax is not just nested parens and various forms of quoting and basic function invocation. The syntax includes the positions of arguments to various standard macros and special forms. Are they are sublists or inline? what are the keywords? And most importantly, are they evaluated or not? From an academic point of few, this technically could be considered semantics of a programming language, but I think that's false -- we don't consider human sentence structure semantics. This is totally syntax. And in lisp, it's highly irregular from form to form. It's just something you have to "know" based on the form, and the lack of syntax other than parens and quotes certainly doesn't help you at all here.
Compared to something like python, it's unreadable and confusing.
You have a point; your basic statement is something I agree with. However, it depends on what variant of Lisp. Common Lisp, it's true, does have a lot of remnants from the past which make it ugly. (After all, why should I have to say 'aref' when it would be so much nicer just to say [] for array references...)
However, other Lisps exist. Take a look at Scheme or Clojure. Scheme is prettier, and Clojure more practical.
(On a side note: these different variants of Lisp certainly don't help create one "Lisp community".)
Until you start getting into the most complex (and powerful) aspects of lisp, the last two lines of syntax are rarely used. You get get a very long way without understanding them, but once you do lisp will become one of your favorite languages.
At the very root, Python syntax is nearly identical to Java, C, etc.
The syntax of Haskell, OCaml, etc, is a deviation from that of Python, Java, etc, but not an incredibly significant one. Perhaps you may find that the syntax of these languages scares you but you think you could probably learn it after a bit of mind-wrangling.
Lisp, on the other hand, is old. It was developed over 10 years before even C came to being! So the syntax is completely different, and requires you to actually learn it instead of just assuming that your knowledge of other programming languages will pull you through.
In summary, it's not a fault in you. It's just that you are used to C-derived and influenced syntaxes, but not to Lisp; and the syntax of Lisp is different enough that you need to actually learn it.
Here's a crash course:
Now, to be honest, I just showed you nearly 100% of the 'syntax' Lisp has. The rest is already understanding the language (knowing how to def. functions, how to do loops, etc).By the way, what you might find interesting is that I once showed this to a friend of mine who knew nothing about programming. I showed him how to write a basic program in Java (with a few subroutines and a loop), then how to do it in Lisp. He exclaimed, "Argh! If I can do it like this, then why do I need all those fancy weird words like public and void and what not and braces and... eugh!"
Sorry for that longish post, I hope you found it at least a bit informative. ;)