# elisp: Why does + without parameters return 0?

In elisp `+` function without parameters gives 0, `(+) ==> 0`. `*` function without parameters give 1: `(*) ==> 1`. Only `(/)` gives error: `wrong number of arguments`.

But in Python entering `+` without summands give an error: `+ ==> SytntaxError: incomplete input`.

I was wondering what were the justifications for this behavior in elisp.

elisp arithmetic operators

Definition of `+`

(+ &rest NUMBERS-OR-MARKERS)

Return sum of any number of arguments, which are numbers or markers.

• emacs.stackexchange.com/tags/elisp/info
– Drew
Dec 17, 2023 at 18:53
• The closest equivalent of the elisp `+` function in Python is the Python `sum` function, not the Python `+` operator. If you ask Python to add nothing by typing `sum([])`, it will do exactly the same thing that the elisp `+` function does: it will return 0. Dec 17, 2023 at 19:36
• As @TannerSwett (in the above comment) and @shynur (in a comment below his answer) have said, you should think of `+` as a `sum` function, not as a binary operator. The mathematical convention (and it is just a convention, although a very useful one) is that an empty sum has the value 0 and `+` follows that convention. The reason it is useful is that it allows you to prove things without having to deal with the case of the empty list separately from the case of the non-empty list: it makes proofs shorter and easier. Similarly for `*` and `product`. Dec 18, 2023 at 2:56
• IMHO this is a Lisp question, not just elisp, as @Drew has already noted. If I encountered a Lisp that didn't behave this way, I'd wonder what else was broken. Dec 18, 2023 at 22:05
• The brief answer is that `+` acts as a monoid homomorphism. I don't know how to cleanly express that in Lisp, but in Python, it just means that since integers under addition with identity 0 form one monoid and lists with concatenation and identity `[]` form another, then `sum(a + b) == sum(a) + sum(b)` for any two integer lists `a` and `b`. Since `a == a + []`, then `sum([]) == 0` so that `sum(a) == sum(a) + sum([])`. Dec 19, 2023 at 16:41

Math. The sum of nothing is obviously nothing. The product of nothing is more mysterious, because it isn’t nothing. But if you look closely you will soon notice that in both cases you get back the identity element for the operation. The identity element for addition and subtraction is zero, because adding or subtracting zero gives you back whatever you started with. The identity element for multiplication (and division) is one, because multiplying or dividing by one gives you back whatever you started with.

Why do the identity elements matter, you ask? Consider the following sums:

elisp simplifies to
`(+ x x x x)` = 4x
`(+ x x x)` = 3x
`(+ x x)` = 2x
`(+ x)` = 1x
`(+)` = 0x

As you can see, the sum of an empty list really is zero. This is a restatement of the proof offered on Wikipedia, which you might take a look at if you want references. A similar proof works for products:

elisp simplifies to
`(* x x x x)` = x⁴
`(* x x x)` = x³
`(* x x)` = x²
`(* x)` = x¹
`(*)` = x⁰

Anything raised to the zeroth power is one, so the product of an empty list is also one. It’s the only number that makes sense there. Again there is a proof on Wikipedia, with additional information relevant to set theory and category theory, along with references.

In response to your comment that you still don’t see why `+` doesn’t complain about missing arguments, look again at the declaration:

``````(+ &rest NUMBERS-OR-MARKERS)
``````

You can see that it is defined to take no required arguments, and to put all additional arguments into a list called `NUMBERS-OR-MARKERS`. So you can see right away that it will not give you an error if you don’t pass in any arguments.

• Interesting. I didn't realize `(-)` was zero in Elisp. `(+)` and `(*)` make sense to me, but having the non-commutative one accept no arguments is kind of strange, especially since `(- x)` is a fundamentally different operation than `(- x y)`. Common Lisp rejects `(-)`, so it's interesting that Elisp chose to diverge from its inspiration on this. Dec 17, 2023 at 19:56
• Silvio: Elisp was based on MacLisp: maclisp.info/pitmanual/number.html#9.12 (there is also a deviation from that in elisp (or at least in modern elisp), but it's regarding no-argument and single-argument division, rather than subtraction). Dec 17, 2023 at 21:15
• "The sum of nothing is obviously nothing": But `0` is not "nothing". Dec 17, 2023 at 22:47
• @U.Windl I agree that `0` is not nothing, at least for lisp. `(+ nothing nothing)` gives “unbound variable” error. `(+ “nothing” “nothing”)`gives type error: “nothing” is not a number. Dec 18, 2023 at 8:22
• We have now descended into sophistry... Dec 18, 2023 at 17:56

