The philosophy I try to follow is to use multiple dispatch when you don't
care at the calling site what the types of your arguments are and therefore
which method will be called. For example, consider the case when you
receive some output from a library function and you either don't know or
are too lazy to check what types are being returned. Multiple dispatch is
perfect for just sending on those outputs without worrying about it and
have it do the right thing automatically.
Now, on the other hand, when you invest care at the calling site in making
sure a particular method needs to be invoked, I would argue you probably
don't need to worry about fitting everything in a multiple dispatch scheme.
In your 'maxitemid' vs 'miniterid' case, it seems your calling function is
going to need to do some logic to figure out which method it wants to
invoke. In that case, you're already treating them as separate functions
and so I would say they should be named as separate functions.
There are other tricks though to using dispatch in such cases and I think
it's mostly a matter of preference on which style you think looks nicer.
You could use the 'Val' parametric type and have something like:
getitems(::Type{Val{:max}}, id::ItemId) #invoke as getitems(Val{:max},
ItemId(10))
getitems(::Type{Val{:min}}, id::ItemId) #
getitems(Val{:min}, ItemId(11))
Or you could declare some empty immutables to act as labels in the same
manner as Val.
On Sunday, June 28, 2015 at 8:26:51 AM UTC-4, ks wrote:
>
> Hello Mauro,
>
> Thank you for your answer.
>
> > 1. Use different function names: getitems, getitems_maxid. Not too
>> elegant
>> > as you mix purpose and details of function usage in its name.
>> > 2. Use named arguments. This will cause the function implementation to
>> grow
>> > (a series of if / else), again not too elegant.
>> > 3. Define a new type: ItemId which behaves exactly as Int but can be
>> used
>> > to 'activate' multiple dispatch (one function would use Int and the
>> second
>> > one would use ItemId). Generally not the best approach if you have
>> methods
>> > each having an argument that should be really represented as an Int
>> rather
>> > than a new type.
>>
>> For dispatch to work you have to use #3. By the same logic you use in
>> #1 this is good: a 3 of ItemId has different "units" to a 3 of
>> maxnumitems. For instance, you shouldn't be able to do ItemId +
>> maxnumitems. Using different types gives you that and is the most
>> Julian approach but #1 and #2 work fine and might be the right solution
>> at times too.
>
>
> The "units" explanation is very convincing. But what would you do when you
> have two methods that have different semantics but are indistinguishable by
> the argument types? A quick example:
>
> getitems( maxitemid::ItemId )
> getitems( minitemid::ItemId )
>
> both arguments use the same type and so no multiple dispatch is possible
> here (introducing two types here wouldn't be right I feel). I'm just
> thinking about general approach to structuring code in Julia, like when do
> you handle things with multiple dispatch and when do you switch over to
> another convention.
>
>
>> Note that a type such as
>>
>> immutable ItemId
>> id::Int
>> end
>>
> is as performant as an Int.
>
>
> Thanks. Would it be possible to define a new type which is not a composite
> type, just an Int without any fields but with its own name? So that you can
> use it like "a" rather than "a.id"?
>
> Thank you again,
> Krystian
>