On Saturday, May 16, 2015 at 8:50:12 AM UTC-4, [email protected] 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
>>
>