What's Function, What's Operator?

, ,

Typically, we understand what “function” and “operator” mean, but programer may have a hard time explaining them, and mathematician may never thought about it. Here, we clarify a bit on the meaning of the word “function” and “operator”, their context, their relation.

Function is a Mathematical Concept

Function you probably understand. A function takes a input, and output a value for a given input. The inputs are called “parameters”. A specific set of input is called “arguments”. The number of parameters of a function is called the function's “arity”. So, for example, the function “sin” has arity 1. A constant, such as 35, π, can be considered as functions of no parameter, so they are functions of arity 0. A function of 2 parameters, such as f(x,y) := x+y has arity 2.

Function is a mathematical concept. Viewed in another way, it's a map from one space (aka set) to another.

Operator is About Notation

A operator, is less of a mathematical concept, but more of a concept of notation. Or, in computer language contexts, a element of syntax. A “operator” is a symbol (or symbols) that are written to indicate operations. For example, we write 1+2, the “+” is a operator, and the “1” and “2” are its “operands”. Mathematically, operator is a function that acts on its operands. The operands are the arguments of the function.

Binary Operators

Typically, operators takes 2 arguments, the left and right of the symbol. ⁖ 2×3, 3/4, 2^3, union {3,4}∪{2,4,1}, etc.

Unary Operators

But there are also 1-argument operators. For example the minus sign -3, and the logical not ¬ sign, the factorial 3!, square root √3.

Multi-symbol Operators

Operators can also involve other forms with more symbols. For example, the absolute sign |-3|, floor ⌊3.8⌋ uses a bracket, summation ∑ takes 4 arguments: a expression, a variable, and start and end values. The anti-derivative (aka indefinite integral) ∫ takes 2 arguments: a expression and a symbol. In traditional notation, the integration operator involves 2 symbols, ∫ and ⅆ. For example, we write ∫ sin(x) ⅆx .

Implicit Operators

Operator can be a bit complicated. For example -3 can be interpreted in several ways. We can think of the minus sign as unary operator acting on the argument 3. So, mathematically, it is a function of 1 arity that returns the addictive inverse of the element 3. Or, we can interprete it as one single entity, a element of Reals denoted -3. When we write 3-2, the ways to interprete it gets a bit more complex. One way to think of it as a notation shorthand for 3 + (-2). The -2 part can be thought of as before. Another way is to think of - as a binary operator on 3 and 2, but this seemingly simple interpretation is a bit complex. Because, what is math definition of the minus binary function? I'm not sure how it can be defined in terms of algebra without ultimately thinking of it as additon of 2 elements, one being a addictive inverse. The other way is to think of it as a real line, moving the first argument to the left by a distance of the second argument. Of course ultimately these are equivalent, but i can't think of a simple, direct, interpretation that can serve as a math foundation. Also, this is directly related to how does one interprete division, such as 3/2.

The multiplication operator also gets complicated. For example, when we write 3 x, it usually means 3*x. The space acts as implicit multiplication sign. But when we write 3 +2, the space there has no significance. When we write 3x, even there is no space nor any operator, but we mean 3*x. As a computer language syntax based on traditional notation, the parsing rule is not trivial.

Operator Stickiness

There's also the concept of “operator stickiness” (aka “operator precendence”) at work that makes expressions with operators more concise. When we write3△4▲5, how do you know it's (3△4)▲5 or 3△(4▲5)? The concept of operator stickiness is needed to resolve that. Otherwise, you'll need to always write 3+(4*5) instead of the simpler 3+4*5. But this again, also introduced more complexity. When you have a expression of tens of different operators, it becomes a problem of remembering the stickiness grammar for each operator.

(in practice, when you are not sure about the procedence, you usually just use explicit priority indicator by parens. This often happens in programing with logic operators (⁖ and &&, or ||, not !.) Forgetting Operator Precedence is a common error in programing. In written math for human communication, it is prone to miscommunication.)

Operator is tied to Notation

Because the concept of “operator” more has to do with syntax and notation, and when considering traditional math notation of writing in “2-dimensions”, also the fact that traditional math notation has a lot ambiguities, it gets a bit complicated and not as imprecise as we like. 〔➤ The Problems of Traditional Math Notation

Mathematically, operator and function are the same thing.

Math function in traditional notation has the form ⁖ sin(x), f(x,y), where the things inside the paren are its parameter/arguments, and function name is placed to the left.

Operators are useful because writing everything out in full function notation gets very cumbersome and hard to read. For example, we write 3+4*5 instead of plus(3,times(4,5)) or +(3,*(4,5)).

Here's a example of traditional notation using operators:

-b+√(b^2-4 a c)/(2 a)

If you don't allow space as implicit multiplication sign, then you have to write:

