[Omake] test/object/Test14
Jason Hickey
jyh at cs.caltech.edu
Thu Aug 2 12:07:48 PDT 2007
On Aug 2, 2007, at 9:45 AM, Aleksey Nogin wrote:
> 1) "Naive user / principle of lease surprise" argument. The goal of
> foreach is to be a simple iterator. For an array A, there should
> not be a difference between "A.foreach(key)" and "foreach(key, $A)".
>
> 2) "Namespaces" argument. Prior to the method call, we have to
> disjoint unrelated namespaces - the "this" namespace of the caller
> and the object fields namespace. Our implementation not only
> confuses the two, but allows the object namespace to "steal" from
> the "original this" namespace.
>
> Note that in the above example, even if "map" was not an object
> field, it will become one under your semantics. Also note that the
> fact that the function arguments are currently in "this" namespace
> only makes it easier to hit this problem, but it has no direct
> relation to it.
>
> 3) "High-level straightforwardness" argument. Fully exported
> fragments of code ought to be locally equivalent to imperative
> interpretation.
I don't agree with any of these arguments. We really must not define
some funky semantics of binding. Let me give a different example, to
show that this has nothing to do with exports/hoisting.
X. =
x = 0
f() =
println($x)
Y. =
x = 1
call() =
f()
Y.call()
The program prints "1". This is because, even though f() is defined
as a method of X, it is called as a method of Y.
The real issue is the meaning of a simple application f(). What it
currently means is that the function f should be called as a method
of the current object--regardless of where f() was originally
defined. There are lots of other examples, like "f = $(A.B.C.g); f
()" will extract the method A.B.C.g and call it as a method of the
current object, etc.
We _could_ choose the alternative semantics, that methods are
strictly bound to their object, and so a method value would have to
be a kind of closure. But it wouldn't work very well, because the
closure would be statically defined.
Alternatively, we could rewrite the code to do what we think the
programmer really meant, but I don't like it.
X. =
...
Y. =
...
call() =
X.f()
Do you see why this example is related? The problem is that in
"A.foreach(key => ...)" the function "key => ..." is called as a
method of A, not a method of the current object, so when you define
this.map you are defining a field of A. Again, it has nothing to do
with hoisting. There is the dual problem that A's fields shadow the
function parameter.
All that being said, we could think about some way to get what you
want specifically for foreach. Basically, a way to do the following
translation.
Original:
A.foreach(key => exp)
Translates to:
apply(key) =
exp
public.obj = $(this)
A.foreach(key => ...)
obj.apply($(key))
export
this = $(obj)
In any case, I think we should undo the changes to the hoisting code.
Jason
--
Jason Hickey http://www.cs.caltech.edu/~jyh
Caltech Computer Science Tel: 626-395-6568 FAX: 626-792-4257
More information about the OMake-Devel
mailing list