4
$\begingroup$

Why do many programming languages use brackets () for function definitions and calls?

For example, in Python:

def f(): ...

f()

In Go:

func f() { ... }

f()

Many other languages use similar syntax.

$\endgroup$
3
  • 11
    $\begingroup$ Because that is the mathematical notation for applying a function. $\endgroup$
    – alephalpha
    Commented Jun 3, 2023 at 8:54
  • $\begingroup$ @alephalpha thank you! $\endgroup$ Commented Jun 3, 2023 at 8:57
  • $\begingroup$ It's also waaaaaay easier to parse than a simple space after the function name and overall less ambiguous for complex chains of function calls. $\endgroup$
    – Beefster
    Commented Apr 30 at 17:39

3 Answers 3

13
$\begingroup$

Because of math functions.

Like this:

f(x) = x + 5

Wikipedia

$\endgroup$
4
  • $\begingroup$ That said, many functions, such as sin, are often written without parentheses in math. $\endgroup$
    – xigoi
    Commented Oct 15, 2023 at 18:58
  • $\begingroup$ Maths notation never used parentheses unless they are needed to disambiguate things $\endgroup$
    – Chris Dodd
    Commented Apr 21 at 21:46
  • 3
    $\begingroup$ @ChrisDodd Citation please. I searched the web for "introductory algebra functions", and every course I found describes f(x) as the standard or most common notation: mathhints.com/intermediate-algebra/introduction-to-functions and math.libretexts.org/Bookshelves/Algebra/… and symbolab.com/study-guides/boundless-algebra/… and openstax.org/books/college-algebra-2e/pages/… $\endgroup$
    – IMSoP
    Commented Apr 23 at 17:23
  • 1
    $\begingroup$ @ChrisDodd I think you're referring to functions such as trig functions and logarithms. In those cases some people only use parentheses in order to disambiguate things, while others use them all the time. However, when referring to functions that are not those, such as f and g, I've never seen them used without parentheses. $\endgroup$
    – pigrammer
    Commented Apr 28 at 16:01
-1
$\begingroup$

Mathematical Notation

The concept of a "function" which maps a particular input to a particular output originates in mathematics. A common notation for defining and applying functions in mathematics is $f(x)$ where $f$ is the function, and $x$ represents its input.

This dates back far beyond the birth of programming, to the 18th Century; for instance Cajori, "A History of Mathematical Notations", volume 2, paragraph 643 states (hat tip to RobertR for providing this reference in a comment):

The use of parentheses for this purpose occurs in Euler in 1734, who says, "Si $f(x/a+c)$ denotet functionem quamcunque ipsius $x/a+c$"

That these parentheses are to indicate function application, not merely precedence, is clearer in other examples from later in that section:

Another time [Lagrange] wrote Clairaut's equation, $y-px+f(p)=0$, "$f(p)$ dénotant une fonction quelconque de $p$ seul"

Other notations do occur in mathematics, such as reserving Greek letters as function names, and letting $\phi x$ represent application of $\phi$ to input $x$. But using $f(x)$ is probably the notation most people are familiar with, as can be seen in introductory teaching material (some more-or-less random examples: openstax, Symbolab, LibreTexts, MathHints).

Influence of Early Programming Languages

Many early programming languages were explicitly inspired by mathematical notation, and intended for use by those familiar with algebra. For instance, the first manual for FORTRAN, dated 1956 says:

A FORTRAN arithmetic formula resembles very closely a conventional arithmetic formula; it consists of the variable to be computed, followed by an = sign, followed by an arithmetic expression. For example, the arithmetic formula Y = A-SINF(B-C) means "replace the value of y by the value of a-sin(b-c)".

To use a function in such expressions, "The name of the function is followed by parentheses enclosing the arguments (which may be expressions), separated by commas." It's worth noting that FORTRAN also used parentheses for "subscripts" on a variable - accessing elements of a 1-, 2-, or 3-dimensional array. Function names were distinguished from variable names by requiring the last letter to be "F". The original implementation used a 6-bit character encoding, so the limited range of symbols available may have played a part in its design.

At the same time, ALGOL was being designed in committee as an "International Algebraic Language". The Preliminary Report describing it in Communications of the ACM, Volume 1, Issue 12 includes as the first agreed objective:

The new language should be as close as possible to standard mathematical notation and be readable with little further explanation.

In the "Reference Language" used to define ALGOL in that report, the form for functions is denoted as:

Form: $F ⁓ I (P, P, . . . ., P)$ where $I$ is an identifier, and $P, P, . . . . , P$ is the ordered list of actual parameters

Unlike FORTRAN, the reference definition of ALGOL used arbitrary symbols, so the choice of parentheses is not due to a constraint on available characters.

These early languages, and particularly ALGOL, were hugely influential, having a clear influence on the syntax of nearly every procedural language since.

Practical Advantages

As well as the influence of mathematical notation, and early languages, the use of parentheses has a number of practical advantages over other possibilities.

Using single-symbol function names and juxtaposition, as in $\phi x$, would severely limit the number and readability of functions in anything but the smallest programs.

Separating the function name from its arguments with spaces is possible, but leads to an ambiguity between nesting and multiple parameters: does f a b represent f(a, b) or f(a(b)) or f(a)(b), etc. As discussed on this related answer, there are some styles of programming language where this has a natural default, and this style is used.

$\endgroup$
0
-8
$\begingroup$

Warning: This Idea is not Yet Widely Adopted

Below, I describe why we write functions definitions and function calls with parentheses ().

However, I will warn you, that this newer model for programming languages and is not a popular model at the time of my writing.


