To add a little detail to Mauro's response:

The "overly-specific types" suggestion really applies to functions, not
types.  That is because a different version of every function is generated
based on the types of the arguments (as described at the end of the section
you linked to).  The main reason to add type annotations to functions is to
restrict the types of the parameters, which can sometimes be useful, but is
often unnecessary (and as described in that link, can make for less generic
code).

I'll give my answers your questions below, but if you haven't done so yet,
I would suggest a long read through the manual to help understand these
issues.

> *Questions*
> >
> > *1)* Is there any reason to define fieldtypes instead leaving fields with
> > no type annotation?
>

Any field of a type which itself does not have a concrete type will be
"boxed"--essentially, stored as a pointer with type information.  That
makes it very difficult to generate fast code for compound objects of this
type, because the compiler doesn't know the type of that field a compile
time, and unlike functions, it doesn't automatically specialize the type
based on the field types.

So, it will always work, but without concrete types for the fields, the
compiler always has to generate extra code to check the type of the field,
and then generate code which will do the right thing for the discovered
type.  Whereas, with typed fields, the compiler knows the type of the field
at compile time, and can compile fast code immediately.

>
> > *2) *How much performance do I sacrifice by defining a field as *Any*
> instead
> > of *Array  *or instead of Array{Float64,2}  or Array{Number,2}?
>

For functions, nothing.  For types, see the answer to 1 above.  A real
answer depends on what you want to do, and could range from "not much
effect" (e.g., if you're working with a struct defining a GUI interface) to
"won't work at all" (e.g., if you're trying to call a BLAS function on an
Array{Number,2})


> > *3)* suppose I define:
> >
> > type Mytype
> >        a:: Array{Number,1}
> >        b:: Array
> >        c
> >        end
> >
> > then I create an object by
> >
> > *var=Mytype( [1;2] , [1;2], [1;2] )*
> >
> > julia> typeof(var.a)
> > Array{Number,1}
> >
> > julia> typeof(var.b)
> > Array{Int64,1}
> >
> > julia> typeof(var.c)
> > Array{Int64,1}
> >
> >
> > Why field a is Array{Number,1} while b and c is Array{Int64,1} ? Isn't
> > Number generic enough to be turned into Int64?
>

First, to repeat what I said above, functions are specialized based on the
types of their arguments, but types are not--they are only specialized if the
type is parameterized
<http://julia.readthedocs.org/en/latest/manual/types/#man-parametric-types)>
!

Given that, the types of the fields of Mytype as you defined it are always

julia> Mytype.types
(Array{Number,1},Array{T,N},Any)

where

   - Array{Number,1} is a concrete type with abstract elements.
   - Array === Array{T,N} is an abstract type
   - Any is also an abstract type.

So, val.a has to have the concrete type Array{Number,1}, and val.b and val.c
must be values with types which are subtypes of Array and Any respectively.

It's also useful to know that, when you construct a type, Julia converts
the parameters to the correct type, if necessary.  For var.b and var.c, no
conversion is necessary, since typeof([1;2]) == Array{Int64,1} is a subtype
of both Array{T,N} and Any (in Julia).

julia> typeof([1;2])
Array{Int64,1}

julia> Array{Int64,1} <: Array
true

However for the first field, Array{Int64,1} is *not* a subtype of
Array{Number,1}:

julia> Array{Int64,1} <: Array{Number,1}
false

So [1;2] is converted to an Array{Number,1}, and then stored.  (For this
last point, see
http://julia.readthedocs.org/en/release-0.3/manual/types/#parametric-composite-types
)

If any of this is confusing (and it quite probably is), I recommend reading
the Julia manual section on types
<http://julia.readthedocs.org/en/release-0.3/manual/types/>, as well
as the Wikipedia
article on Covariance and Contravariance
<http://en.wikipedia.org/wiki/Covariance_and_contravariance_%28computer_science%29>
.

Moral: you should almost always give fields concrete types (with concrete
subtypes), and for more flexibility, you can use parameterized types.

Cheers,
   Kevin

Reply via email to