You are correct it is restrictive, though I will take some convincing that 
this is a bad thing, as systems get larger in Julia it is going to be 
increasingly important to manage code reuse and prevent accidental masking 
of types. Multiple dispatch is a wonderful tool for supporting these goals. 
Unfortunately allowing people the ability to export get(<string>) et al to 
the users scope seems like a bad idea. This is already happening from 
modules today. Perhaps the middle ground is to force an explicit import, so 
*using* only imports functions which have types defined in the module.  The 
person defining the module exports all the functions they want but only 
those that are 'safe' e.g. follow my original rule are implicitly 
imported. Hence you would have something like the following code. This is 
not far different from the importall today, except that the exports are 
automatically restricted. 

using MyMath         # Imports *only *those functions which include types 
defined in MyMath 
import MyMath.*      # Imports all other  functions  defined in MyMath
import MyMath.afunc  # Imports  one  function
import MyOther.afunc # Fails collides with MyMath.afunc
 

 



On Wednesday, April 22, 2015 at 4:40:03 PM UTC-4, Jeff Bezanson wrote:
>
> That rule seems extremely restrictive to me. It would be very common, 
> for example, to create a library of functions that operate on standard 
> data types like numbers and arrays. I don't see that we can exclude 
> that kind of use. 
>
> Also, printing a warning is not the key part of #4345. The important 
> part is that you'd have to qualify names in that case, which is the 
> same thing that would happen if `export`ing the names were disallowed. 
>
>
> On Wed, Apr 22, 2015 at 8:47 AM, Michael Francis <[email protected] 
> <javascript:>> wrote: 
> > I read through the issues / threads ( and some others ) 
> > 
> > https://github.com/JuliaLang/julia/issues/2327 
> > https://github.com/JuliaLang/julia/issues/4345 
> > 
> > I'm not sure that the either the SuperSecretBase or the warning are the 
> > correct approach. I'd like to propose a counter which is a very simple 
> rule. 
> > 
> > "You can only export functions from a module where they reference at 
> least 
> > one type defined in the module." 
> > 
> > There may have to be a slight tweak for Base, though it is not hard to 
> argue 
> > that the primitive types are defined in Base. 
> > 
> > so 
> > 
> > module Module1 
> > type Bar end 
> > my( b::Bar ) = 1 
> > 
> > export my       # fine exports to the global space 
> > end 
> > 
> > module Module2 
> > type Foo end 
> > my() = 1 
> > 
> > export my       # ERROR exporting function which does not reference 
> local 
> > type 
> > end 
> > 
> > module Module3 
> > type Wow end 
> > my( w::Wow ) = 1 
> > my() = 1 
> > end 
> > export my       # Is an ERROR I can not export a function which does not 
> > reference a local type 
> > end 
> > 
> > So in the example provided my Mike above, multiple dispatch would do the 
> > right thing. If I also want to define a function for value in my module 
> it 
> > would work consistently against the types I define. We don't have to 
> perform 
> > recursive exports and import usage should be reduced. 
> > 
> > If you want to define an empty function you can do so with a default arg 
> > module Module4 
> > type Zee end 
> > my( ::Type{Zee} = Zee ) = 1 
> > export my       # Works, but I can select against it using multiple 
> dispatch 
> > by providing the last arg 
> > end 
> > 
> > 
> > I can't convince myself that exporting Types in general (nor macros) is 
> a 
> > good idea. 
> > 
> > A tweak may be to add C# like module alias syntax, which is just 
> syntactic 
> > sugar over what we have ( except that we would likely want the 
> definition of 
> > MY to be const in the scope. 
> > 
> > MY = using Foo.Bar.ReallyLongModuleName 
> > t = MY.Type() 
> > my( t ) 
> > 
> > 
> > Thoughts ? 
> > 
> > 
> > I'm sure there is something I have missed, but this simple rule would 
> seem 
> > to encourage multiple dispatch and support the development of modules. 
> > 
> > On Tuesday, April 21, 2015 at 1:07:40 PM UTC-4, Jeff Bezanson wrote: 
> >> 
> >> We're planning to do something about this: #4345. When `using` two 
> >> modules with conflicting names, we should do something other than pick 
> >> one depending on order. Most likely we will print a warning, and 
> >> require uses of the name to be qualified. 
> >> 
> >> If the two modules really do want to define different methods for the 
> >> same function, then either one has to import the other, or you have to 
> >> use your SuperSecretBase approach. 
> >> 
> >> On Tue, Apr 21, 2015 at 9:37 AM, Michael Turok <[email protected]> 
> >> wrote: 
> >> > Note that this can be made to work by tearing a page from Base:  we 
> can 
> >> > a 
> >> > module (SuperSecretBase), that defines a stub value() function. We 
> then 
> >> > use 
> >> > importall SuperSecretBase in each of Foo and Bar.    But this means 
> that 
> >> > any 
> >> > module we create would need to declare its functions into 
> >> > SuperSecretBase. 
> >> > 
> >> > julia> workspace() ; include("mike.jl") 
> >> > 
> >> > julia> using Foo 
> >> > 
> >> > julia> using Bar 
> >> > 
> >> > julia> value(Bar.BarType()) 
> >> > "Bar::value" 
> >> > 
> >> > julia> value(Foo.FooType()) 
> >> > "Foo::value" 
> >> > 
> >> > julia> 
> >> > 
> >> > Modified code follows: 
> >> > 
> >> > module SuperSecretBase 
> >> > value() = nothing 
> >> > export value 
> >> > end 
> >> > 
> >> > # ------------------------------ 
> >> > 
> >> > module Foo 
> >> > 
> >> > importall SuperSecretBase 
> >> > 
> >> > importall Base 
> >> > type FooType end 
> >> > 
> >> > value(x::FooType) = "Foo::value" 
> >> > get(x::FooType) = "Foo::get" 
> >> > 
> >> > export value 
> >> > 
> >> > end 
> >> > 
> >> > # ------------------------------ 
> >> > 
> >> > module Bar 
> >> > 
> >> > importall SuperSecretBase 
> >> > 
> >> > importall Base 
> >> > 
> >> > type BarType end 
> >> > 
> >> > value(x::BarType) = "Bar::value" 
> >> > get(x::BarType) = "Bar::get" 
> >> > 
> >> > export value 
> >> > 
> >> > end 
> >> > 
> >> > 
> >> > 
> >> > 
> >> > On Tuesday, April 21, 2015 at 9:26:01 AM UTC-4, Michael Turok wrote: 
> >> >> 
> >> >> Hi, 
> >> >> 
> >> >> What is the idiomatic way to create a function value() in different 
> >> >> modules, dispatched on different arguments, without getting the 
> >> >> warning/error about conflicting with an existing identifier? 
> >> >> 
> >> >> It seems like there is an order dependency with the example below. 
> >> >> Seems 
> >> >> like the 2nd module defines value(), unless you had already used 
> >> >> value() 
> >> >> prior to importing the 2nd module. 
> >> >> 
> >> >> Note that if I do the same with get() a function defined in Base, I 
> >> >> don't 
> >> >> get an error. 
> >> >> 
> >> >> Code and output from julia REPL below. 
> >> >> 
> >> >> Any help appreciated, 
> >> >> Michael 
> >> >> 
> >> >> # this is mike.jl 
> >> >> 
> >> >> # ------------------------------ 
> >> >> module Foo 
> >> >> # ------------------------------ 
> >> >> importall Base 
> >> >> type FooType end 
> >> >> 
> >> >> value(x::FooType) = "Foo::value" 
> >> >> get(x::FooType) = "Foo::get" 
> >> >> 
> >> >> export value 
> >> >> 
> >> >> end 
> >> >> 
> >> >> # ------------------------------ 
> >> >> module Bar 
> >> >> # ------------------------------ 
> >> >> importall Base 
> >> >> 
> >> >> type BarType end 
> >> >> 
> >> >> value(x::BarType) = "Bar::value" 
> >> >> get(x::BarType) = "Bar::get" 
> >> >> 
> >> >> export value 
> >> >> 
> >> >> end 
> >> >> 
> >> >> Using this in the REPL: 
> >> >> julia> workspace() ; include("mike.jl") 
> >> >> 
> >> >> julia> using Foo 
> >> >> 
> >> >> julia> value(Foo.FooType()) 
> >> >> "Foo::value" 
> >> >> 
> >> >> julia> using Bar 
> >> >> Warning: using Bar.value in module Main conflicts with an existing 
> >> >> identifier. 
> >> >> 
> >> >> julia> value(Bar.BarType()) 
> >> >> ERROR: `value` has no method matching value(::BarType) 
> >> >> 
> >> >> # ----------------------------------------------------- 
> >> >> 
> >> >> julia> workspace() ; include("mike.jl") 
> >> >> 
> >> >> julia> using Foo 
> >> >> 
> >> >> julia> using Bar 
> >> >> 
> >> >> julia> value(Foo.FooType()) 
> >> >> ERROR: `value` has no method matching value(::FooType) 
> >> >> 
> >> >> julia> value(Bar.BarType()) 
> >> >> "Bar::value" 
> >> >> 
> >> >> # ----------------------------------------------------- 
> >> >> 
> >> >> julia> workspace() ; include("mike.jl") 
> >> >> 
> >> >> julia> using Bar 
> >> >> 
> >> >> julia> using Foo 
> >> >> 
> >> >> julia> value(Foo.FooType()) 
> >> >> "Foo::value" 
> >> >> 
> >> >> julia> value(Bar.BarType()) 
> >> >> ERROR: `value` has no method matching value(::BarType) 
> >> >> 
> >> >> julia> 
>

Reply via email to