On Saturday, May 16, 2015 at 8:50:12 AM UTC-4, ele...@gmail.com wrote: > > >> If Module A has connect(value::Any), and I add a module B with >> connect(value::TypeB), I don't see a problem with calls to connect with >> something of TypeB "changing" the behavior >> of Module A by not letting it grab *all* calls to connect(). >> Maybe it's still too early in the morning, but I still don't see the >> problem here... you go to the most specific type, not the the generic one... >> > > Example, assume there exists an entity relationship graph module that has > a "connect" function that connects a relationship between two named nodes > and attaches a piece of unknown data: > > module relationship > connect(data::Any, from::UTF8string, to::UTF8string) = ... > end > > And a database module where you connect to the named database with a > username, note this obeys the rule "must use type defined in same module": > > module scotts_database_module > type scotts_database end > connect(db::scotts_database, name::UTF8string, user::UTF8string) = ... > end > > In my user code *assuming functions merged* : > > using relationships, scotts_database_module # function connect now has two > methods > > #I make lots of relationship connections like > connect(1, "nodea", "nodeb") # connection with an integer data > connect("some text", "nodeb", "nodec") # connection with a string data > # now I want to connect two nodes with one of your excellent databases as > the data > sd = scotts_database() > connect(sd, "nodea", "nodeb") # connection with a database data > > huh? why is my best customer getting a *runtime* error "no database named > 'nodea'"? >
OK, I'd say that is something the user will need to solve, and the documentation for the relationship "connect", because it is making a totally generic function, using types not defined by it, is the one that should "lose" in this situation. The user didn't *have* to use "using" for the relationships module... and people who write modules like relationships, since they are making a very generic function, need to be careful about the names they chose, or not export those names. connect() is an obvious very bad choice... > > [...] > >> Maybe this is just in 0.4, but you can specify the type of a Varargs >> parameter, i.e. x::TypeB... >> > > Yes, but there can still be any number of parameters of that type in a > call. f(x::TypeB...) has to be checked against f(a::TypeA, b::TypeB, > c::TypeC) because the relationship between TypeA and TypeB and between > TypeC and TypeB could be such that again merging these functions will > change the dispatch of f(x::TypeB...). Its not impossible to do it, but it > significantly complicates the checking algorithm. > Are you saying that this is an issue if TypeA <: TypeB, or TypeC <: TypeB? Otherwise, I don't see a problem. > > [...] > >> I mean if the method is a parametric method eg f{T}(a::T) the type of 'a' >>> depends on the parameter T. IIUC the method f{T} gets re-compiled for all >>> types that it gets as parameters, where there is no existing method, so, >>> without knowing all *uses* of f(), Julia can't know which methods exist to >>> merge. >>> >> >> In that case, the module writer would need to have something like f{T <: >> Union(TypeB, MyOtherBType)} in order for the compiler to use T. >> > > Probably its too late (timezones!!), but I don't see what you mean? > In order to T to act to make the method unambigous, T must be of a type defined in that module. So, if you had something like f(T)(a::T), wihtout restricting T as above with the Union, it could not be declared to be unambigous, and the compiler could easily detect that and give an error. > > >> >> However, I'd said that I wouldn't depend on that, I'd want a keyword for >> function definition, that declares that this function is designed to be >> unambigous >> (the compiler should still do the checking though). >> > > I am all for being explicit, but I'm not sure what you want the keyword > semantics to be? > > >> [...] >> >> If each module is using functions with different types, how can their >> behavior change? >> > > Indeed, if *each* module is using types that do not overlap it cannot, > what I was saying was that you need to check that by looking at *both* > modules, not just locally at one module. > > >> [...] >> > > >> Again, I think with a keyword or syntax to show that the programmer means >> this to be a new generic function, that the programmer makes the guarantee >> that it is unambiguous, >> it is. >> > > In the scotts_database example above, how could you, as the writer of that > module make such a guarantee, you have no way of knowing I would use your > module with the relationship module, in fact you didn't even know it > existed. Or "connect" could even just be a function in the users own code, > not even in a module. > I can make that guarantee, because my functions that I (using new syntax) make that guarantee for, all use a type defined in my module. Since that will always be the most specific type, that is what always will be dispatched to. > >> >>> >>>> 3) If it is meant to be only callable via module.name (or >>>> module.module.name [etc]), outside the module, i.e. it is not allowed >>>> to make it extend something at the higher level. >>>> >>> >>> "Only callable by qualified name" depends on the situation in the user >>> code, which modules they "using" into a specific scope. When a module is >>> being compiled this is not known, so it can't affect anything in the module. >>> >> >> No, I am saying that this is a new capability that Julia presently does >> not have (AFAIK). How do you say that the user code is not allowed to use >> "using" on this function? >> > > Don't export it? > I did some test cases, and even not exported, things leak out... maybe it's a bug... > > >> [...] >> What I'm saying is that ONLY for functions where the module writer has >> specified that the method(s) are supposed to be unambigous, would it do any >> tests and try to merge. >> > Otherwise, it should act as it does now for exported functions, and simply >> not merge if the name conflicts. >> > > Again I'm not sure how the module writer can know that? > By always using a type defined in the module... > > >> [...] >>> Agree, you can't extend a function from another module in a way thats >>> only visible in this module. Thats why extension needs to be explicit "I >>> do mean it, and I understand it has global consequences". But independent >>> objects that are not exported should already be isolated properly I believe. >>> >>> >> Unfortunately, they leak into the global method table :-( >> > > Which "they" do you mean? > > methods that extend functions, even if they don't export... seems pretty bad to me... > >> Scott >> >