What you are really observing is issue #265 ( https://github.com/JuliaLang/julia/issues/265). `A.f` got compiled the first time you called it, but a recompile didn't get triggered when you altered the definition of `_f`
On Sat, May 2, 2015 at 11:54 AM Tom Breloff <[email protected]> wrote: > After reading this response, I realized that maybe I don't have a complete > grasp on how and when a module's method is overwritten/extended. I did a > simple test of what I thought might produce unexpected results, but in fact > worked exactly as I wanted it to! Bravo guys... every time I think there > might be a (very slight) hole in the design of the language, I am proven > wrong. :) > > Here's the test, which ensures that code from within that module will > always call a "clean" group of functions (even when a function is > exported!)... i.e. you can't change/replace the internal dispatch from > outside the module, which was my primary concern. Check out the numbers > highlighted in orange. If the internal call to _f(x) could be masked, they > should be -1... however that's not allowed so it (correctly) returns 999. > > In summary... please ignore all my comments above about private functions > since it already works the way I want, and thanks for teaching me a little > more about the language. > > > julia> module A > export f, _f > f(x) = _f(x) > _f(x) = 999 > end > > julia> using A > > julia> A.f(0), A.f(0.0), A._f(0), A._f(0.0) > (999,999,999,999) > > julia> f(0), f(0.0),_f(0), _f(0.0) > (999,999,999,999) > > julia> A._f(x::Float64) = -1 > _f (generic function with 2 methods) > > julia> A.f(0), A.f(0.0), A._f(0), A._f(0.0) > (999,*999*,999,-1) > > julia> f(0), f(0.0),_f(0), _f(0.0) > (999,999,999,-1) > > > > > On Friday, May 1, 2015 at 8:57:04 PM UTC-4, [email protected] wrote: >> >> >> >> On Friday, May 1, 2015 at 11:39:20 PM UTC+10, Tom Breloff wrote: >>> >>> I agree that auto-merging could cause hard-to-find bugs for the user. >>> This is less important than causing impossible-to-find bugs for a package >>> writer IMO. >>> >> >> I'm not sure I understand what impossible to find bug not merging >> functions causes. >> >> >> >>> >>> Here's a couple potential solutions for the user space issues: >>> >>> - "@verbose using SomeHugeModule" >>> - this could analyze the exported functions and check for name >>> clashes superficially (i.e. no concept of dispatch types) and print a >>> report of potentially dangerous method names >>> - new syntax: "using SomeHugeModule without fragileMethod1, >>> fragileMethod2" >>> - similar to "import A: x, y" but the reverse... allow everything >>> except those 2 methods to be imported >>> >>> Note that for a user that just wants to use a module without worrying >>> about safety, nothing changes. However for users building more complex >>> systems with many packages, they have a way to see potential clashes and >>> decide on their own how best to handle them. A "using ... without ..." >>> syntax would be super nice for some larger packages that mostly have unique >>> names exported, but may have a couple clashes. Then you can do "using" and >>> just add to the "without" list if any clashes become a problem. >>> >> >> The "without" syntax allows possible reductions in verbosity when >> excluding a few names from the import, and makes them visible, so it is >> useful, but it is only syntactic sugar, not any new solution. >> >> >>> >>> >>> And here's an idea for the package writer issue: >>> >>> @includes_private Module A >>> >>> f(x) = "not too important" >>> _f(x) = "important... must call this internally" # NOTE: the >>> underscore tells the @includes_private macro to "hide" this function from >>> the outside world >>> >>> function g() >>> bigobj = createHugeObject() >>> f(bigobj) >>> _f(bigobj) # we should be able to guarantee that this calls our >>> function above... even if someone defines A._f(x) elsewhere >>> end >>> >> >> Julia experts should correct me, but it is my understanding that within >> the module it will always call the definition local to the module (unless >> you import explicitly). To quote the manual "Within a module, you can >> control which names from other modules are visible (via importing)". >> >> >> >>> >>> >>> end >>> >>> using A >>> f(x) = "something orthogonal to A.f" >>> A._f(x) = "something else" # NOTE: this should either not be allowed >>> (hard) or at least not clash with A's _f(x)... maybe replacing _f with a >>> gensym within A?? >>> g() >>> >>> >>> I *think* these solutions are somewhat straightforward, and the only >>> thing that would change core julia is the "without" syntax. If changing >>> syntax is not worth it, maybe you could make a "using_without" macro? >>> >> >> I don't really understand what the @include_private macro does and what >> problem it solves. Just don't export _f(). >> >> >>> >>> @using_without SomeHugeModule fragileMethod1 fragileMethod2 >>> >>> And now that I think about it, you could combine these concepts into >>> another macro which would analyze for name clashes and add any potentially >>> dangerous method names to the without list: >>> >>> @safe_using SomeHugeModule >>> >>> >>> >>> Does this functionality exist already? Are these macros something the >>> community would want? I would be willing to work on it. >>> >>> >>> >>>
