I am surprised that you cannot just use parentheses anywhere you want.

Parentheses are good friends of us when we don’t want to memorize the evaluation order of operators (Pop quiz: In C, what does 0 | 1 & 1 evaluates to?). In Scheme, however, there is no such need. The order of operation is self-obvious with all syntax-required parentheses already in place.

In lots of programming languages you could just insert extra parentheses, sometimes just for the sake of clarity. However, the catch in Scheme is that extra parentheses would not just be ignored. For example:

In C#,

if (((n == 1) && (x != 9) || (n < 1)) || (y > 7)) //This is fine.
  return 1;
if((((((((true)))))))) //This is fine.
  return 1;

But in Scheme,

(if (= x 2) 1) ;this is fine.
(if (((((= x 2))))) 1) ;this is not fine
Error: bool is not callable: #t

Why? And why this error message? Let’s see the simplest comparison example:

In Python,

>>> 4
4
>>> (4)
4

In C#,

> csi //Enters C# interactive mode in VS CMD 2019
> 4
4
> (4)
4

But in Scheme,

scm> 4
4
scm> (4)
Error: int is not callable: 4

We get a similar error message!

You realize that when you surround something in a pair of parentheses, Scheme no longer considers it as an expression but rather would try to call it. Indeed, Scheme would interpret parentheses as procedure calls or pairs. In this case Scheme thinks you are calling the procedure 4 with no argument, but what you want is an expression 4.

Now, for a more complicated example.

In C#,

> Func<int,int> cube = x => x * x * x;
> cube(2);
8
> Func<int,int> cube = (x) => x * x * x;
> cube(2);
8

In Python,

>>> cube = lambda x : x**3
>>> cube(2)
8
>>> cube = lambda (x) : (x**3)
  File <string>, line 1
    cube = lambda (x) : (x**3)
                  ^
SyntaxError: invalid syntax 
>>> cube = lambda x : (x**3)
>>> cube(2)
8

In Scheme,

scm> (define identity (lambda x x))
Error: argument 0 of LambdaProcedure has wrong type (symbol)
scm> (define identity (lambda (x) x))
identity
scm> (define identity (lambda ((x)) x))
identity
Error: non-symbol: (x)
scm> (identity 0)
0
scm> (define identity (lambda (x) (x))) ; This will pass, but it is wrong!
identity
scm> (identity 0)
Error: int is not callable: 0

Can you figure out why Scheme behaves this way? How come Scheme now does want parentheses?

Hint: First argument of lambda should be a symbol type instead of an expression type; first expression of an if should be an expression type.