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.
+
function in Python is the Pythonsum
function, not the Python+
operator. If you ask Python to add nothing by typingsum([])
, it will do exactly the same thing that the elisp+
function does: it will return 0.+
as asum
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*
andproduct
.+
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, thensum(a + b) == sum(a) + sum(b)
for any two integer listsa
andb
. Sincea == a + []
, thensum([]) == 0
so thatsum(a) == sum(a) + sum([])
.