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