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.
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.
sin, are often written without parentheses in math.
$\endgroup$
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$
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).
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 formulaY = 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.
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.
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.
() indicate that a several distinctly different things should be grouped together into one single unified objectLet 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
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)
argsare arguments or inputs to a function
intisintegerorwhole number1, 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
Instead of parsing characters, I recommend parsing transitions between characters.
pow(base, exp)
transition from character to character description potransition from ptooowtransition from otoww(transition from wto((btransition from (tobbatransition from btoa
Transitioning from w to ( should create a token for the implicit multiplication operator, or perhaps, we might call it the anonymous infix operator.
pow represents a function pointer. I wouldn't necessarily conceive the call operator as an "anonymous infix operator". In most languages, the call operator effectively has a compound syntax (that can't be broken down further into elements), with the left bracket separating the first two operands, commas separating further operands, and the right bracket unambiguously terminating the list of operands on the right (including coping with the case of calling a niladic function, where there is only one operand to the operator).
$\endgroup$
(), 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$
w(b inside of the string of text pow(base, exp) will eventually resolve to be the call-operator. However, consider 3(1 + 2) and (3)(1) + 2 and 10(x + y) when the string of text located to the left of the parentheses is numbers only, such as 10, then the anonymous infix operator will resolve to multiplication operator for float, integers, or other numeric data-types.
$\endgroup$