Kintaro
Kintaro

Reputation: 1287

How can I type hint an array?

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

Answers (3)

Alex Taggart
Alex Taggart

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

dreish
dreish

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 Objects. (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

levand
levand

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

Related Questions