Magpie doesn't let you do that. If it did, it wouldn't look like that
because methods live in lexical scope and aren't actually looked up on
the object.
Even so, it also doesn't let you refer to methods in lexical scope by
name either. This is more or less by design because I'm trying to
avoid some of the bad performance implications of having being able to
refer to things by name.
> 2. I couldn't find a dictionary/map class which would allow me to build #1
Maps have been on my todo list for a while...
> 3. I couldn't find any way to reference a method by signature, such as
> val foo = bar // Where bar is the name of a method (of course more
> complicated with multimethods and type signatures)
Strangely enough, methods aren't first-class in Magpie. They live in a
different namespace from variables and you can't get a reference to
one without invoking it. Functions, however, *are* first class, so you
can first class-ify a method by making a little function that invokes
it:
def (left) foo(right)
print(left + " foo(" + right + ")")
end
var wrapper = fn(left, right) left foo(right)
Now you can pass around wrapper and invoke it as you please. Note that
you have to use the call method to call a function:
wrapper call("left", "right")
>
> As I understand it, records are like tuples, so you can't use them quite
> like dictionaries.. unless I'm wrong. Does anyone have any ideas?
Records are kinda-sorta like dictionaries but more limited: they are
immutable and can only be created from literals. Records are to
dictionaries as tuples are to lists. I've gotten to lists (and arrays,
their immutable brother), but I haven't implemented maps/dictionaries
yet.
If you were feeling crazy, you could implement one yourself completely
in Magpie, but that's likely the kind of thing that should be provided
directly by the language for performance reasons.
- bob
Very nice. That looks exactly like I'd hoped this would work.
One thing to consider: if you find yourself often needing to select a
method parametrically like this, I think that's a hint to actually
make a parameter. What you're doing here is fine, but you could also
have a single mouseEvent method that took an argument for the type
that you could then specialize on, like:
def (view is View) mouse("down", point is Point)
print("mouse down at " + point)
end
def (view is View) mouse("up", point is Point)
print("mouse up at " + point)
end
view sendEvent(MouseEvent new(Event: (type: "down"), point: point))
def (this is View) sendEvent(event is MouseEvent)
print(">>>", this subviews)
for subview in this subviews do
if subview contains(event point) then
return subview sendEvent(event point - this origin)
end
end
mouse(event type, event point)
this
end
Since methods can specialize on values too, it's pretty easy to make a
set of methods that you "switch" on by some value.
- bob
method parametrically like this, I think that's a hint to actuallyOne thing to consider: if you find yourself often needing to select a
make a parameter.
Right. We may go in the direction at some point, but I'm trying to see
how far we can get without actually referring to things by name.
Avoiding doing so I think makes it easier to compile to efficient code
(all identifiers can be erased) and makes things like tree shaking
(removing unused code) easier and I don't want to give those up unless
we get something really useful in return.
- bob