-b+√((b^2)-4*a*c)/(2*a)

If you don't allow the concept of operator precedence, then you have to write:

(-b)+(√((b^2)-((4*a)*c))/(2*a))

If you prefer the structural clarity of the traditional function notation f(x), you have to write:

/(+(-(b),√(+(^(b,2),-(*(4,a,c))))),*(2,a))

If you prefer words than symbols, as traditionally practiced when writing out functions, you have to write:

divide(add(minus(b),sqrt(add(power(b,2),minus(times(4,a,c))))),times(2,a))

The notation using operators is much concise, readable, but at the cost of relatively complex lexical grammar. The full functional notation is precise, grammatically simple, but difficult to read.

In math context, it's best to think of functions instead of operator, and sometimes also use a uniform function notation, where all arguments are explicitly indicated in one uniform way.

Here's what Wikipedia has to say about operators: Operation (mathematics). Quote:

An operation ω is a function of the form ω : X1 × … × Xk → Y. The sets Xj are called the domains of the operation, the set Y is called the codomain of the operation, and the fixed non-negative integer k (the number of arguments) is called the type or arity of the operation.

Note that it doesn't really speaks of “operators”, but speaks of “operations”, and flatly defines operation as a function.

Traditional Function Notation “f(x)” Isn't Perfect

Note that, even the functional notation such as sin(x), isn't perfect.

Problem of Functions Returning Functions

Normally, with full function notation, you'd expect that execution order of operations clearly corresponds to the nesting structure. For example, in our example before:

divide(add(minus(b),sqrt(add(power(b,2),minus(times(4,a,c))))),times(2,a))

The inner-most parts are evaluated first.

But there's a problem when a function returns a function. For example, the derivative takes a function and returns a function. We might write:

derivative(f)

Now, if we want to evaluate the result at 3, then we might write:

derivative(f)(3)

You can see that the notation no longer nests. The operator precedence issue is back. Now, you need to have a slightly more complex notion of precedence to work out the syntax.

One solution to this is the lisp language's syntax. In lisp syntax, everything is written inside a paren. The first element is the function name, the rest is its arguments. So, sin(x) would be written as (sin,x). (comma is used for separator here) Our derivative example would then be:

((derivative,f),3)

In this way, the syntax remains a pure nested form, and the nesting structure always corresponds to order of evaluation.

Our formula example in fully nested syntax is:

(/,(+,(-,b),(√,(+,(^,b,2),(-,(*,4,a,c))))),(*,2,a))

We could change the comma separator to space. So, it would look like this:

(/ (+ (- b) (√ (+ (^ b 2) (- (* 4 a c))))) (* 2 a))

(Note: actual lisp language's syntax is not 100% regular. Many of its syntax does not have the form (a b c …). See: Fundamental Problems of Lisp.)

Syntax Design for Computer Languages

Mixing Operator Syntax with Full Function Notation Syntax

In most computer language, they allow both the operator and full function syntax. For example, you can write (sin(x))^2+3. (almost all languages do this; ⁖ C, C++, C#, Java, Pascal, Perl, Python, Ruby, Bash, PowerShell, Haskell, OCaml. The only exception is lisps.)

(Though, almost all computer languages do not have a regular syntax, in fact, none of any major computer lang has a syntax specification. The closest one that has a somewhat regular and simple syntax grammar is Mathematica. See: Concepts & Confusions of {Prefix, Infix, Postfix, Fully Nested} NotationsA Programing Language that Does: Math Notation (Mathematica, TeX), Proof System (Coq, HOL), Computer Algebra System.)

Mixed form is normal, and most flexible. Because, it is impractical for every function to have a associated operator symbol. And, writing everything in nested brackets is not readable and hard to write too. The question is, is it possible to design a syntax, that is fully regular with a very simple lexical grammar, and easy to read and write?

The following are half written, still work in progress

Here's a explanation of one approach. (much based on syntax of Mathematica)

Start with a fully nested syntax. So, everything is in a fully nested functional notation, like this: (a b c …).

For some function names or builtin names, we give them a operator symbol. For example, say we have a function named plus (plus,2,3). Now, suppose we assign the symbol “+” as a operator to “plus”. So, when we have △+▲, it is syntactically equivalent to (plus,2,3)

Unique Semantics for Each Symbol

Note first that the char paren is used for 2 purposes. ① as a operation priority grouping indicator. ② as delimiter for function's arguments.

So, if the context is designing a consistent math notaton or computer language syntax, this we need to fix. One way, is by insisting that each symbol used only has one unique purpose, and not be dependent on adjacent symbols. So, we might insist that, function parameter delimiters should use the square bracket. Like this sin[x]. (this is what Mathematica does)

blog comments powered by Disqus