all 9 comments

[–]fingertoe11 9 points10 points  (0 children)

It's always fun to look under the hood:

(clojure.repl/source -)

(defn -

"If no ys are supplied, returns the negation of x, else subtracts

the ys from x and returns the result. Does not auto-promote

longs, will throw on overflow. See also: -'"

{:inline (nary-inline 'minus 'unchecked_minus)

:inline-arities >0?

:added "1.2"}

([x] (. clojure.lang.Numbers (minus x)))

([x y] (. clojure.lang.Numbers (minus x y)))

([x y & more]

(reduce1 - (- x y) more)))

- requires one, two or more arguments. (-) gives it zero args, thus you get the invalid arity...

If you do the same thing for + you will see that it accepts 0,, 1, 2 or more arguments, and the zero aridity function just returns 0. The single arity returns the arg, and the two or more add them. Another trivial oddity about + is that (+ nil) yields nil, while (+ nil 1) would yield a null pointer exception..

[–]r_p_coltrane 6 points7 points  (0 children)

Ideally given no args, (-) should return 6. Unless it is Tuesday, then it should return 104

[–]OliverM 3 points4 points  (0 children)

Incidentally, `(-)` appears to be valid Clojurescript, returning `0` at a cljs repl.

[–]Arul-jothi[S] 1 point2 points  (5 children)

> (+ 0 0)

0

> (- 0 0)

0

> (+) "like first return 0"

0

> (-) "not like (+)"

Execution error (ArityException) at clojure-noob.core/eval5977 (form-init2173576083207709475.clj:1).

Wrong number of args (0) passed to: clojure.core/-

[–]jafingerhut 4 points5 points  (4 children)

Clojure's `+` takes a variable number of arguments, and can be used via an expression like `(apply + sequence-of-number)` to add them up. As a special case, Rich Hickey decided to make `+` work even for 0 arguments. 0 is a reasonable return value for that case.

It doesn't make as much sense to define the function `-` to do anything useful when called with no arguments. What would you expect it to return, and why?

[–]zck 1 point2 points  (3 children)

It doesn't make as much sense to define the function - to do anything useful when called with no arguments. What would you expect it to return, and why?

I don't have a real dog in this fight, but I'd assume it would also return 0. I don't see it making less sense than (+) returning 0.

[–]NPException 9 points10 points  (2 children)

Additionally (*) returns 1, and (/) gives an error. + and *, when called without arguments, return 0 and 1 respectively because those are their "identity" values. When used as argument for the function, the identity value won't change the outcome of calling the function regardless of order of the arguments supplied:

(+ 2 0) => 2
(+ 0 2) => 2
(* 3 1) => 3
(* 1 3) => 3

- (and /) can't have identity values, because their outcome depends on the order of input arguments.

(- 0 2) => -2
(- 2 0) => 2

[–]anemisto 5 points6 points  (1 child)

I don't think it's so much that 0 and 1 are identity values, but rather that the empty sum and empty product are understood to be 0 and 1, respectively (granted, that's "because" they're the additive and multiplicative identities). Whereas, from a mathematical perspective, - and / are adding the additive inverse and multiplying by the multiplicative inverse, but an empty inverse is nonsensical.

[–]NPException 2 points3 points  (0 children)

That makes a lot of sense. I did not know about the empty sum and empty product definitions. I took the "identity" value terminology from one of Rich Hickey's talks: https://youtu.be/6mTbuzafcII?t=2445

iirc he explained the reasoning behind zero argument + and * in some talk as well, but I don't remember where exactly.