Parentheses () indicate that a several distinctly different things should be grouped together into one single unified object

Let us take the pow function as an example.

pow is the name for one of the many canonical function some students write when practicing and learning how to write code.

For example, pow(10, 4) will make the computer leave what it was doing, go calculate somthing, and return with a value of 1000.

In the notation pow(base, exp) we are applying a function named pow to one single input, not two separate inputs.

The input to the pow function is an instance of an an anonymous class such that the anonymous class has fields named base and exp.

That is, we might write,

float base = 0.901;
int   exp  = 30;  

# Below this comment, we create an ***anonymous class*** having attributes named `base` and `exp`
# 
# we instantiate the anonymous class and then assign
# the instance to a memory address with label `args`
# 
# The instance has a name, but the class has no name. 

args   = (base, exp) 
result = pow(args)

# COMMENT FOR HUMAN EYES ONLY:
#    result = 0.04382720037 

Digression

You asked what paratheses () do in the definition and call of a function in a computer programme.

I consider that to be a basic thing students encounter early on in their studies of computer programming.

Therefore, the following digression might help you:

float base = 0.901;
int   exp  = 30;  
args   = (base, exp) 
result = pow(args)  
  • args are arguments or inputs to a function

  • int is integer or whole number 1, 2, 3,891, et cetra...

  • Electronic computers delete all comments before translating code into machine language. Electronic computers cannot read or understand most comments.


In our newer model of programming language syntax, all functions accept ONE input and only one input.

Consider this code written to implement somthing known as a btree:

 def __print_backend(
        self,
        nid=None,
        level=ROOT,
        idhidden=True,
        filter=None,
        key=None,
        reverse=False,
        line_type="ascii-ex",
        data_property=None,
        sorting=True,
        func=print,
    ):
    pass 

In an old-fashioned view of things, the function has 11 inputs.

However, one of many newer views of things is to represent the function as having one single input, such that that single object has 11 separate attributes.

Consider the event in which a computer programmer writes the following piece of code:

foobar(arg1, arg2, arg3)

For our example function named foobar, the input arguments 1, 2 and 3 are all bundled, by a compiler, into a single anonymous class object.

At the time of my writing anonymous class objects are not very popular.

However, functions of no name (anonymous functions) are very popular in some programming languages such as python and the Matrix Laboratory (MatLab).

The purpose of parentheses in functions is to bundle together smaller objects into a larger, more complex, instance of an anonymous class.

In turn, one of the advantages to using parentheses () to create anonymous classes is so that we can use in-fix lexors/tokenizers instead of a pre-fix lexors, tokenizers, and/or parsers.

pow(base, exp) is not a pre-fix function applied to two inputs.

Rather, pow is the left-most argument to the anonymous in-fix operator.

anonymous in-fix operator
├─ pow
├─ instance of an anonymous class (base, exp)
│  ├─ base
│  ├─ exp

When studying arithmetic, children learn that (10)(5) = 10*5.

The product of 10 and 5 need not have a multiplication sign explicitly written.

Likewise, 10y is the same thing as 10 × y

PICTURE OF A SYNTAX TREE FOR PARSING POW(BASE, EXP)

Instead of parsing characters, I recommend parsing transitions between characters.

pow(base, exp)

transition from character to character description
po transition from p to o
ow transition from o to w
w( transition from w to (
(b transition from ( to b
ba transition from b to a

Transitioning from w to ( should create a token for the implicit multiplication operator, or perhaps, we might call it the anonymous infix operator.


$\endgroup$
12
  • 4
    $\begingroup$ I don't get what this is supposed to say. It seems to be rather about semantic interpretation of function calls, not necessarily of its syntax. For many parts it is hard to tell what is intended to be your own view as opposed to that of (developers) of many programming languages. Please consider to edit for clarity. $\endgroup$ Commented Oct 14, 2023 at 8:37
  • 1
    $\begingroup$ "Anonymous class objects are not very popular" this is false: most languages that are object oriented also have anonymous class syntax. "Anonymous functions are very popular in some programming languages" also false. Most widely used languages these days (except C) have anonymous function syntax. $\endgroup$
    – Seggan
    Commented Oct 14, 2023 at 14:06
  • 1
    $\begingroup$ I really like this approach for handling (), it's one I plan on going with for a future language I'm making (mainly since it means function calls with anonymous structs are a convenient way to do named arguments). But I don't think it this is the reason most, if any, existing languages have for this syntax. $\endgroup$ Commented Oct 14, 2023 at 15:09
  • 2
    $\begingroup$ @SamuelMuldoon All those are reasons why a developer might want to use function(arg1, arg2, ...) syntax – notably not binding ones, as the semantics you describe aren't how many languages treat things and there are several languages that show it can be done completely differently. I don't see how those are reasons that many specific, existing languages have chosen to use that syntax. In fact, the intro of this answer ("this newer model for programming languages and is not a popular model at the time of my writing") suggests these consideration aren't why the syntax is commonly used. $\endgroup$ Commented Oct 16, 2023 at 10:29
  • 3
    $\begingroup$ What you call an “anonymous class object” is present in many modern languages and usually called a tuple. A few programming languages have functions systematically take a tuple as a single argument, notably Standard ML. (Many ML-like languages also have functions take a single argument, but they favor currying for multiple arguments.) Lisp, one of the oldest programming languages, also has arguments packed into a single data structure; in Lisp, that's a list, because Lisp is built around lists. But most languages don't do that because packing arguments transparently just isn't that useful. $\endgroup$ Commented Oct 16, 2023 at 20:53

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .