Cheers
-- Martin
I'm surprised because I thought two new methods were added, for
getters and setters. They are gone, then? Not that I mind either way,
but... it does suprise me. :-)
Now, I do have one issue with it, that I did not bring up on the
document. This is a flexible tool, granted, but there's one particular
use case people want, which is the dynamic reference (like C#'s
dynamic). It can easily be implemented using Dynamic, and I wonder if
it cannot be further improved by extending AnyVal, which would avoid
the extra indirection. Let me give a brief example, just to make sure
we are all on the same page:
class DynamicRef(val underlying: Any) extends Dynamic {
def applyDynamic(m: String)(parms: Any*): Any = ??? // reflection
call on underlying
// def respondsTo? dynamic languages usually have a method like that
}
object DynamicRef {
implicit def apply(obj: Any): DynamicRef = new DynamicRef(obj)
}
def f(o: Any) {
val r: DynamicRef = o
r.doStuff()
}
So, it is simple to implement (at least I expect that to be the case
with Scala's own reflection library), but it is _not_ implemented by
default, and I think that's a mistake. This is a common enough use
case that it warrants inclusion in the standard library. Now, I'll
grant that I'm often asking for things in the standard library (though
there are things I think should be gone from there as well), but this
is one I don't particularly care for in my own code. I've seen plenty
evidence on mailing lists and Stack Overflow, however, that others do
want it.
--
Daniel C. Sobral
I travel to the future all the time.
> 1) First of all, methods. BindInvokeMember supports named arguments.
> CSharpInvokeMemberBinder (internal class emitted by C# compiler) also
> supports type arguments. I think, these two features should also be
> supported by applyDynamic (presumably by detecting applyDynamic calls in
> doTypedApply and augmenting it with type arguments and info about parameter
> names).
Ah, yes. Named parameters. Another staple of today's dynamic languages.
> 2) There are six more binders to represent various variations on methods.
> This category also includes BindBinaryOperation, BindUnaryOperation,
> BindGetMember, BindGetIndex, BindSetIndex, BindSetMember. These guys are
> mostly covered by applyDynamic as I understand it, but there's a minor
> nuisance. How do you distinguish between a field getter and a nullary method
> invocation from applyDynamic's PoV?
I expected that was one reason why getters had their own methods, and
my surprising at finding out they don't (anymore?).
> 4) Applications. With InvokeBinder C# virtualizes direct applications of
> dynamic stuff (e.g. "dynamic x = blah; x(42)"). Again, not sure whether we
> need that (that's why I called for some use cases), but this is also
> something that's not currently supported.
I'm not sure I understand this. I'd expect Scala to translate that
into an "apply" call, which ought to suffice for any Scala or Java
object. Do you mean "blah" being a method invocation?
obj.applyDynamic("meth")("Bob", age = 13)
and then it would be up to applyDynamic to define the right-named
parameters. In all likelihood that would fail. What else can we do?
Package the parameter names somehow with the arguments? Then how to
pass them to the method? Postulate a
method
applyDynamicNamed
and rewrite to
obj.applyDynamicNamed("meth")(() -> "Bob", "age" -> 13)
It's a possibility. It does add to the complexity of the proposal but not much.
> 2) There are six more binders to represent various variations on methods.
> This category also includes BindBinaryOperation, BindUnaryOperation,
> BindGetMember, BindGetIndex, BindSetIndex, BindSetMember. These guys are
> mostly covered by applyDynamic as I understand it, but there's a minor
> nuisance. How do you distinguish between a field getter and a nullary method
> invocation from applyDynamic's PoV?
You don't. If you have a selection obj.meth you do not know whether
that's supposed to be a dynamic field selection or a dynamic method
call. So best best you can do is replace it with
obj.applyDynamic("meth")
I don't think we have a problem with setters, either. Pick:
obj.foo = 10
This expands first to
obj.foo_=(10)
and then to
obj.applyDynamic("foo_=")(10)
>
> 3) Casts. By the virtue of ConvertBinder C# virtualizes casts from dynamic
> to whatever. They need it to provide syntactic sugar to COM's
> QueryInterface, not sure whether we need that, but for sure this scenario is
> not supported by the SIP.
>
It is intentionally not supported because it opens up a can of worms.
Just to be clear: In terms of language surface area the C# proposal is
20 to 100 times more complicated than the Scala one.
Cheers
- Martin
I assumed something like that. I actually thought of two parameter
lists, but tuples is way better. I'd just zip the parameter lists
anyway.
>
>> 2) There are six more binders to represent various variations on methods.
>> This category also includes BindBinaryOperation, BindUnaryOperation,
>> BindGetMember, BindGetIndex, BindSetIndex, BindSetMember. These guys are
>> mostly covered by applyDynamic as I understand it, but there's a minor
>> nuisance. How do you distinguish between a field getter and a nullary method
>> invocation from applyDynamic's PoV?
>
> You don't. If you have a selection obj.meth you do not know whether
> that's supposed to be a dynamic field selection or a dynamic method
> call. So best best you can do is replace it with
>
> obj.applyDynamic("meth")
How can a non-macro implementationof applyDynamic distinguish between
these two calls?
object.meth
object.meth()
You have repeatedly emphasized those would be different methods, and
other languages *do* have a distinction between fields and methods,
which Dynamic would have to support somehow.
>
> I don't think we have a problem with setters, either. Pick:
>
> obj.foo = 10
>
> This expands first to
>
> obj.foo_=(10)
>
> and then to
>
> obj.applyDynamic("foo_=")(10)
Yeah, that is trivial, but if getters get special treatment (for the
reason I explained above), then I'd like setters to get such special
treatment too. It would make it more elegant.
Cheers
- Martin
--
Martin Odersky
Prof., EPFL and Chairman, Typesafe
PSED, 1015 Lausanne, Switzerland
Tel. EPFL: +41 21 693 6863
Tel. Typesafe: +41 21 691 4967