On Saturday, May 2, 2015 at 2:47:06 PM UTC+10, MA Laforge wrote:
>
> *Need help creating my package!*
>
> I am writing a program to perform a Monte-Carlo simulation of a plane's 
> normal vector in Julia.  I want to publish my "Geometry" package for others 
> to use it... because it is awesome!
>
> Please do not ask me why I would want run such a simulation.  Also: please 
> don't ask why my code is so inelegant (using simple "Vector"s instead of 
> defining a "Coordinate" type).  It is a secret.  All I can say is that I 
> will make billions of dollars selling this to people in a parallel universe 
> where everybody is high... all the time.
>
> I am following this thread because I see people having similar problems to 
> mine.  But apparently, there are no issues reported by the developers of 
> the major Julia packages... so I am willing to accept I am doing something 
> wrong.  I just want someone (anyone) to tell me what that is (I just can't 
> figure it out).
>
> Here is part of my program:
> #I'm running Monte-Carlo, so I need that awesome "Distributions" package:
> using Distributions
>
> #This is my awesome Geometry module that I want to distribute to others:
> module Geometry
>     #I define a plane with 3 points... because using its normal is for 
> suckers:
>     type Plane
>         point1::Vector
>         point2::Vector
>         point3::Vector
>     end
>
>     #Then I waste the CPU's time computing the normal... 'cuz I'm awesome:
>     Normal2(x::Plane) = cross(x.point2-x.point1, x.point3-x.point1)
>
>     export Plane
>     export Normal2
> end
>
> #Of course, I want to use that module using Julia's great succinct syntax:
> using Geometry
>
> #Bet you can't guess why varying the z-coordinate will make me billions of 
> dollars!:
> #That's why I am a genous:
> function varyzdim(x::Vector, amount::Number)
>     result = copy(x)
>     result[3] *= 1+amount
>     return result
> end
>
> #Principal algorithm:
> function simulate_monte_carlo(nruns::Integer)
>     plane = Plane(Float64[0,0,0], Float64[1,0,0], Float64[0,1,0])
>     n = Normal2(plane)
>     dist=Normal(0, .01)
>     return [varyzdim(n,x) for x=rand(dist, nruns)]
> end
>
> #Step 1: Run simulation
> result = simulate_monte_carlo(3)
> @show result
>
> #Step 2: ...
>
> #Step 3: Profit!
> :Done
>
> *Problems:*
>
>    - I was not able to call Geometry.Normal2 as Geometry.Normal... 
>    because it collided with Distributions.Normal.
>
>
Yes, thankfully Julia has saved you from confusion, humility and loss of 
profit :)


>    - I *could* define "Normal(x::Plane)" to "extend" 
>    Distributions.Normal... but then my friend will not be able to use my 
>    awesome module.  Apparently, the universe where *he* is selling his 
>    software will be destroyed by Schrödinger's cat if the code is not 
>    deterministic.  He tells me the cat will loose it or something...  I don't 
>    know...  I don't think I really care as long as he is happy.
>    - In any case, I don't *want* to extend Distributions.Normal, because 
>    Geometry.Normal is very much >>>orthogonal<<< to the former.
>
>
Indeed, its best to know which you are using, cats or no cats.
 

>
>    - I guess it would work if "Normal" was defined in Base...  I mean 
>    pretty much *everybody* will want to use Julia's Base module anyways....  
>    But it's not really practical for me to fork Julia just to add method 
>    "Normal" to module Base.
>    - If I decide to keep the method name as "Normal2"... how do I know no 
>    other module out there won't try to use the same workaround as mine?  Then 
>    I will not be playing nice with *that* module (I am getting a little 
>    anxious now...).
>    
>
Well again it will be good to know which you are using, to avoid the 
anxiety ... so just keep the "normal" name and be explicit, Geometry.normal 
that should calm your shattered nerves and maintain the profits.
 

>
>    - 
>    - I could write this in C++... But I don't think I have the patience 
>    anymore (after getting hooked on Julia).
>
> +some
 

> *So what am I missing here?*
>
>    1. Am I doing something wrong?  What is it about Julia's module system 
>    that I am not understanding.
>
>
Not as far as I can tell.
 

>
>    1. Am I being too fussy?  Is it unreasonable for me to expect that my 
>    Monte-Carlo simulation can take advantage of multi-dispatch on *both* 
>    "Geometry.Normal" and "Distributions.Normal" without needing to explicitly 
>    import Normal from their respective modules?
>
>
and Psychiatry.normal and TimeToGetUp.normal and ...

Whoa, there's that anxiety again, did I check that all those modules didn't 
define a function on a common ancestor type?  Maybe I should just check it 
again ... and again ... and ... etc.  You should be much less anxious since 
Julia just stops you from getting in such a state of worry by not allowing 
common names to be `using`ed.
 

>
>    1. Is this case not considered common enough to warrant improvements 
>    to Julia's module/namespace system in the future?  Should I accept that 
> the 
>    best solution in the long term is to only "import Geometry".  Is the best 
>    solution to explicitly qualify my version of Normal as "Geometry.Normal" 
>    whenever two modules export the same symbol... despite having un-ambiguous 
>    signatures (AFAIK)?
>
>
If you consider it a serious problem you could try implementing the change 
so it can be tried to see if it works, and what problems it exposes.
 

>
>    1. Am I wrong about not being able to extend Base?  Is it in fact 
>    possible for me to extend base in order to add the symbol "Normal" without 
>    forking?  ...But then what do I do about having broken the Distributions 
>    module (because Base would then "own" Normal)?
>
>
>
Indeed if you could *add* it to base you would break lots of stuff.  
 

>
> *Please! I would appreciate the input of *anyone* who can help me make the 
> Geometry package work harmoniously with other packages (present & future) 
> in Julia's ecosystem.*
>

Your Geometry module will work fine, but users (and you) will have to be 
explicit about which "normal" they want to use if they also import the 
symbols from another module which exports the same name.

Personally I *want* it to be explicit that I'm calling Photography.shoot() 
not NuclearMissile.shoot() :)
 

>
>
> PS:
> I could understand if a solution to this problem is non-trivial...  I can 
> also understand if this is simply not a high priority for the core team 
> right now...  But that's not the principal message I am getting from this 
> thread at the moment.
>


This problem is not unique to Julia.

C++ has the same issues, its choice is to automatically merge all functions 
of the same name,as has been requested in this thread, then apply some 
complex rules of exquisite subtlety to the *static* type of the arguments 
to decide which to dispatch statically at compile time.  And Bjarne notes 
the decisions are "occasionally surprising".  In fact its common to 
explicitly qualify names in C++ to avoid the confusion. 

But overload resolution does not apply to dynamic dispatch, types being 
dynamically dispatched must have a common parent with the function declared 
"virtual", dynamic dispatch is not possible on multiple parameters, or 
between types that do not have common ancestors, so C++ sidesteps the 
problem that way.

Note that applying the C++ overload resolution rules dynamically at runtime 
would likely make performance unacceptable.

Reply via email to