it's not clear (to me) how the classbox/namespace behavior for monkey patching works in practice.
Say I use module Dates that extends String, and module Inflections that does the same, as I want to use String#weeks and String#pluralize. But both redefine String#singular.
When I do "import Dates, Inflections" what happens? Which version of String#singular do I get?
If I import Dates, and then import Texts as I want to use String#stemmed_terms which in turn uses Inflections?
If I import two modules defining a same method with different signature does everything work fine?
> Say I use module Dates that extends String, and module Inflections that does the same, as I want to use String#weeks and String#pluralize. But both redefine String#singular.
If you do an unqualified import (i.e. import everything from both modules), that will be an error (well, it should be, I still need to implement this). If you just need #weeks and #pluralize, you can import just those:
import Dates weeks
import Inflections pluralize
If those two methods internally call singular, that will still be OK. If you actually need access to both versions of singular, you can rename on import:
> If I import Dates, and then import Texts as I want to use String#stemmed_terms which in turn uses Inflections?
That's OK since imports aren't transitive. If you import Texts, you'll just get what it exports not what it itself imports and uses.
> If I import two modules defining a same method with different signature does everything work fine?
...Maybe. This is probably the trickiest corner case of the language. If both of those modules share some import where that method is defined, then they will be defining specializations of the same multimethod and everything is fine. If those two modules are totally unrelated, then those are different multimethods entirely and you can't "merge" them when you import both.
For example, io defines an "open" multimethod. Let's say your module Doors also defines "open". In your App module, you want to import both. If Doors happens to import io, then its "open" is a specialization of that one, and App will be fine when it imports them both. If not, those are two different multimethods and you'll need to rename one when you import.
One way to look at it is that a multimethod is a bit like a virtual method (but not tied to a specific class). You can have a bunch of methods with the same name in the same module as long as they're all overriding the same base virtual method.
ah thanks for your reply, it seems a sensible system.
A last question (since when I tried to wrap my head around multimethods, OOP and modules for my toy language I always got lost and you probably have an answer).
Suppose I want to define a method local to an object in my main module, for example I want to have Dates#weeks use a custom #singular method.
For sake of polymorphism, I would expect that dispatching on my object should still invoke my method, but weeks is always referring to its own, I understand.
Do you believe this trade off (killing a bit of late binding, akin to having un-overrideable "private" members in java/c++) is necessary, or you just feel this is a good enough solution?
> I would expect that dispatching on my object should still invoke my method, but weeks is always referring to its own, I understand.
Correct. But if singular itself was publicly exported by Dates, when you defined your own specializations of it in your module, they will go into the same multimethod that Dates is using. The big limitation here is that you can't replace the version that Dates has specialized on String by specializing on the same type.
The way this works is that when you import a multimethod from another module, you're importing the exact same multimethod object that that module is using. If you then define your own specializations, the original module can see them too.
This is necessary to make overriding work at all, though it's a bit confusing in some ways. Honestly, I feel like I'm still trying to wrap my head around it too.
Say I use module Dates that extends String, and module Inflections that does the same, as I want to use String#weeks and String#pluralize. But both redefine String#singular.
When I do "import Dates, Inflections" what happens? Which version of String#singular do I get?
If I import Dates, and then import Texts as I want to use String#stemmed_terms which in turn uses Inflections?
If I import two modules defining a same method with different signature does everything work fine?