36

Having looked at some languages for functional programming, I always wondered why some fp-languages use one or more whitespace characters for function application (and definition), whereas most (all?) imperative/object-oriented languages are using parentheses, which seems to be the more mathematical way. I also think that the latter style is much more clear and readable than without the parens.

So if we have a function f(x) = x² there are the two alternatives to calling it:

  • FP: f x

    Examples:

    • ML, Ocaml, F#
    • Haskell
    • LISP, Scheme (somehow)
  • Non-FP: f(x)

    Examples:

    • Almost all imperative languages (I know, see the comments/answers)
    • Erlang
    • Scala (also allows "operator notation" for single arguments)

What are the reasons for "leaving out" the parentheses?

20
  • 10
    To make it more confusing, erm, I meant succinct.
    – Den
    Jul 8, 2014 at 7:53
  • 11
    @Den if you learn haskell, the syntax will be one of the least confusing things :p Jul 8, 2014 at 9:49
  • 5
    You do realize the irony of saying that using parentheses would be more mathematical and then using the exponentiation function as an example? Jul 8, 2014 at 10:43
  • 12
    @Den you are doing yourself harm by rejecting a language because of its syntax. Surely you had no trouble learning xml or sql (those are not general purpose languages, but they define their own syntax). Jul 8, 2014 at 11:08
  • 7
    I would like to point out that shell scripts (e.g. bash) generally don't use parameters to call commands. PowerShell sort of has the worst of both worlds in that functions are declared with parentheses and called without them. Jul 8, 2014 at 14:30

6 Answers 6

59

which seems to be the more mathematical way

functional languages are inspired by lambda calculus. In this field, parentheses are not used for function application.

I also think that the latter style is much more clear and readable than without the parens.

Readability is in the eye of the beholder. You are not used to reading it. It is a bit like mathematical operators. If you understand the associativity, you only need a few parens to clarify the structure of your expression. Often you don't need them.

Currying is also a good reason to use this convention. In haskell, you can define the following:

add :: Int -> Int -> Int
add x y = x + y

x = add 5 6 -- x == 11
f = add 5
y = f 6 -- y == 11
z = ((add 5) 6) -- explicit parentheses; z == 11

With parens, you could use two convention: f(5, 6) (not curried) or f(5)(6) (curried). The haskell syntax helps to get used to the currying concept. You can still use a non-curried version, but it is more painful to use it with combinators

