Hi,

Wow, thanks for all that input :) It is always a pleasure to post on
this list, to get such good advice.

On Wed, 21 Dec 2011 09:51:31 +0100
Tassilo Horn <[email protected]> wrote:

> > I am idly thinging on how to create types with special restraints on
> > them, like being only in the range 1-1000 or only even numbers etc
> > and all normal operations like + and - still being valid.
> 
> + and - would have wrap-around semantics, I guess?

No, they wouldn't, they should error out. Actually this started as a
discussion during lunch between me and a Ada proponent where such types
seem to be common. I was thinking how much I can custom-tailor types,
like only-odd-numbers, only-prime-numbers. As some kind of universal
precondition system. Sorry if I am explaining the idea so fuzzy, I
don't seem to be good in explaining.

> > Anyone has an idea how to implement that? In Python I'd subclass the
> > number type and implement all oparators, but how would one do this
> > in Clojure?
> 
> You could do something similar with a protocol defining the restricted
> operations and a record for the numbers that implement that protocol.
> 
> --8<---------------cut here---------------start------------->8---
> (defprotocol RestrictedArithmetics
>   (canonic [this])
>   (r+ [this o])
>   (r- [this o]))
> 
> (defrecord RangeNum [v l u]
>   RestrictedArithmetics
>   (canonic [this]
>     (cond
>      (> v u) (RangeNum. (mod v u)  l u)
>      (< v l) (RangeNum. (+ u v)    l u)
>      :else   this))
>   (r+ [this o]
>     (canonic (RangeNum. (+ v (:v o)) l u)))
>   (r- [this o]
>     (canonic (RangeNum. (- v (:v o)) l u))))
> 
> (r+ (RangeNum. 500 1 1000) (RangeNum. 500 1 1000))
> ;=> #user.RangeNum{:v 1000, :l 1, :u 1000}
> (r+ (RangeNum. 501 1 1000) (RangeNum. 500 1 1000))
> ;=> #user.RangeNum{:v 1, :l 1, :u 1000}
> (r- (RangeNum. 500 1 1000) (RangeNum. 500 1 1000))
> ;=> #user.RangeNum{:v 1000, :l 1, :u 1000}
> --8<---------------cut here---------------end--------------->8---
> 
> But I'm not quite sure, if that's a decent approach.  For any
> RangeNum, you have a map plus three long values, so you multiply the
> memory requirements quite a bit.

This is not really a problem, since first it doesn't have to wrap
around, and second I don't mind a performance hit for this. In this
case I happyily sacrifice performance for correctness.
> 
> So maybe you should use `deftype' above instead of `defrecord'.
> 
> --8<---------------cut here---------------start------------->8---
> (defprotocol RestrictedArithmetics
>   (canonic [this])
>   (value [this])
>   (r+ [this o])
>   (r- [this o]))
> 
> (deftype RangeNum [v l u]
>   RestrictedArithmetics
>   (canonic [this]
>     (cond
>      (> v u) (RangeNum. (mod v u)  l u)
>      (< v l) (RangeNum. (+ u v)    l u)
>      :else   this))
>   (value [this] v)
>   (r+ [this o]
>     (canonic (RangeNum. (+ v (value o)) l u)))
>   (r- [this o]
>     (canonic (RangeNum. (- v (value o)) l u))))
> 
> (value (r+ (RangeNum. 500 1 1000) (RangeNum. 500 1 1000)))
> ;=> 1000
> (value (r+ (RangeNum. 500 1 1000) (RangeNum. 501 1 1000)))
> ;=> 1
> (value (r- (RangeNum. 500 1 1000) (RangeNum. 501 1 1000)))
> ;=> 999
> --8<---------------cut here---------------end--------------->8---
> 
> And maybe you should take a completely different approach. ;-)

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 :)

regards,
Marek

-- 
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

Reply via email to