Even though we write them with the same parenthesis syntax
And that's basically the answer to your question.
we need to learn how each works.
While it is possible to introduce DSLs with a not so lispy syntax like Common Lisps loop
using regular macros (I'll leave reader macros out of this), they are mostly used to control evaluation, and will still use regular s-expression syntax. One important feature is that even the more complex loop
-like macros can be read using the same old sexpr reader.
While it's true that you'll have to learn about the different macros and the form of input they take, say Common Lisp's cond
with its more nested vs. Clojure's cond
reducing one layer of nesting, that doesn't only hold for macros, but also for regular functions. Imagine a usual function taking a quoted list of a particular structure as an argument – you'll still have to conform to the expected input structure, whether the function transforms code, expects some kind of alist, plist, a tree or something entirely different.
Whenever you encounter new functionality, there will be some API you'll have to learn. That would also hold for a language that only allowed strictly function(arg1, arg2, …, argN)
syntax – you'd still have to learn what the expected arguments are, what side effects occur, and what the output of any given function is.
What's easier about Lisp syntax compared to a language like Scale, is that everything is represented more or less the same, and also that the code itself used these representations and data structures (that would be the homoiconicity everyone is talking about). This difference in syntactic complexity would become pretty clear if you tried to write a Lisp or Clojure parser and then a Scala parser. You'll have to cope with a much more complicated grammar – more complex rules concerning precedence, whitespace, ambiguities, more exceptions, and so on.