

Want to hack on the Magpie programming language? - munificent
http://journal.stuffwithstuff.com/2011/06/06/magpie-wants-you/

======
riffraff
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?

~~~
munificent
> 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:

    
    
        import Dates singular = Dates.singular
        import Inflections singular = Inflections.singular
    

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

~~~
riffraff
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?

~~~
munificent
> 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.