This is a very natural outcome.

For instance,

``````(+ 2 10 30)
``````

you know the result is `42`, right?
So, what if we remove the `10`?
Obviously, the result will decrease by `10`, meaning the result of

``````(+ 2 30)
``````

is `32`.
Then what if we remove the `2` from the above expression?
Exactly, the result of

``````(+ 30)
``````

will decrease by `2`. I.e., the result is `30`.
And we finally remove the `30`; obviously the result of

``````(+)
``````

is `30 - 30 = 0`.

The same logic can be applied to `*`.
(Even to the factorial, which is that exclamation mark `!`. This is why `0! = 1`.)

• and why `x^0 = 1`, etc. Mathematical intuition. Dec 17, 2023 at 14:56
• "what if we remove the 40..." I am not sure. If we remove one of the parameters + function should complain that an argument is missing. (like in Python). So in elisp, it seems, this convention was implicitly added to +. I don't see it in the formal definition of +. (I added that to the question.) Dec 17, 2023 at 16:06
• @zeynel The plus sign here actually represents the sum (sigma) Dec 17, 2023 at 19:36
• Actually I think `+` with less than two arguments should be `nil`. Dec 17, 2023 at 22:46
• This is a much better answer than the "sum of nothing is obviously nothing" one. Dec 18, 2023 at 11:07

This is due to associativity of addition:

``````Sum(Array1) + Sum(Array2) = Sum(concat(Array1, Array2))
``````

If Array1 is empty, we get

``````Sum(Empty) + Sum(Array2) = Sum(Array2)
``````

thus `Sum(Empty)=0`.

The python error is due to deficiencies of syntax, not any math. Even in python `sum([])` is 0.

• This also explains why `(*)` returns `1`, and Common Lisp `(every #'predicate '()` returns `T`. Dec 17, 2023 at 22:45
• I agree with the recursive definition, but why isn't it required that `+` has at least two arguments? Adding an infinite series of "Sum(Empty) +" to a sum doesn't really help. Dec 17, 2023 at 22:50
• @U.Windl: why should we put an arbitrary limitation on `#'+`?
– sds
Dec 18, 2023 at 14:30

1. Why are `+` and `*` multiple-arity functions and they allow even zero arguments?

2. Why isn't this the case for `/` (division)?

Others have answered #1: both `+` and `*` have an identity element: 0 for `+` and 1 for `*`. 0 + N = N, and 1 * N = N, for any number N.

The answer for #2 is that `/` (division) has no identity element. There's no number N such that for any number M, N/M = M.

I found Empty sum and Empty product.

So `+` and `*` do not follow the typical binary operator rules, but the mathematical definitions of sum and product.

The "syntax" for (e-)lisp `+` is just like that of any other function call `(func args...)`, i.e. it is a list where the first element is the function to call, and the remainder of the list is the argument(s) to pass. The only oddity is that the name of the function is made up of special characters rather than alphanumeric ones. As such then, the arguments can have any count including zero.
The restriction you see in Python is a syntactic one: The `+` operator is binary and requires two operands (actually, I'm not sure if unary prefix `+` exists). This restriction forbids having no arguments, but equally forbids having more than two. You can add several values using several-1 `+` operations which is just iteratively applying the binary addition operator, but there is no syntax that uses a single `+` and more than two operands. As some have mentioned, the closest thing is the `sum` function, which follows the same behaviour (in this aspect, anyway) as the `+` function in (e-)lisp.
As far as `elisp` is concerned this is what I understood from answers and comments:
`(+ 3)` and `(+)` are hardcoded into `+` function's source code to give `(+ 3) ==> 3` and `(+) ==> 0` to conform to mathematical conventions. The rest is the subject of mathematics. So, there is nothing else to discuss as far as `elisp` is concerned.