Yichao is right, because doing so won't help performance in any way (indeed,
it will hurt it massively compared to an `if a.b...` runtime branch in your
code). You get the performance benefit from multiple dispatch only when the
compiler knows the "value" ahead of time (e.g., when it's compiling your
code), and transitions between the value-domain and type-domain prevent that
from happening.
Seems like you might be looking for this:
julia> type A{b}
x::Float64
end
julia> foo(a::A{true}) = 1
foo (generic function with 1 method)
julia> foo(a::A{false}) = 0
foo (generic function with 2 methods)
julia> a = A{true}(7)
A{true}(7.0)
julia> foo(a)
1
julia> b = A{false}(7)
A{false}(7.0)
julia> foo(b)
0
HOWEVER, I urge you not to do this frivolously. The compiler has to generate
separate versions of every function that takes an A{true} and A{false}. This
means your code will be slower to load/start. If you overuse this trick, you
can end up getting combinatorial explosions in the number of compiled variants
you require, and your code will become completely unusable.
A runtime check of a boolean is very fast, and if the outcome is fairly
predictable
(http://stackoverflow.com/questions/11227809/why-is-processing-a-sorted-array-faster-than-an-unsorted-array)
it can be very difficult to observe
any performance hit at all.
We do use such tricks in various places in core julia code, but only when
we've first tried not to. So it's a wonderful trick, but use it very
judiciously.
Best,
--Tim
On Wednesday, March 30, 2016 10:59:37 PM Yichao Yu wrote:
> On Wed, Mar 30, 2016 at 10:51 PM, Chris <[email protected]> wrote:
> > Here's my current dilemma, (hopefully) explained by this simple example:
> >
> > I have a composite type that has a bool field:
> >
> > type A
> >
> > x::Float64
> > b::Bool
> >
> > end
> >
> > I have a function with different behavior based on the value of A.b. The
> > manual suggests the following solution:
> >
> > function dothing(a::A, ::Type{Val{false}})
> >
> > ...
> >
> > end
> >
> > function dothing(a::A, ::Type{Val{true}})
> >
> > ...
> >
> > end
> >
> > That's fine, but now I have to call the function as dothing(a, Val{a.b}),
>
> Don't do this, just use a branch. Never construct a type with a type
> parameter of runtime determined value.
> The doc should be made very clear to discourage this!
>
> > which just strikes me as slightly redundant/verbose. Is there some way to
> > make this more compact, i.e. just dothing(a), while still avoiding the
> > check of a.b inside the function? Perhaps parameterizing the type A
> > itself?
> >
> > Hopefully I made myself relatively clear. Thanks in advance.