[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Are all functions multi-methods?
Steven Shaw <steven_shaw@iprimus.com.au> wrote:
> "Neelakantan Krishnaswami" <neelk@alum.mit.edu> wrote in message
> >
> > define function foo(x) // #1
> > x + x
> > end;
> >
> > begin // #2
> > let foo = method(x) x + x end;
> > // ...
> > end;
> >
> > begin // #3
> > local method bar(x) x + x end;
> > // ...
> > end;
> >
>
> ok now I'm more confused :-) So these all examples of "normal"
> functions that won't be dispatched by the argument types? The
> 'method' function creates a function?
Okay, let me try and be more precise about terminology, to see if I
can't clear things up. If you look at the class hierarchy, you can see
that the hierarchy for function objects looks like this:
<function>
|
+----------+---------+
| |
<method> <generic-function>
A <method> is a function kind of like in C or Python -- you call it
with some arguments, and it does some work and returns some values. A
<generic-function> is the thing that enables dynamic dispatch. It
contains a set of <method>s, and when you call a <generic-function>,
it looks at the types of its arguments, and then picks which <method>
to execute. Now, I'll try explaining what each of the three forms I
wrote up there does:
#2 An expression like 'method(x) x + x end' is just literal syntax for
a <method>, just like "avocado" is the literal syntax for a <string>.
#3 If you think about the expression in #2, you'll realize that you
can't write recursive functions with a method expression. To fix this,
the local statement was introduced. It lets you define a recursive
method, like this:
begin
local method fact(n)
if (n.zero?)
1
else
n * fact(n - 1) // we refer to fact within its body
end if;
end method;
//
fact(5) // fact is a variable bound to a <method>
end;
#1 Now, you have the pieces to understand 'define function' very
easily. It's just a macro that expands like this:
define function foo(x)
x + x ---> define constant foo = method(x) x + x end;
end function;
And as an added bonus, I'll even throw in a description of what
generic-definer and method-definer do!
When you write a statement like:
define generic move(pt :: <point>) => ();
You tell the Dylan compiler to create a <generic> object. Then, when
you write:
define method move(pt :: <point>) => ()
pt.x := pt.x + 1;
pt.y := pt.y + 1;
end method move;
a method is created and added to the <generic>. If there is no generic
definition, then a default one will be created, and the method added
to that.
> How do you call these functions? Is it always the same? The
> functions in your examples - would they be called like this:?
>
> 1. foo(1) -- calling global function
> 2. foo(1) -- calling function value
> 3. bar(1) -- calling local function
The syntax for calling any function is always the same. The Dylan
compiler and runtime will figure out the right thing to do, and do it.
In fact, the compiler does quite a bit of work to make everything as
efficient as possible, but it does all its optimizations in such a way
that the model I've described always appears to be true. You don't
need to think about it at all.
--
Neel Krishnaswami
neelk@alum.mit.edu