An example from Base/float.jl that dispatches on the type itself (this is just one use of many reasonable ones):
## precision, as defined by the effective number of bits in the mantissa precision(::Type{Float16}) = 11 precision(::Type{Float32}) = 24 precision(::Type{Float64}) = 53 precision{T<:AbstractFloat}(::T) = precision(T) On Thursday, March 10, 2016 at 2:15:05 PM UTC-5, Jeffrey Sarnoff wrote: > > There are situations in which dispatching off of Type(s) is necessary. > Dispatching through Types by way of typed instances (realizations) is more > common, and the only way to go when you want to do something with the > fields' values of a typed instance. Rather than look at the two as > better/worse, consider them two manners of expression that are available to > you. Using whichever feels more natural and/or writes itself more simply > is always helpful. If you are treating the dice and the coin as singleton > entities, then it makes sense to code them that way. As a bonus, that can > simplify later elaborations and alterations that you may choose to make. > If your dice and coin are conceptual abstractions that permeate all > possible realizations of dice-ness and coin-ness, then it makes sense to > operate on --and dispatch through-- their type-ness. > > > On Thursday, March 10, 2016 at 1:42:56 PM UTC-5, ben wrote: >> >> Thanks. I understand that, but is there a specific reason why doing: >> >> takedecision{H <: Dice}(::Type{H}) >> >> is bad / not as good? >> >> On Thursday, March 10, 2016 at 1:06:01 PM UTC-5, Jeffrey Sarnoff wrote: >>> >>> when you do >>> immutable Dice end >>> or >>> type Dice end >>> you create a singleton type -- there can be only one instance (or all >>> instances are that identical single instance). >>> >>> To realize a singleton type, call it: >>> myDice = Dice(); myCoin = Coin() >>> >>> now, you can use >>> choose(x::Dice) = println("throw the dice") >>> choose(myDice) >>> throw the dice >>> >>> >>> On Thursday, March 10, 2016 at 12:02:09 PM UTC-5, ben wrote: >>>> >>>> Hi everyone, >>>> >>>> One of the many cool things we can do in Julia is use multiple dispatch >>>> to avoid a "method" argument followed by a "if" construct sending to >>>> back-end functions. I sometimes get confused about which of the following >>>> two ways of achieving this is better: >>>> >>>> ~~~ >>>> immutable Dice end >>>> immutable Coin end >>>> >>>> takedecision{H <: Dice}(::Type{H})=println("throw a dice") >>>> takedecision{H <: Coin}(::Type{H})=println("flip a coin") >>>> makedecision(::Dice)=println("throw a dice") >>>> makedecision(::Coin)=println("flip a coin") >>>> >>>> takedecision(Dice) >>>> takedecision(Coin) >>>> makedecision(Dice()) >>>> makedecision(Coin()) >>>> ~~~ >>>> >>>> If the method has "tuning parameters" (like the type of Dice or of >>>> Coin), the second way is much better, using inner fields >>>> `method.tuningparameter` and constructor `Method(tuningparameter)`. But if >>>> the method type is a pure "label" type without any additional content, >>>> both >>>> ways work. The first one is uglier in the source code but nicer for the >>>> user and may be more faithful to the concept (I want to make a decision by >>>> throwing a coin, not by throwing this particular coin). Indeed see the >>>> confusion caused by Gridded(Linear()) in this other topic: >>>> https://groups.google.com/forum/#!topic/julia-users/0cV6v-FJD7c >>>> >>>> Am I missing something key in terms of the pros and cons of each of >>>> these two ways? Is there a principled good practice? >>>> >>>> Best >>>> >>>> Ben >>>> >>>>