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