Reputation: 1287
I have the following record:
(defrecord Signal [samples ^double sample-rate ^double scaling-factor])
How can I specify samples
to be a double array?
I am using clojure 1.2.0
Edit:
@dreish I get the following output when I call (show Signal)
after the changes from levand:
[35] <init> (Object,double,double)
[36] <init> (Object,double,double,Object,Object)
[37] __extmap : Object
[38] __meta : Object
[39] sample_rate : double
[40] samples : Object
[41] scaling_factor : double
I know that hinting of non-primitive type is just used to avoid reflection. From http://clojure.org/datatypes
Thanks everybody!
Upvotes: 18
Views: 6005
Reputation: 7825
To elaborate on what dreish wrote:
As it is currently implemented (1.2), type hints do not manifest in the API (instance variables, constructor/method signatures), but rather are used to eliminate reflection calls within the lexical scope. For example:
user=> (set! *warn-on-reflection* true) true user=> (defprotocol P (foo [p])) P user=> (defrecord R [n] P (foo [_] (.intValue n))) Reflection warning, NO_SOURCE_PATH:4 - reference to field intValue can't be resolved. user.R user=> (defrecord R [^Number n] P (foo [_] (.intValue n))) user.R
The issue that remains is the boxing of primitive numbers, though a double array is-a Object, so no worries there.
That said, I believe there are some enhancements in the master branch (1.3) such that the instance variables, etc., can be emitted as primitive types based on type hinting.
Upvotes: 4
Reputation: 285
I agree with levand's answer on which type hint to use, but you might want to check whether defrecord
actually uses these type hints. On my installation (also 1.2.0), it does not.
user=> (defrecord Signal [^doubles samples ^double sample-rate ^double scaling-factor])
user.Signal
user=> (use '[clojure.contrib.repl-utils :only [show]])
nil
user=> (show Signal)
=== public final user.Signal ===
[stuff deleted]
[38] <init> (Object,Object,Object)
[39] __extmap : Object
[40] __meta : Object
[41] sample_rate : Object
[42] samples : Object
[43] scaling_factor : Object
[more stuff deleted]
As you can see, the constructor arguments (38) and the member variables (41-43) are still just Object
s. (Arrays are references anyway, but it will be nice to someday be able to store unboxed numbers in a record once that feature is implemented.)
Upvotes: 5
Reputation: 8500
Like this:
(defrecord Signal [^doubles samples ^double sample-rate ^double scaling-factor])
Rich Hickey added this a while back:
Added special type hints for primitive arrays - #^ints, #^floats, #^longs, #^doubles
See http://clojure.org/news for a discussion of how it works.
I don't have a Clojure environment with me to see if this is still the best way to do it. I assume the #^ syntax was updated to ^ along with all the other type hints in Clojure in 1.2
Edit: Another blog post on it: http://asymmetrical-view.com/2009/07/02/clojure-primitive-arrays.html
Upvotes: 20