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

Reply via email to