That's why I had asked the following:

If I understand correctly (and this is why I said at the very beginning, 
> part of this may be my newness to Julia), then if I have to explicitly 
> reference
> A.set_record, it will not work, because it will *not* dispatch to 
> BetterA.set_record...
> Is that correct or not?


So you are saying that that is not so, that once I've extended a function 
in A in my module BetterA, it doesn't matter if I call that function as 
A.func or BetterA.func?

Scott

On Saturday, April 25, 2015 at 10:24:54 PM UTC-4, Stefan Karpinski wrote:
>
> I think there's some confusion here.
>
> If BetterA extends a function from A then those are the same function 
> object and calling A's function is the same as calling BetterA's function 
> by that name.
>
> If several modules implement a common interface, they shouldn't simply 
> happen to use the same names – they should implement different methods of 
> the same function object, inherited from a common namespace. These methods 
> should dispatch on a connection object that determines who's method to use.
>
> On Apr 25, 2015, at 8:02 PM, Scott Jones <[email protected] 
> <javascript:>> wrote:
>
> I think you are again misunderstanding... I am *not* writing "generic" 
> code.
> I am writing code that accesses database A, with names like connect, 
> set_record, get_record, disconnect
> It's connect takes an argument of type A.DBManager, with some parameters 
> like address, port, user, password, and returns an A.DBConnection object.
> There is absolutely no ambiguity with the Base.connect, nor is the 
> interface necessarily even the same, *however*, it is what the users of 
> database A
> would *expect* as far as names (possibly identical names to database A's C 
> bindings).
> I also use some other code that extends that package, say BetterA, adding 
> useful stuff like being able to serialize / deserialize Julia objects, and 
> use set_record and get_record.
> That code was written with A in mind, and *explicitly* imports set_record 
> and get_record, extends them, and exports them.
> My code does using A, using BetterA, and then does things like:
> myconn = connect(aManager, "127.0.0.1", 3000, "scott", "") ; 
> set_record(myconn, myjuliaobject)
> That set_record is actually handled nicely by multiple dispatch, the 
> set_record in BetterA takes the Julia object, builds a string, and then 
> calls A's set_record.
>
> If I understand correctly (and this is why I said at the very beginning, 
> part of this may be my newness to Julia), then if I have to explicitly 
> reference
> A.set_record, it will not work, because it will *not* dispatch to 
> BetterA.set_record...
>
> Is that correct or not?
>
> Note, another reason I *don't* want to have to specify the module/package, 
> is what happens if I want to use another package, that implements the same 
> interface?
> For example, I started out using MongoDB.connect, MongoDB.set_document!, 
> etc., but then my old classmate, friend and great 6.111 partner Brad 
> Kuzsmaul comes along and convinces me that
> TokuMX is the greatest thing since sliced bread, so now I want to simply 
> do:
> using TokuMX instead of using MongoDB, and everything is hunky-dory, but 
> I'll be very sad if I had to go in and edit all the code to say 
> TokuMX.set_document instead of MongoDB.set_document!.
>
> Now, after I've gotten my code working for multiple data sources I realize 
> I need to connect to a KVS to use as the backend... So, I want to use a 
> package GTM, that has a
> connect(gtm_manager, cluster, namespace), and a set_node!(gtmconnect, 
> global, value, subscripts...).  Later, I discover that there is another 
> package GlobalsDB, that implements the same interface,
> and so I have the same issue, I don't want to have been forced to not do 
> using, when there are absolutely no ambiguities, and I really don't want to 
> have to use module names on my calls!
>
> The important point is that there can be different, unambiguous, perfectly 
> valid sets of functions, which do not implement the same interface, but 
> which may indeed implement different interfaces
> (MongoDB & TokuMX may implement some sort of Document DB interface, while 
> GTM & GlobalsDB implement an ANSI M interface, and MySQL & Postgres & 
> SQL_Server & ODBC all implement a SQL interface...
> and *all* of them are going to want to call things by the names that make 
> sense to users of their systems... and those users are also going to want 
> to be able to use multiple interfaces without hassle)
>
> This is all very real world...
>
> @kevin I hope this answers your question as well
>
>
>
> On Saturday, April 25, 2015 at 6:56:55 PM UTC-4, Jeff Bezanson wrote:
>
> In general connect(x, y, z) is dynamically dispatched: you don't 
> always know the type of `x`. So you wouldn't be able to write 
> *generic* code that uses connect. In generic code, there really can be 
> only one interface: if I write code that's supposed to work for any 
> `x`, and I say `connect(x, address, port)`, like it or not my code 
> only works for one of A and B, not both. 
>
>
> On Sat, Apr 25, 2015 at 6:25 PM, Scott Jones <[email protected]> 
> wrote: 
> > No, not at all. 
> > 
> > I have a bunch of code written using package A. 
> > It knows what the correct arguments are to the connect function for type 
> > AConnectionManager. 
> > I did using A, because having to specify all the time which package 
> (however 
> > short the name is), 
> > and it means that I wouldn't be able to use other packages with were 
> > designed to extend package A 
> >  (and did use the import A to extend the functions with new methods). 
> > 
> > Then I need to connect to another database package, that also used the 
> name 
> > connect, with other arguments, 
> > but no conflicting signatures at all. 
> > It has a connect(BConnectionManager, namespacename, globalname) function 
> > (with a set of methods). 
> > There might also be further packages which extend module B's functions, 
> > explicitly doing import B export extendedfunction 
> > I think that should work just fine, but you are saying that I *must* 
> specify 
> > B.connect, which then also means (AFAIK), 
> > that I won't get a C.connect that extends B.connect (and intended to). 
> > 
> > Why do you want to restrict what can be done, because you have this view 
> > that, like the Highlander, there can only be *one* true interface for a 
> > name? 
> > 
> > Scott 
> > 
> > On Saturday, April 25, 2015 at 6:13:11 PM UTC-4, Jeff Bezanson wrote: 
> >> 
> >> When two people write packages independently, I claim there are only 
> >> two options: (1) they implement a common interface, (2) they don't. To 
> >> pick option (1), there has to be some kind of centralization or 
> >> agreement. For option (2), which is effectively the default, each 
> >> package just gets its own totally separate function, and you have to 
> >> say which one you want. We're not saying "you'd better get together 
> >> with all other developers", because with option (2) you don't need to. 
> >> 
> >> IIUC, you're proposing option (3), automatically merge everybody's 
> >> methods, assuming they don't conflict. But I don't see how this can 
> >> work. We could have: 
> >> 
> >> module A 
> >> type AConnectionManager 
> >> end 
> >> 
> >> function connect(cm::AConnectionManager, port, address) 
> >> end 
> >> end 
> >> 
> >> module B 
> >> type BConnectionManager 
> >> end 
> >> 
> >> function connect(cm::BConnectionManager, address, port) 
> >> end 
> >> end 
> >> 
> >> Obviously, you cannot do `using A; using B`, and then freely use 
> >> `connect` and have everything work. The fact that the type of the 
> >> first argument distinguishes methods doesn't help. The rest of the 
> >> arguments don't match, and even if they did the behaviors might not 
> >> implement compatible semantics. The only options I see are my options 
> >> 1 and 2: (1) move to a common interface, or (2) specify A.connect or 
> >> B.connect in client code, because the interfaces aren't compatible. 
> >> 
> >> 
> >> On Sat, Apr 25, 2015 at 5:55 PM, Scott Jones <[email protected]> 
> >> wrote: 
> >> > The problem is, in practice, people *will* have names that collide, 
> and 
> >> > will 
> >> > not mean the same thing. 
> >> > It seems that people here are trying to say, if you have a particular 
> >> > name 
> >> > you'd like to use, 
> >> > you'd better get together with all other developers past and future 
> and 
> >> > hammer out who 
> >> > "owns" the name, and what concept it can be used for... (like 
> >> > mathematical 
> >> > sin and fun sin, 
> >> > or tree bark and dogs bark... it gets even worse when you consider 
> other 
> >> > languages... 
> >> > [Say I'm in Spain, and I write a robotics package that has a function 
> >> > "coger"..., and somebody in Argentina 
> >> > writes a function "coger" that does something, well, XXX...]) 
> >> > 
> >> > I just don't see this as working for any length of time (and I think 
> it 
> >> > is 
> >> > already breaking down with Julia... 
> >> > to me, the fact that DataFrames picked using ~ as a binary operator, 
> >> > when 
> >> > that might have been 
> >> > something that somebody wanted to use in the core language, shows how 
> >> > fragile things 
> >> > are now...) 
> >> > 
> >> > Scott 
> >> > 
> >> > On Saturday, April 25, 2015 at 5:27:10 PM UTC-4, Mauro wrote: 
> >> >> 
> >> >> I don't think it is realistic to expect be able to willy-nilly be 
> >> >> 'using' any number of packages and it just works.  The way you 
> propose 
> >> >> may work most of the time, however, there were some solid arguments 
> >> >> made 
> >> >> in this thread on how that can lead to hard to catch failures. 
> >> >> 
> >> >> And maybe more importantly, from a programmer's sanity perspective, 
> I 
> >> >> think it is imperative that one generic function does just one 
> >> >> conceptual thing.  Otherwise it gets really hard to figure out what 
> a 
> >> >> piece of code does. 
> >> >> 
> >> >> On Sat, 2015-04-25 at 22:24, Scott Jones <[email protected]> 
> wrote: 
> >> >> > On Saturday, April 25, 2015 at 3:58:16 PM UTC-4, Jeff Bezanson 
> wrote: 
> >> >> >> 
> >> >> >> I think this is just a different mindset than the one we've 
> adopted. 
> >> >> >> In the mindset you describe, there really *ought* to be only one 
> >> >> >> function with each name, in other words a single global 
> namespace. 
> >> >> >> As 
> >> >> >> long as all new definitions for a function have disjoint 
> signatures, 
> >> >> >> there are no conflicts. To deal with conflicts, each module has 
> its 
> >> >> >> own "view" of a function that resolves conflicts in favor of its 
> >> >> >> definitions. 
> >> >> >> 
> >> >> > 
> >> >> > As a practical point, *why* should I have to know about every 
> other 
> >> >> > package 
> >> >> > or module that users of my package might possibly want to use at 
> the 
> >> >> > same 
> >> >> > time? 
> >> >> > With the way it is now, it seems I have to force everybody to not 
> use 
> >> >> > using, and use fully specified names, which seems utterly against 
> the 
> >> >> > extensibility of Julia, 
> >> >> > because if I try to export a function, I must know the intentions 
> of 
> >> >> > every 
> >> >> > user, which packages they might load, etc. that might possibly 
> have 
> >> >> > the 
> >> >> > same name. 
> >> >> > 
> >> >> > I have a module that defines a packed database format, and I want 
> to 
> >> >> > define 
> >> >> > a length, push!, and getindex methods... 
> >> >> > Then (for examples sake) I also want to define a foobar method 
> that 
> >> >> > people 
> >> >> > can use, and be able to call it on objects from my module with 
> just 
> >> >> > foobar(db,arg1,arg2) (where db is from my class). 
> >> >> > All is well and good, but then some user complains that they can't 
> >> >> > use 
> >> >> > my 
> >> >> > package and package newdb, because coincidentally they also 
> defined a 
> >> >> > function 
> >> >> > called foobar, that does have a different signature. 
> >> >> > 
> >> >> > I believe they should be able to use both, as long as there aren't 
> >> >> > any 
> >> >> > real 
> >> >> > conflicts, *without* spurious warnings... 
> >> >> > 
> >> >> > 
> >> >> >> This approach has a lot in common with class-based OO. For 
> example 
> >> >> >> in 
> >> >> >> Python when you say `x.sin()`, the `sin` name belongs to a single 
> >> >> >> method namespace. Sure there are different namespaces for *top 
> >> >> >> level* 
> >> >> >> definitions, but not for method names. If you want a different 
> `sin` 
> >> >> >> method, you need to make a new class, so the `x` part is 
> different. 
> >> >> >> This corresponds to the requirement you describe of methods 
> >> >> >> referencing some new type from the same julia module. 
> >> >> >> 
> >> >> >> Well, that's not how we do things. For us, if two functions have 
> the 
> >> >> >> same name it's just a cosmetic coincidence, at least initially. 
> In 
> >> >> >> julia two functions can have the same name but refer to totally 
> >> >> >> different concepts. For example you can have Base.sin, which 
> >> >> >> computes 
> >> >> >> the sine of a number, and Transgressions.sin, which implements 
> all 
> >> >> >> sorts of fun behavior. Say Base only defines sin(x::Float64), and 
> >> >> >> Transgressions only defines sin(x::String). They're disjoint. 
> >> >> >> However, 
> >> >> >> if you say 
> >> >> >> 
> >> >> >> map(sin, [1.0, "sloth", 2pi, "gluttony"]) 
> >> >> >> 
> >> >> >> you can't get both behaviors. You'll get a method error on either 
> >> >> >> the 
> >> >> >> 1.0 or the string. You have to decide which notion of `sin` you 
> >> >> >> mean. 
> >> >> >> We're not going to automatically merge the two functions. 
> >> >> >> 
> >> >> >> 
> >> >> > 
> >> >> > I'm not saying you should... on the other hand, if I have to 
> >> >> > functions 
> >> >> > from 
> >> >> > different packages, developed independently, 
> >> >> > that happen to have a name in common, (but with different 
> >> >> > signatures), 
> >> >> > the 
> >> >> > users should not have to somehow get the developers 
> >> >> > together (who may not even be around anymore), to somehow resolve 
> the 
> >> >> > conflict (which would probably adversely affect other users 
> >> >> > of both packages if some names had to be changed) 
> >> >> > 
> >> >> > Then if we 
> >> >> >> see the same name appearing in multiple packages, we decide if 
> there 
> >> >> >> is indeed a common interface, and if so move the packages to 
> using 
> >> >> >> it, 
> >> >> >> e.g. by creating something like StatsBase or maybe adding 
> something 
> >> >> >> to 
> >> >> >> Base. But we don't want Base to grow much more, if at all. 
> >> >> > 
> >> >> > 
> >> >> > I'm sorry, but that just seems like a recipe for disaster... you 
> are 
> >> >> > saying 
> >> >> > that *after* users finally 
> >> >> > decide they want to use two packages together, that then somehow 
> you 
> >> >> > will 
> >> >> > force the 
> >> >> > developers of the packages to agree on a common interface, or 
> change 
> >> >> > the 
> >> >> > names of conflicting functions, 
> >> >> > or make everybody use names qualified with the module name(s)... 
> >> >> > 
> >> >> > As for your map, example... 
> >> >> > If instead, I have map(sin, [1.0, myslothdays, 2pi, 
> mygluttonydays] 
> >> >> > ), 
> >> >> > where myslothdays and mygluttonydays both have the type 
> MySinDiary, 
> >> >> > and 
> >> >> > there is a Transgressions.sin(x::Transgressions.MySinDiary) 
> method... 
> >> >> > that should work, right? 
> >> >> > 
> >> >> > What is a good reason for it not to work? 
> >> >> > 
> >> >> > Scott 
> >> >> > 
> >> >> > On Sat, Apr 25, 2015 at 3:27 PM, Scott Jones <
> [email protected] 
> >> >> >> <javascript:>> wrote: 
> >> >> >> > My point is, if I have been careful, and export methods that 
> >> >> >> > always 
> >> >> >> > reference at least one of type defined locally in my module, so 
> >> >> >> > that 
> >> >> >> they 
> >> >> >> > should always be unambiguous, I should NOT have to know about 
> any 
> >> >> >> > other 
> >> >> >> > module (or Base) that a user of my module might also be using 
> >> >> >> > having 
> >> >> >> > a 
> >> >> >> > function with the 
> >> >> >> > same name, and should NOT have to do an import. 
> >> >> >> > 
> >> >> >> > For methods where I *am* trying to extend some type defined in 
> >> >> >> > another 
> >> >> >> > module/package or base, then yes, I believe you should do 
> >> >> >> > something 
> >> >> >> > explicitly to indicate that. 
> >> >> >> > 
> >> >> >> > I don't think there is any real conflict here... right now it 
> is 
> >> >> >> > too 
> >> >> >> > restrictive when the module's programmer has clearly signaled 
> >> >> >> > their 
> >> >> >> intent 
> >> >> >> > by always using their own, unambiguous 
> >> >> >> > signitures for their functions. 
> >> >> >> > 
> >> >> >> > Have I got something fundamentally wrong here? 
> >> >> >> > 
> >> >> >> > Thanks, 
> >> >> >> > Scott 
> >> >> >> > 
> >> >> >> > On Saturday, April 25, 2015 at 2:10:25 PM UTC-4, Jeff Bezanson 
> >> >> >> > wrote: 
> >> >> >> >> 
> >> >> >> >> Scott, the behavior you're trying to get sounds to me like "IF 
> >> >> >> >> this 
> >> >> >> >> function exists in Base then I want to extend it, otherwise 
> just 
> >> >> >> >> make 
> >> >> >> >> my own version of the function". That strikes me as a hack. 
> What 
> >> >> >> >> we've 
> >> >> >> >> tended to do is let everybody define whatever they want. Then 
> if 
> >> >> >> >> we 
> >> >> >> >> see the same name appearing in multiple packages, we decide if 
> >> >> >> >> there 
> >> >> >> >> is indeed a common interface, and if so move the packages to 
> >> >> >> >> using 
> >> >> >> >> it, 
> >> >> >> >> e.g. by creating something like StatsBase or maybe adding 
> >> >> >> >> something 
> >> >> >> >> to 
> >> >> >> >> Base. But we don't want Base to grow much more, if at all. 
> >> >> >> >> 
> >> >> >> >> Getting an error for using both Base and your package seems 
> >> >> >> >> annoying, 
> >> >> >> >> but alternatives that involve doing "something" silently 
> surely 
> >> >> >> >> must 
> >> >> >> >> be considered worse. If a colliding name gets added to Base, 
> the 
> >> >> >> >> default behavior should not be to assume that you meant to 
> >> >> >> >> interfere 
> >> >> >> >> with its behavior. 
> >> >> >> >> 
> >> >> >> >> On Sat, Apr 25, 2015 at 1:57 PM, Jeff Bezanson 
> >> >> >> >> <[email protected]> 
> >> >> >> >> wrote: 
> >> >> >> >> > Michael, that's not a bad summary. I would make a couple 
> edits. 
> >> >> >> >> > You 
> >> >> >> >> > don't really need to qualify *all* uses. If you want to use 
> >> >> >> >> > `foo` 
> >> >> >> from 
> >> >> >> >> > module `A`, you can put `import A.foo` at the top and then 
> use 
> >> >> >> >> > `foo` 
> >> >> >> >> > in your code. That will have no surprises and no breakage. 
> >> >> >> >> > 
> >> >> >> >> > Also I think calling it "SuperSecretBase" makes it sound 
> worse 
> >> >> >> >> > than 
> >> >> >> it 
> >> >> >> >> > is. You can have modules that describe a certain named 
> >> >> >> >> > interface, 
> >> >> >> >> > and 
> >> >> >> >> > then other modules extend it. Which reminds me that I need 
> to 
> >> >> >> >> > implement #8283, so you can introduce functions without 
> adding 
> >> >> >> methods 
> >> >> >> >> > yet. 
> >> >> >> >> > 
> >> >> >> >> > On Sat, Apr 25, 2015 at 12:31 PM, Stefan Karpinski 
> >> >> >> >> > <[email protected]> wrote: 
> >> >> >> >> >> Scott, I'm not really understanding your problem. Can you 
> give 
> >> >> >> >> >> an 
> >> >> >> >> >> example? 
> >> >> >> >> >> 
> >> >> >> >> >> 
> >> >> >> >> >> On Sat, Apr 25, 2015 at 11:53 AM, Scott Jones 
> >> >> >> >> >> <[email protected]> 
> >> >> >> 
> >> >> >> >> >> wrote: 
> >> >> >> >> >>> 
> >> >> >> >> >>> A problem I'm running into is the following (maybe the 
> best 
> >> >> >> practice 
> >> >> >> >> >>> for 
> >> >> >> >> >>> this is documented, and I just to stupid to find it!): 
> >> >> >> >> >>> I have created a set of functions, which use my own type, 
> so 
> >> >> >> >> >>> they 
> >> >> >> >> >>> should 
> >> >> >> >> >>> never be ambiguous. 
> >> >> >> >> >>> I would like to export them all, but I have to import any 
> >> >> >> >> >>> names 
> >> >> >> that 
> >> >> >> >> >>> already exist... 
> >> >> >> >> >>> Then tomorrow, somebody adds that name to Base, and my 
> code 
> >> >> >> >> >>> no 
> >> >> >> longer 
> >> >> >> >> >>> works... 
> >> >> >> >> >>> I dislike having to explicitly import names to extend 
> >> >> >> >> >>> something, 
> >> >> >> how 
> >> >> >> >> >>> am I 
> >> >> >> >> >>> supposed to know in advance all the other names that could 
> be 
> >> >> >> >> >>> used? 
> >> >> >> >> >>> 
> >> >> >> >> >>> What am I doing wrong? 
> >> >> >> >> >>> 
> >> >> >> >> >>> On Saturday, April 25, 2015 at 11:20:14 AM UTC-4, Stefan 
> >> >> >> >> >>> Karpinski 
> >> >> >> >> >>> wrote: 
> >> >> >> >> >>>> 
> >> >> >> >> >>>> I think you're probably being overly optimistic about how 
> >> >> >> >> >>>> infrequently 
> >> >> >> >> >>>> there will be dispatch ambiguities between unrelated 
> >> >> >> >> >>>> functions 
> >> >> >> that 
> >> >> >> >> >>>> happen 
> >> >> >> >> >>>> to have the same name. I would guess that if you try to 
> >> >> >> >> >>>> merge 
> >> >> >> >> >>>> two 
> >> >> >> >> >>>> unrelated 
> >> >> >> >> >>>> generic functions, ambiguities will exist more often than 
> >> >> >> >> >>>> not. 
> >> >> >> >> >>>> If 
> >> >> >> you 
> >> >> >> >> >>>> were 
> >> >> >> >> >>>> to automatically merge generic functions from different 
> >> >> >> >> >>>> modules, 
> >> >> >> >> >>>> there are 
> >> >> >> >> >>>> two sane ways you could handle ambiguities: 
> >> >> >> >> >>>> 
> >> >> >> >> >>>> warn about ambiguities when merging happens; 
> >> >> >> >> >>>> raise an error when ambiguous calls actually occur. 
> >> >> >> >> >>>> 
> >> >> >> >> >>>> Warning when the ambiguity is caused is how we currently 
> >> >> >> >> >>>> deal 
> >> >> >> >> >>>> with 
> >> >> >> >> >>>> ambiguities in individual generic functions. This seems 
> like 
> >> >> >> >> >>>> a 
> >> >> >> good 
> >> >> >> >> >>>> idea, 
> >> >> >> >> >>>> but it turns out to be extremely annoying. In practice, 
> >> >> >> >> >>>> there 
> >> >> >> >> >>>> are 
> >> >> >> >> >>>> fairly 
> >> >> >> >> >>>> legitimate cases where you can have ambiguous 
> intersections 
> >> >> >> between 
> >> >> >> >> >>>> very 
> >> >> >> >> >>>> generic definitions and you just don't care because the 
> >> >> >> >> >>>> ambiguous 
> >> >> >> >> >>>> case makes 
> >> >> >> >> >>>> no sense. This is especially true when loosely related 
> >> >> >> >> >>>> modules 
> >> >> >> extend 
> >> >> >> >> >>>> shared 
> >> >> >> >> >>>> generic functions. As a result, #6190 has gained a lot of 
> >> >> >> >> >>>> support. 
> >> >> >> >> >>>> 
> >> >> >> >> >>>> If warning about ambiguities in a single generic function 
> is 
> >> >> >> >> >>>> annoying, 
> >> >> >> >> >>>> warning about ambiguities when merging different generic 
> >> >> >> >> >>>> functions 
> >> >> >> >> >>>> that 
> >> >> >> >> >>>> happen share a name would be a nightmare. Imagine popular 
> >> >> >> >> >>>> packages 
> >> >> >> A 
> >> >> >> >> >>>> and B 
> >> >> >> >> >>>> both export a function `foo`. Initially there are no 
> >> >> >> >> >>>> ambiguities, 
> >> >> >> so 
> >> >> >> >> >>>> things 
> >> >> >> >> >>>> are fine. Then B adds some methods to its `foo` that 
> >> >> >> >> >>>> introduce 
> >> >> >> >> >>>> ambiguities 
> >> >> >> >> >>>> with A's `foo`. In isolation A and B are both fine – so 
> >> >> >> >> >>>> neither 
> >> >> >> >> >>>> package 
> >> >> >> >> >>>> author sees any warnings or problems. But suddenly every 
> >> >> >> >> >>>> package 
> >> >> >> in 
> >> >> >> >> >>>> the 
> >> >> >> >> >>>> ecosystem that uses both A and B – which is a lot since 
> >> >> >> >> >>>> they're 
> >> >> >> both 
> >> >> >> >> >>>> very 
> >> >> >> >> >>>> popular – is spewing warnings upon loading. Who is 
> >> >> >> >> >>>> responsible? 
> >> >> >> >> >>>> Package A 
> >> >> >> >> >>>> didn't even change anything. Package B just added some 
> >> >> >> >> >>>> methods 
> >> >> >> >> >>>> to 
> >> >> >> its 
> >> >> >> >> >>>> own 
> >> >> >> >> >>>> function and has no issues in isolation. How would 
> someone 
> >> >> >> >> >>>> using 
> >> >> >> both 
> >> >> >> >> >>>> A and 
> >> >> >> >> >>>> B avoid getting these warnings? They would have to stop 
> >> >> >> >> >>>> writing 
> >> >> >> >> >>>> `using A` or 
> >> >> >> >> >>>> `using B` and instead explicitly import all the names 
> they 
> >> >> >> >> >>>> need 
> >> >> >> from 
> >> >> >> >> >>>> either 
> >> >> >> >> >>>> A or B. To avoid inflicting this on their users, A and B 
> >> >> >> >> >>>> would 
> >> >> >> have 
> >> >> >> >> >>>> to 
> >> >> >> >> >>>> carefully coordinate to avoid any ambiguities between all 
> of 
> >> >> >> >> >>>> their 
> >> >> >> >> >>>> generic 
> >> >> >> >> >>>> functions. Except that it's not just A and B – it's all 
> >> >> >> >> >>>> packages. 
> >> >> >> At 
> >> >> >> >> >>>> that 
> >> >> >> >> >>>> point, why have namespaces with exports at all? 
> >> >> >> >> >>>> 
> >> >> >> >> >>>> What if we only raise an error when making calls to `foo` 
> >> >> >> >> >>>> that 
> >> >> >> >> >>>> are 
> >> >> >> >> >>>> ambiguous between `A.foo` and `B.foo`? This eliminates 
> the 
> >> >> >> >> >>>> warning 
> >> >> >> >> >>>> annoyance, which is nice. But it makes code that uses A 
> and 
> >> >> >> >> >>>> B 
> >> >> >> >> >>>> that 
> >> >> >> >> >>>> calls 
> >> >> >> >> >>>> `foo` brittle in dangerous ways. Suppose, for example, 
> you 
> >> >> >> >> >>>> call 
> >> >> >> >> >>>> `foo(x,y)` 
> >> >> >> >> >>>> somewhere and initially this can only mean `A.foo` so 
> things 
> >> >> >> >> >>>> are 
> >> >> >> >> >>>> fine. But 
> >> >> >> >> >>>> then you upgrade B, which adds a method to `B.foo` that 
> also 
> >> >> >> matches 
> >> >> >> >> >>>> the 
> >> >> >> >> >>>> call to `foo(x,y)`. Now your code that used to work will 
> >> >> >> >> >>>> fail 
> >> >> >> >> >>>> at 
> >> >> >> run 
> >> >> >> >> >>>> time – 
> >> >> >> >> >>>> and only when invoked with ambiguous arguments. This case 
> >> >> >> >> >>>> may 
> >> >> >> >> >>>> be 
> >> >> >> >> >>>> possible 
> >> >> >> >> >>>> but rare and not covered by your tests. It's a ticking 
> time 
> >> >> >> >> >>>> bomb 
> >> >> >> >> >>>> introduced 
> >> >> >> >> >>>> into your code just by upgrading dependencies. 
> >> >> >> >> >>>> 
> >> >> >> >> >>>> The way this issue has actually been resolved, if you 
> were 
> >> >> >> >> >>>> using A 
> >> >> >> >> >>>> and B 
> >> >> >> >> >>>> and call `foo`, initially only is exported by A, as soon 
> as 
> >> >> >> package B 
> >> >> >> >> >>>> starts 
> >> >> >> >> >>>> exporting `foo`, you'll get an error and be forced to 
> >> >> >> >> >>>> explicitly 
> >> >> >> >> >>>> disambiguate `foo`. This is a bit annoying, but after 
> you've 
> >> >> >> >> >>>> done 
> >> >> >> >> >>>> that, your 
> >> >> >> >> >>>> code will no longer be affected by any changes to `A.foo` 
> or 
> >> >> >> `B.foo` 
> >> >> >> >> >>>> – it's 
> >> >> >> >> >>>> safe and permanently unambiguous. This still isn't 100% 
> >> >> >> bulletproof. 
> >> >> >> >> >>>> When 
> >> >> >> >> >>>> `B.foo` is initially introduced, your code that used 
> `foo`, 
> >> >> >> expecting 
> >
>
> ...

Reply via email to