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

Reply via email to