add' :: (Int, Int) -> Int
add' (x, y) = x + y
u = add'(5, 6) -- just like other languages
l = [1, 2, 3]
l1 = map (add 5) l -- [6, 7, 8]
l2 = map (\x -> add'(5, x)) l -- like other languages

Notice how the second version forces you to register x as a variable, and that the subexpression is a function which takes an integer and adds 5 to it? The curried version is much lighter, but also considered by many as more readable.

Haskell programs makes extensive use of partial application and combinators as a mean of defining and composing abstractions, so this is not a toy example. A good function interface will be one where the order of parameters provides a friendly curried usage.

Another point: a function without parameters should be called with f(). In haskell, since you only manipulate immutable lazy evaluated values, you just write f, and consider it as a value which will need to perform some computations when needed. Since its evaluation won't have any side effect, it makes no sense to have a different notation for the parameterless function and its returned value.

There are also other conventions for function application:

  • Lisp: (f x) -- prefix with external parentheses
  • Forth: x f -- postfix
5
  • 7
    Minor nitpick: the terms are "currying" and "curried", not "currification" and "currified".
    – Doval
    Jul 8, 2014 at 11:22
  • "non curried" what's a non-curried function in haskell ?
    – Ven
    Jul 9, 2014 at 11:09
  • 3
    @user1737909 A function that takes a tuple as an argument.
    – Doval
    Jul 9, 2014 at 12:02
  • 1
    @Doval Actually it should be “schönfinkeling” and “schönfinkeled”. But oh well, history always defines the winner retrospectively.
    – Profpatsch
    Sep 14, 2014 at 15:28
  • 1
    Thinking about a parenthesized currying syntax, something like f(a, ,b) or add(a, ) or add(, b) would seem more flexible by default.
    – phresnel
    Jan 3, 2018 at 11:08
25

The basic idea is to make the most important operation (function application) easiest to read and easiest to write. A space is very unintrusive to read and very easy to type.

Note that this is not specific to functional languages, e.g. in Smalltalk, one of the first OO languages and languages inspired by it (Self, Newspeak, Objective-C), but also in Io and languages inspired by it (Ioke, Seph), whitespace is used for method calls.

Smalltalk-style:

anArray sort
anArray add: 2
aString replace: "a" with: "b"

(In the latter case, the name of the method is replace:with:.)

Io-style:

anArray sort
anArray add(2)
aString replace("a", "b")

Scala also allows whitespace for method calls:

foo bar(baz)

And leaving off the parentheses if there is only one argument:

foo bar baz

Ruby also allows you to leave off the parentheses:

an_array.sort
an_array.add 2
a_string.replace "a", "b"

using parentheses, which seems to be the more mathematical way

Not really:

f(x)
sin x
x²
|x|
x!
x + y
xy
½

Math notation has evolved over a long time in a horribly inconsistent way.

If at all, functional languages take their inspiration from λ-calculus where function application is written using whitespace.

1
  • 3
    There is also an argument for economy of editing. In particular, functional languages typically support composition directly. Putting parentheses around the function instead of the argument makes sense. You only have to do it "once": (e . f . g) x as opposed to e(f(g(x))). Also, Haskell, at least, would not stop one from doing f(x) instead of f x. It's just not idiomatic.
    – nomen
    Jul 8, 2014 at 22:34
18

Parenthesis for function application is just one of the many saddles Euler left us with. Like anything else mathematics needs conventions when there are several ways to do something. If your mathematical education only extends as far as a non-maths subject at university then you probably aren't too familiar with the many fields where function application happens happily without any of these nonsense brackets (e.g. Differential Geometry, Abstract Algebra). And you don't even mention functions that are applied infix (almost all languages), "outfix" like taking a norm, or diagrammatically (Befunge, Algebraic Topology).

So in answer I'd say it's due to a much higher proportion of functional programmers and language designers having extensive mathematical education. Von Neumann says "Young man, in mathematics you don't understand things. You just get used to them.", certainly this is true of notation.

6
  • 8
    Don't even get me started on f(x) vs. sin x vs. vs. |x| vs. x! vs. x + y vs. xy vs. ½ vs. a summation vs. an integral vs. … Jul 8, 2014 at 15:28
  • 2
    +1 for the von Neuman quote. +1 for the rest of the answer, but I can't give +2. :(
    – pvorb
    Jul 9, 2014 at 0:17
  • 3
    I catch a hint of elitism here; I dispute the neutrality of "functional programming language designers are better educated". Jul 9, 2014 at 6:59
  • 7
    @CaptainCodeman He says more educated in mathematics, a statement with which I agree. At least when it comes to Haskell, you can notice that both the concepts are more mathematical in nature and the community is more mathematically inclined as well. They're not more intelligent, just better educated in mathematics.
    – Paul
    Jul 9, 2014 at 11:18
  • 5
    @CaptainCodeman No, since he never implied they are more educated in general, just more educated in mathematics. That's exactly what he said: "extensive mathematical education". :)
    – Paul
    Jul 9, 2014 at 11:38
9

Although there's a lot of truth in Simon's answer, I think there's also a much more practical reason. The nature of functional programming tends to generate a lot more parentheses than imperative programming, due to function chaining and composition. Those patterns of chaining and composition also usually happen to be able to be unambiguously represented without parentheses.

The bottom line is, all those parentheses get annoying to read and track. It's probably the number one reason LISP isn't more popular. So if you can get the power of functional programming without the annoyance of excess parentheses, I think language designers are going to tend to go that way. After all, language designers are also language users.

Even Scala allows the programmer to omit parentheses in certain circumstances, which happen to come up fairly frequently when programming in a functional style, so you sort of get the best of both worlds. For example:

val message = line split "," map (_.toByte)

The parens at the end are necessary for associativity, and the others are left off (as well as the dots). Writing it this way emphasizes the chained nature of the operations you're performing. It might not be familiar to an imperative programmer, but to a functional programmer it feels very natural and flowing to write this way, without having to stop and insert syntax that adds no meaning to the program, but is just there to make the compiler happy.

3
  • 2
    "The bottom line is, all those parentheses get annoying to read and track. It's probably the number one reason LISP isn't more popular.": I do not think parentheses are a reason for Lisp not to be popular: I do not think they are particularly difficult to read, and I find other languages have a much more awkward syntax.
    – Giorgio
    Jul 8, 2014 at 16:57
  • 2
    LISP syntax largely makes up for the annoying parentheses with its super-high degree of orthogonality. That just means it has other redeeming features that make it still usable, not that the parens aren't annoying. I understand not everyone feels that way, but the vast majority of programmers I've met do. Jul 8, 2014 at 17:08
  • "Lost In Stupid Parentheses" is my favorite LISP backronym. Computers can also use the humane way to specify code blocks and drop the redundancy, as in languages like Wisp. Apr 9, 2016 at 20:11
4

Both premises are wrong.

  • These functional languages don't use space for function application. What they do is simply parse any expression that comes after a function as an argument.

    GHCi> f 3
    4
    GHCi> f(3)
    4
    GHCi> (f)3
    4

    course if you use neither a space nor parens then it normally won't work, simply because the expression isn't properly tokenised

    GHCi> f3

    <‌interactive>:7:1:
        Not in scope: ‘f3’
        Perhaps you meant ‘f’ (line 2)

    But if these languages were restricted to 1-character variable names then it would work too.

  • Nor do mathematics conventions normally require parentheses for function application. Not only will mathematicians often write sin x – for linear functions (usually called linear operators then) it's also very much usual to write the argument without parens, perhaps because (much like any function in functional programming) linear functions are often handled without directly supplying an argument.

So really, your question boils down to: why to some languages require parentheses for function application? Well, apparently some people, like you, consider this more readable. I strongly disagree with that: one pair of parens is nice, but as soon as you have more of two of them nested it starts to get confusing. Lisp code demonstrates this best, and pretty much all functional languages would look similarly cluttered if you needed parens everywhere. This doesn't happen so much in imperative languages, but mainly because these languages aren't expressive enough to write concise, clear one-liners in the first place.

2
  • Got me, the question is not perfect. :) So the conclusion to draw is: "Parentheses don't scale."
    – pvorb
    Jul 9, 2014 at 0:13
  • 2
    Nor are non-functional languages that unanimous in requiring parentheses; for a few examples, Smalltalk has object method: args, Objective C has [object method: args], and Ruby and Perl both allow omitting parentheses in function and method calls, only requiring them to resolve ambiguity.
    – hobbs
    Jul 9, 2014 at 5:39
2

A small historical clarification: the original notation in mathematics was without parenthesis!

The notation f x for an arbitrary function of x was introduced by Johan Bernoulli around 1700 shortly after Leibniz started talking of functions (actually Bernoulli wrote ϕ x). But prior to that many people where already using notations like sin x or l x (the logarithm of x) for specific functions of x, without parenthesis. I suspect that's the reason many people today still write sin x instead of sin (x).

Euler, who was a student of Bernoulli, adopted Bernoulli's ϕ x and changed the greek into a latin letter, writing f x. Later he noticed that it might be easy to confuse f for a "quantity" and believe that f x was a product, so he startet writing f:x. Hence the notation f(x) is not due to Euler. Of course Euler needed parenthesis for the same reason we still need parenthesis in functional programming languages: to distinguish for example (f x) + y from f (x+y). I suspect that people after Euler adopted the parenthesis as a default because they mainly saw Euler write compound expressions like f (ax+b). He seldomly wrote just f x.

Fore more on this see: Did Euler ever write f(x) with parenthesis?.

I don't know if designers of functional programming languages or the inventors of the lambda calculus were aware of the historical roots of their notation. Personally I find the notation without parenthesis more natural.

Not the answer you're looking for? Browse other questions tagged or ask your own question.