Fully dynamic d by opDotExp overloading
Adam Burton
adz21c at googlemail.com
Sat Apr 18 12:43:47 PDT 2009
Jason House wrote:
> Andrei Alexandrescu Wrote:
>
>> Nick Sabalausky wrote:
>> > Please do not accuse me of such a thing simply because I haven't
>> > changed my opinion. You've held your ground as well, so I could just as
>> > easily accuse you of being closed-minded and merely reaffirming a your
>> > preconceived opinion. I have indeed listened to the arguments and
>> > responded to them.
>>
>> Given my track record, I think it should come at no surprise that I'm
>> not a fan of dynamic typing.
>>
>> Andrei
>
> I'm no fan of it either. I will be pissed if one day I'm using a D library
> and a function name typo becomes a runtime error. There is no program too
> short for me to introduce typos and bugs.
>
> Even still, this dynamic stuff does not bother me much because it only
> gets turned on if the class designer wanted it. I assume that it'd be a
> corner of the language I could avoid. The use seems reasonable besides
> sone bicycle shed coloring, so I plan to sit quietly in the corner and
> await an outcome.
>
> My only 2 cents is to use something other than dot for dynamic function
> invocation. Given how much I plan to use it, it's probably better for me
> to abstain.
I agree.
Bare with me on this as I am making some assumptions, I don't follow D2
development very closely ... or D as much as I would like these days :-(.
What about using something like '->' for dynamic calls instead of '.'? When
you see '.' your safe in the knowledge that at a glance you know said method
with said signature exists else the compiler will throw a paddy, when you
see '->' you know that method call is evaluated at runtime. This has the
added benefit that the same class can be used in compile time checking code
and runtime.
It actually means a case of "it's another operator" instead of something
that requires thought as to how it affects the existing use of '.' (which
other replies I have seen people suggesting marking the class as dynamic and
what not which means more keywords?). '->' becomes an operator whos default
behaviour (using a default implementation in Object) just happens to be too
search the type for a matching method signature and call it. Consider below
(I not looked into variadic functions so its not complete D code ... excuse
my ignorance :-)):
interface IServerProxy
{
open();
close();
void opArrow(char[] methodname, v ...) // Maybe put this in interface so
we are forced to overload? otherwise IServerProxy looks like it just opens
and closes which is a lie and doesn't enforce the overload of dynamic method
calls
}
class ServerProxy : IServerProxy
{
public:
this() { .. create some stuff ... }
void opArrow(char[] methodname, v ...)
{
if (_validDispatches.contains(methodname))
_messagedispatcher.dispatch(methodname, v[0]); // Send a call
with a payload
else
super.opArrow(methodname, v);
}
void specialmessage(char[] payload)
{
... do special processing ...
_messagedispatcher.dispatch("specialmessage", payload); // Send a call
with a payload
}
void open() { ... create network connections yada yada .. }
void close() { ... close network connections yada yada .. }
}
void main()
{
ServerProxy svr = new ServerProxy();
StaticAsMuchAsPoss(svr);
DynamicAsMuchAsPoss(svr);
AlsoShowBypassNeedToUpcast(svr);
}
void StaticAsMuchAsPoss(IServerProxy svr) // Plays with the best of both
worlds
{
svr.open(); // Compile time checked valid
svr.message("bob"); // Compile time checked invalid!!
svr->message("bob"); // run-time checked valid
svr->lalala("bob"); // run-time checked invalid!! HOWEVER through the
course of the program it may become valid later on ;-)
svr.close(); // Compile time checked valid
}
void DynamicAsMuchAsPoss(IServerProxy svr)
{
svr->open(); // run-time checked valid
svr->kick("someone"); // run-time checked valid
svr->close(); // run-time checked valid
}
void AlsoShowBypassNeedToUpcast(IServerProxy svr)
{
svr.open(); // Compile time checked valid
svr.specialmessage("bob"); // Compile time checked invalid!!
svr->specialmessage("bob"); // run-time checked valid
svr.close(); // Compile time checked valid
}
As you can see StaticAsMuchAsPoss mostly makes compile time checked calls,
so for the most part your typo's are all checked, apart from when it comes
to dispatching messages then we go runtime (in this case its just a case of
syntax sugar like the use of most operators, we could just use a stand alone
method called dispatch (or add instead of opAdd) and not be dynamic, result
is the same however, just it looks a lil nicer and maybe more appropriate?),
so your mostly safe. DynamicAsMuchAsPoss is completely managed via the
operator, so it's probably slower due to more runtime checks, since even
methods that we could use the '.' for compile time checks have to be
dynamically invoked, but the result is the same. AlsoShowBypassNeedToUpcast
shows through this method you need not upcast to call those pesky derived
methods if you don't want too (although generally I would cast as then its
just the cast that's the potential danger line as my use of the derived
class can be compile-time checked, that's not to say the use of the dynamic
call like that is always bad though, I just wouldn't recommend it :-) ).
Seems to me that using the above method seems like less hassle, '.' stays as
it has always been used and D can have added dynamic abilities ... or even
be used similarly to a dynamic language without breaking old code. The only
real issue I see is return types. Seems to me the operator (or even
opDotExp) needs some sort of built in variant type to handle being able to
returning anything (base types, sturcts, classes, union etc...) (which I
think would also have opArrow to do the same as Object allowing for things
such as bob->callme()->callmesomethingelse() without casting to Object
between each call). What do people think?
More information about the Digitalmars-d
mailing list