Thanks Milan, interesting to see others have wondered the same thing I did. 
Note that you can define dice=Dice() and encoding_utf8=Encoding{UTF8}() 
once and for all to avoid the parentheses (as Jeffrey points out).

On Thursday, March 10, 2016 at 3:27:31 PM UTC-5, Milan Bouchet-Valat wrote:
>
> Le jeudi 10 mars 2016 à 11:15 -0800, Jeffrey Sarnoff a écrit : 
> > 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. 
> Yet this doesn't address the question of which solution is the best in 
> the case of singleton types, for which the type and the instance carry 
> the same amount of information. 
>
> FWIW, I also had the same interrogation when creating a parametric 
> singleton type like this [1]: 
> immutable Encoding{enc} end 
>
> In the end, I chose to use instances rather than types since it makes 
> type signatures shorter and thus clearer for documentation. For 
> example, I find this [2]: 
> readstring(stream::IO, enc::Encoding) 
>
> much nicer to read than this: 
> readstring{enc}(stream::IO, ::Type{Encoding{enc}}) 
>
> But this has a downside that one needs to write Encoding{:UTF8}() 
> instead of Encoding{:UTF8}, or Dice() instead of Dice. I find the 
> presence of parentheses quite annoying since it doesn't add anything. 
> (This isn't actually an issue for Encoding since I defined a non- 
> standard string literal enc"UTF8" as a shortcut. But for non-parametric 
> types that issue is generally more visible.) 
>
>
> So these are my two cents, but I'd love to hear ideas from others. If 
> we find strong arguments in one direction or another, we could add them 
> to the manual. 
>
>
> Regards 
>
>
>
> 1: 
> https://github.com/nalimilan/StringEncodings.jl/blob/9ddb5067a123da2fa46bfcdbdf6b3d3aecf9af4f/src/encodings.jl#L8
>  
> 2: https://github.com/nalimilan/StringEncodings.jl/blob/9ddb5067a123da2 
> fa46bfcdbdf6b3d3aecf9af4f/src/StringEncodings.jl#L393 
> <https://github.com/nalimilan/StringEncodings.jl/blob/9ddb5067a123da2fa46bfcdbdf6b3d3aecf9af4f/src/StringEncodings.jl#L393>
>  
> > 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. 
> > 
> > 
> > > Thanks. I understand that, but is there a specific reason why 
> > > doing: 
> > > 
> > > takedecision{H <: Dice}(::Type{H}) 
> > > 
> > > is bad / not as good? 
> > > 
> > > > 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 
> > > > 
> > > > 
> > > > > 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 
> > > > > 
> > > > > 
>

Reply via email to