On Jun 18, 2010, at 6:47 AM, Carson wrote:

Just tried out num branch and I really like how easy it is to be
fast!  However...

Consider:

(defn fact [n] (if (zero? n) 1 (* n (fact (dec n)))))
(defn twice-fact [n] (fact (fact n)))
(defn bad-twice-fact [n] (fact (-> n fact range last inc)))

user=> (fact (fact 5))
java.lang.ArithmeticException: integer overflow (NO_SOURCE_FILE:3)
user=> (fact (fact 5N))
6689502913449127057588118054090372586752746333138029810295671352301633557244962989366874165271984981308157637893214090552534408589408121859898481114389650005964960521256960000000000000000000000000000N
user=> (twice-fact 5)
java.lang.ArithmeticException: integer overflow (NO_SOURCE_FILE:5)
user=> (twice-fact 5N)
6689502913449127057588118054090372586752746333138029810295671352301633557244962989366874165271984981308157637893214090552534408589408121859898481114389650005964960521256960000000000000000000000000000N
user=> (bad-twice-fact 5)
java.lang.ArithmeticException: integer overflow (NO_SOURCE_FILE:7)
user=> (bad-twice-fact 5N)
java.lang.ArithmeticException: integer overflow (NO_SOURCE_FILE:8)

Don't buy it. That's the whole point of BigInt contagion. If fact and foo
are correctly written this will work.

BigInt contagion doesn't help if in some convoluted manner a BigInt's
value is used to construct a primitive sufficiently large that later
causes an overflow.

It'd sure be nice if I could just write ((safe bad-twice-fact) 5) and
get back a BigInt.  Maybe ((safe foo) x) can ensure all arguments and
return values of function foo are boxed, and recursively, ensures
boxing of arguments and return values for all functions called by foo,
etc.  Is that possible? Would that guarantee safety?


------
While range could be written differently, this is tantamount to saying - if I use a bigint to lookup another number in some mapping, it might not be a bigint. Yes, ok, but not a real issue.

-------------
Note - I don't mean to single you out, as others are using the same language, but I find this whole characterization of throw-on-overflow being somehow 'unsafe' to be a bit specious.

I want it to be perfectly clear to everyone, this is not a choice between good math and bad math, i.e. C/Java style truncating/wrapping of results. That will never be the default. Such silent truncation/ wrap is truly unsafe, and often the proposed alternative. It was a surprising result that optimizations of hot spot, combined with pipelining and speculative execution on modern processors, makes the overflow checking a very minor overhead above the raw operations, and, in my mind, a third, new, viable and safe high-performance option.

Is a program that might throw an exception unsafe? If so, no Java program is safe.

Is a vector that throws an exception when asked to store something at an index out of range, rather than grow to accommodate it, unsafe? This is in many ways similar - you are creating a result that doesn't fit, and need to be using a bigger container.

So, let's go easy on the hyperbole. The behavior might not be what you desire, but it is not unsafe.

Rich

--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to