Marek Kubica <[email protected]> writes:
Hi Marek,
> Yeah, the problem that I see is that I have an additional set of
> operators, r+, r- and friends, so every consumer has to be aware of my
> numbers and use the proper operations, like the float-operators in
> OCaml +. -. or the BigInteger stuff in Java. I'd like to avoid that,
> for my new numbers to play with the other kids :)
I see. Probably, you could just define the names + and - in the
protocol which would shadow clojure.core/{+,-} and extend that protocol
also to java.lang.Number, where the implementations would simply call
(clojure.core/+ this o) and (clojure.core/- this o).
But take in mind that my implementation (and the extension sketched
above) assumes that both things are of the same type. So if you intend
to add "normal" numbers to range types and vice versa, and support any
number of parameters like the standard +/- functions, you'd be better
off with multimethods instead of a protocol. You could define
multimethods for the 1- and 2-arg cases, and use those in combination
with `reduce' for the 3-or-more-arg case.
Argh, because it sounded interesting, I was forced to hack something
together. That's only briefly tested, but it seems to make + work for
an arbitrary number of mixed java.lang.Number and RangeNum arguments.
The first argument defines the result type, and as you requested, if the
first one is a range type and the operation overflows the allowed range,
an exception is thrown.
--8<---------------cut here---------------start------------->8---
(defprotocol RangeNumProtocol
(check [this])
(value [this]))
(defprotocol RangeNumLimits
(upper [this])
(lower [this]))
(deftype RangeNum [v l u]
RangeNumProtocol
(check [this]
(if (or (> v u) (< v l))
(throw (RuntimeException. "Over/Underflow"))
this))
(value [this] (and (check this) v))
RangeNumLimits
(upper [this] u)
(lower [this] v))
(extend-protocol RangeNumProtocol
java.lang.Number
(check [this] this)
(value [this] this))
(defmulti + #(class (first %&)))
(defmethod + java.lang.Number
([a] a)
([a b] (clojure.core/+ a (value b)))
([a b & more] (reduce + (+ a b) more)))
(defmethod + RangeNum
([a] a)
([a b] (RangeNum. (value (+ (value a) b)) (lower a) (upper a)))
([a b & more] (reduce + (+ a b) more)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Some applications
(+ 1000 (RangeNum. 500 1 1000) 19)
;=> 1519
(value (+ (RangeNum. 500 1 1000) 499 0 0 1))
;=> 1000
(value (+ (RangeNum. 500 1 1000) 499 0 0 2))
; Evaluation aborted.
; Over/Underflow
; [Thrown class java.lang.RuntimeException]
--8<---------------cut here---------------end--------------->8---
Bye,
Tassilo
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en