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
> > > > >
> > > > >
>