Le jeudi 10 mars 2016 à 12:40 -0800, ben a écrit : > 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). Yes, but then we have three redundant ways of passing the information: Dice, Dice(), and dice. :-)
> > 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/9ddb5067a12 > > 3da2fa46bfcdbdf6b3d3aecf9af4f/src/encodings.jl#L8 > > 2: https://github.com/nalimilan/StringEncodings.jl/blob/9ddb5067a12 > > 3da2 > > fa46bfcdbdf6b3d3aecf9af4f/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-F > > JD7c > > > > > > > > > > > > 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 > > > > > > > > > > > >