By the way, I wanted to emphasize that I don't think this would be an
ideal use of metadata even if your use case was supported. But the
reason metadata is so tempting is that you want frequencies and
distances to be treatable as numbers and so on. If you wrap them up
like I suggested, you couldn't pass them directly to core arithmetic
functions like + and * but would need to perform manual wrapping and
unwrapping.

The analogous case in Haskell is newtypes. Newtypes are used when you
want an isomorphic but nevertheless non-equal version of an existing
data type. So in your example you might have a Frequency and Distance
newtype. Generally you want most of the implemented interfaces (type
classes) to be inherited from the underlying types without having to
implement them by manually unwrapping the operands, forwarding them,
and rewrapping of the results. This is done by newtype deriving. If
you write newtype Frequency = Frequency Integer deriving (Show, Eq,
Ord, Num), you will inherit the behavior for displaying an integer as
a string, equality checking, linear ordering, and integral arithmetic
operations. But you could also leave the Show out and implement it
yourself, probably deferring to the wrapped type's Show instance as
part of your implementation.

I think you could achieve something similar with protocols. There
would be a (defnewtype frequency Protocol1 Protocol2 ... ProtocolN),
which would implement the named protocols for each Frequency instance
by deferring to the wrapped value. This wouldn't be possible for all
protocols but only those with implemented newtype derivers. For
example, the newtype deriver for the arithmetic protocol's addition
function might unwrap the operands, call addition on these now
unwrapped values, and then rewrap the results in the newtype wrapper.
(Clojure's arithmetic tower isn't expressible via protocol-style
single dispatch, so this is vastly simplified, but you get the idea.)

-Per

On Sat, Apr 3, 2010 at 3:18 PM, Per Vognsen <per.vogn...@gmail.com> wrote:
> Unfortunately you can only attach metadata to types that implement the
> IObj interface. That excludes native Java types like Integer and
> Float:
>
> user=> (with-meta 42 {:foo 42})
> java.lang.ClassCastException: java.lang.Integer (NO_SOURCE_FILE:0)
> user=> (with-meta 42.0 {:foo 42})
> java.lang.ClassCastException: java.lang.Double (NO_SOURCE_FILE:0)
> user=> (with-meta (float 42.0) {:foo 42})
> java.lang.ClassCastException: java.lang.Float (NO_SOURCE_FILE:0)
>
> I haven't thought through all the implications, but it seems like
> Clojure could support externalized metadata for these sort of types
> with an identity-based weak-key hash table.
>
> Anyway, the way things stand, your best kept is probably to wrap your
> data in some data structure. It could be as simple as [:frequency x]
> or {:tag :frequency, :value x}.
>
> -Per
>
> On Sat, Apr 3, 2010 at 5:47 AM, strattonbrazil <strattonbra...@gmail.com> 
> wrote:
>> What's the best way to keep track of what kind of value something is?
>> For example, if I have a hash of floats and I want to go through each
>> one and see if a given key-value, which happens to be a float, if it's
>> a distance or a frequency?  Or if something is a struct or a specific
>> struct?  I'm somewhat familiar with the pattern matching done in Scala
>> and couldn't find similar documentation in Clojure.
>>
>> I would think there's some way to filter out values that are a certain
>> struct, but I'd also like to attach information to primitives like
>> floats.  Should I wrap my primitives in structs or do I need
>> metadata?
>>
>> --
>> 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
>>
>> To unsubscribe, reply using "remove me" as the subject.
>>
>

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