I think dropping generic functions which clash is the safest way, as
Stefan suggests in 4345.  Consider

In someone elses package:

module OtherDev
export foo
foo(x::String) = 1
end

In my package:

module MyMod
export foo
foo(x::Number) = 2
end

Some 3rd person uses both in her code:

using OtherDev
using MyMod
a = foo(4.59)

Sometime later OtherDev decides to update his module:

module OtherDev
export foo
foo(x::String) = 1
foo(x::Float64) = 3
end

This would be a hard bug for person 3 to find.  Thus person 3 should be
forced to write his code:

using OtherDev
using MyMod
a = MyMod.foo(4.59)

On Tue, 2015-01-13 at 21:28, Petr Krysl <[email protected]> wrote:
> I think your explanation makes sense. But:
>
> Consider that the two modules may be due to two independent developers. A 
> third guy (me) wishes to use both modules. Why should it be prohibited to 
> have the two "using" define a single generic function foo with two methods 
> (provided they can be disambiguated)?
>
> I think the discussion at 4345 was about the tricky nature of "merging" the 
> definitions of the generic functions. But it seems to me it is only tricky 
> when the arguments do not allow for the compiler to distinguish between 
> them. In that case the compiler should complain or reject the definitions 
> (whichever is practicable), but otherwise it should be done for uniformity.
>
> See, when A defines a foo, and B and C import A.foo and re-export it, there 
> are no guarantees that the foo's are somehow related. They could still 
> implement entirely different (separate) concepts, which could both be 
> different from the concept that the original foo was designed to handle.
>
> P
>
> On Tuesday, January 13, 2015 at 12:06:47 PM UTC-8, Mauro wrote:
>>
>> Is this problem not more related to issue 
>> https://github.com/JuliaLang/julia/issues/2327 ? 
>>
>> The way it works is thus:  If you make a method in a module, say 
>>
>> module A 
>> export foo 
>> foo() = 1 
>> end 
>>
>> This will create a new generic function foo with one method in it. 
>> Now do the same in another module: 
>>
>> module B 
>> export foo 
>> foo(x) = x 
>> end 
>>
>> This defines another generic function, of the same name foo, with a 
>> method in it.  Now doing 
>>
>> using A 
>> using B 
>>
>> Will result in the generic function foo from module B being 'used', 
>> i.e. the binding of the symbol foo points to B.foo and not to A.foo 
>> anymore.  So, essentially generic functions do not get merged which is 
>> what I think you expect to happen. 
>>
>> The way to solve your problem is to define foo in some other module and 
>> import it to A and B 
>>
>> module U 
>> export foo 
>> foo() = error("to be specified later") 
>>
>> module A 
>> import ..U 
>> U.foo() = 1 
>> end 
>> module B 
>> import ..U 
>> U.foo(x) = x 
>> end 
>>
>> end 
>>
>> using U 
>> methods(foo) 
>>
>> now shows both methods: 
>>
>> # 2 methods for generic function "foo": 
>> foo() at none:7 
>> foo(x) at none:11 
>>
>>
>> On Tue, 2015-01-13 at 17:22, Petr Krysl <[email protected] <javascript:>> 
>> wrote: 
>> > I have a trouble following the reasoning in the 4345 issues trail. 
>> > 
>> > If a module defines a method (let us say "count") and brings in into an 
>> > environment that already has a method for the function count(), both are 
>> > available provided there signatures allow for the compiler to 
>> distinguish 
>> > between them to decide which one to call. 
>> > 
>> > I already have a situation like this in my code: I have two modules that 
>> > define the function count(), and  they export  that function  count() 
>>  and 
>> > in the main there are already two methods  count().. 
>> > 
>> > julia> methods(count) 
>> > # 4 methods for generic function "count": 
>> > count(pred::Union(Function,Func{1}),a::AbstractArray{T,N}) at 
>> reduce.jl:436 
>> > count(pred::Union(Function,Func{1}),itr) at reduce.jl:426 
>> > count{T<:FESet}(me::T<:FESet) at 
>> > C:\Users\pkrysl\Documents\GitHub\JFinEALE.jl\src\FESetModule.jl:32 
>> > count(self::FENodeSet) at 
>> > C:\Users\pkrysl\Documents\GitHub\JFinEALE.jl\src\FENodeSetModule.jl:47 
>> > 
>> > The two methods that failed to get both exported are (it appears)  in 
>> > precisely the same  situation, except  that the main module does not 
>> have 
>> > any definition  of a method with the same name: 
>> > 
>> > julia> methods(JFinEALE.HeatDiffusionAlgorithmModule.steadystate) 
>> > # 1 method for generic function "steadystate": 
>> > 
>> steadystate(algo::HeatDiffusionAlgorithm,modeldata::Dict{ASCIIString,Any}) 
>> > at C:\Users\pkrysl\Documents\GitHub 
>> > \JFinEALE.jl\src\HeatDiffusionAlgorithmModule.jl:83 
>> > 
>> > julia> methods(JFinEALE.AcousticsAlgorithmModule.steadystate) 
>> > # 1 method for generic function "steadystate": 
>> > steadystate(algo::AcousticsAlgorithm,modeldata::Dict{ASCIIString,Any}) 
>> at 
>> > C:\Users\pkrysl\Documents\GitHub\JFi 
>> > nEALE.jl\src\AcousticsAlgorithmModule.jl:85 
>> > 
>> > As you can see, the compiler  should be able to decide which of these 
>> > methods to call  as they get passed arguments of different types.. 
>> > 
>> > So,,  this succeeds: 
>> > 
>> > include("FESetModule.jl") 
>> > using JFinEALE.FESetModule 
>> > ... 
>> > export count 
>> > .... 
>> > 
>> > include("FENodeSetModule.jl") 
>> > using JFinEALE.FENodeSetModule 
>> > ... 
>> > export count 
>> > 
>> > and this fails 
>> > 
>> > include("AcousticsAlgorithmModule.jl") 
>> > using JFinEALE.AcousticsAlgorithmModule 
>> > export AcousticsAlgorithm 
>> > export steadystate 
>> > 
>> > include("HeatDiffusionAlgorithmModule.jl") 
>> > using JFinEALE.HeatDiffusionAlgorithmModule 
>> > export HeatDiffusionAlgorithm 
>> > export steadystate 
>> > 
>> > I find this strange and inconsistent. Could someone please explain   
>> > whether  this is something I should fix up at my end or that this is a   
>> > problem with the logic of the programming language.. 
>> > 
>> > Petr 
>> > 
>> > On Monday, January 12, 2015 at 11:24:07 PM UTC-8, Ivar Nesje wrote: 
>> >> 
>> >> New method definitions will replace the previous definition. 
>> >> 
>> >> If you put the function in a module and bring them into you scope with 
>> >> using/importall, you'll run into 
>> >> https://github.com/JuliaLang/julia/issues/4345, which can be 
>> considered 
>> >> either a bug or a missing feature. 
>>
>>

Reply via email to