April 18, 2009
"Christopher Wright" <dhasenan@gmail.com> wrote in message news:gsaver$2ini$1@digitalmars.com...
> Nick Sabalausky wrote:
>> "davidl" <davidl@nospam.org> wrote in message news:op.usje9ia3j5j59l@my-tomato...
>>> The benefit is you don't need to write the call function,
>>
>> ...But you do have to write the opDotExp() function. How is that less work than just writing a dispatch function?
>
> It's more work, but it lets you do other interesting things.
>
> Prime example is one I mentioned earlier. Let's say we also get full RTTI implemented soon (either in a library [I'm working on it] or in the compiler). Then you can write a Variant type that you can call arbitrary methods on. Neat, huh?
>
> Let's say you integrate D with a scripting language where you can add methods to an object at arbitrary times. Instead of writing: scriptObj.invokeMethod("methodname", arguments);
>
> You can instead write:
> scriptObj.methodname(arguments);
>
> This is a library type which has no business knowing about any methods that you have defined on scriptObj. Moreover, the alternative is to write this:
>
> template ScriptMethod(string name)
> {
> enum ScriptMethod = "void " ~ name ~ "(...) { return
> _vm.invokeMethod(_obj, \"" ~ name ~ \"" ~, _arguments, _argptr); }";
> }
>
> class ScriptObjWrapper
> {
> // repeat this a few dozen times for each method
> mixin (ScriptMethod!("methodname"));
> }
>
> It's syntactic sugar, but it's really neat.

Brainfuck and AppleScript are really neat, but I wouldn't want to write an app in either of them ;)

But anyway, like I've said before, syntactic sugar is fine, but this is syntactic sugar that undermines the programmer's ability to rely on compile-time checking of class members. "But only for the classes that use it." No, it undermines that trust across the board because it's non-obvious what classes are using it, so you'd have to always be on guard. "Operator overloading blah blah blah" That only causes problems when it's used *and* abused by a class, while this would cause problems *any* time it's used. Etc etc...


April 18, 2009
"Andrei Alexandrescu" <SeeWebsiteForEmail@erdani.org> wrote in message news:gsbjci$f6h$1@digitalmars.com...
> Of course I agree. The thing is, if you decide to use a dynamic type, then it will become like a dynamic type.
>

I didn't have a problem with that reasoning when Variant was added, because that was just one type. But now we're talking about opening D up to an entire class (no pun intended) of dynamic types. We've got an ointment factory and are now talking about adding a production line for flies and deliberately minimizing isolation. I use D because it's static, if we bring this level of dynamic-ism into it, then I won't be able to keep the flies out of my static ointment.


"Andrei Alexandrescu" <SeeWebsiteForEmail@erdani.org> wrote in message news:gsbjci$f6h$1@digitalmars.com...
> Steven Schveighoffer wrote:
>>
>> I think Nick's point number 2 is that you would have to write the above as:
>>
>> void twix(T)(T value)
>> {
>>       value.invokeMethod("bar");
>>       value.invokeMethod("bar");
>> }
>>
>> which would work whether bar was dynamically or statically defined.
>
> And will uglify and pessimize all code for the benefit of the few.
>

Funny, that's very similar to my reasoning *against* allowing opDotExp. It undermines static typing expectations for the benefit of the few. It's very similar, but just on a smaller scale, to making declarations optional for the sake of those who don't like to use them.



April 18, 2009
"Daniel Keep" <daniel.keep.lists@gmail.com> wrote in message news:gsbini$dga$1@digitalmars.com...
>
> Steven Schveighoffer wrote:
>> ...
>>
>> I think Nick's point number 2 is that you would have to write the above as:
>>
>> void twix(T)(T value)
>> {
>>       value.invokeMethod("bar");
>>       value.invokeMethod("bar");
>> }
>>
>> which would work whether bar was dynamically or statically defined.
>
> So we have to write ALL templated code that calls member functions or accesses properties/fields like this?
>

No, only ones that absolutely need to work with dynamic classes. Which is neither all nor the majority. Though dynamic invokation can absolutely be useful at times, it is, and absolutely should remain, a fringe case.

> Because otherwise objects may as
> well not be able to do this, since it wouldn't play with any templates
> ever.
>
> You have to be joking.
>

Joking about keeping my static guarantees? When the only other thing at stake is a little bit of syntactic sugar on some occasional dynamic code? Not a chance.


April 18, 2009
"Christopher Wright" <dhasenan@gmail.com> wrote in message news:gsb05g$2ini$3@digitalmars.com...
>
> Assuming that you are testing the logic of your application, you will trivially check things like accessing "legnth" rather than "length" -- under the assumption that these two methods would do different things. You would spend approximately no additional testing effort on opDotExp.
>
> This doesn't hold if you are not writing tests.

I don't think I understand what you're trying to say. With static languages, I have never written, nor would I ever need to write, a test that checks for the behavior when accessing an object's "legnth" instead of "length".


April 18, 2009
Nick Sabalausky wrote:
> "Daniel Keep" <daniel.keep.lists@gmail.com> wrote in message news:gsbini$dga$1@digitalmars.com...
>> Steven Schveighoffer wrote:
>>> ...
>>>
>>> I think Nick's point number 2 is that you would have to write the above as:
>>>
>>> void twix(T)(T value)
>>> {
>>>       value.invokeMethod("bar");
>>>       value.invokeMethod("bar");
>>> }
>>>
>>> which would work whether bar was dynamically or statically defined.
>> So we have to write ALL templated code that calls member functions or
>> accesses properties/fields like this?
>>
> 
> No, only ones that absolutely need to work with dynamic classes. Which is neither all nor the majority. Though dynamic invokation can absolutely be useful at times, it is, and absolutely should remain, a fringe case.

But you're getting it exactly, almost rigorously, backwards. Algorithms specify an interface (e.g. implicit in the case of std.algorithm). The proposed feature allows the few to conform to the many, so the onus is exactly where it should.

>> Because otherwise objects may as
>> well not be able to do this, since it wouldn't play with any templates ever.
>>
>> You have to be joking.
>>
> 
> Joking about keeping my static guarantees? When the only other thing at stake is a little bit of syntactic sugar on some occasional dynamic code? Not a chance.

Some people said quite the same thing about virtual methods. They said it's a really stupid idea because now you can't test code - who knows what the callee is going to do? They could throw, do the wrong thing, etc. They said virtual methods break all guarantees and undermine static typing. They also weren't kidding, and they also were "right". Well, I guess they were kinda missing the point :o).


Andrei
April 18, 2009
Nick Sabalausky wrote:
> But anyway, like I've said before, syntactic sugar is fine, but this is syntactic sugar that undermines the programmer's ability to rely on compile-time checking of class members. "But only for the classes that use it." No, it undermines that trust across the board because it's non-obvious what classes are using it, so you'd have to always be on guard. "Operator overloading blah blah blah" That only causes problems when it's used *and* abused by a class, while this would cause problems *any* time it's used. Etc etc...

Compile time checking is not undermined at all, even for classes that use this functionality.  opDotExp just makes it easier to create classes with a large, possibly infinite set of members.  There are three possible cases:

1. The class does not use opDotExp.  Compile time member checking is not undermined.

2. The body of opDotExp triggers an error at compile time if it receives an unexpected name.  Compile time member checking is not undermined, although the specific error message may have changed.

3. The body of opDotExp accepts all names.  Compile time member checking is not undermined, we just have a class that has every legal identifier as a member.


-- 
Rainer Deyke - rainerd@eldwood.com
April 18, 2009
davidl wrote:
> ÔÚ Sat, 18 Apr 2009 03:45:43 +0800£¬Nick Sabalausky <a@a.a> дµÀ:
> 
>> "Andrei Alexandrescu" <SeeWebsiteForEmail@erdani.org> wrote in message
>> news:gsak2p$1s8a$1@digitalmars.com...
>>>
>>> I think there's merit in binding via strings. It makes for very flexible
>>> code that is future-proof, dynamic-linking-friendly, and hot-swappable
>>> without recompiling (e.g. you don't need to recompile because you now
>>> implement an interface etc.) Reflection is very useful as well.
>>>
>>> I think D can and should allow string lookup for its methods. It's a
>>> low-complexity proposition that adds a very interesting tool to D's
>>> arsenal.
>>>
>>
>> That's a separate issue. I absolutely agree with the usefulness of being
>> able to invoke static methods via a string identifier at runtime. But I
>> think opDotExp is an extremely flawed way to do it. A much better way would
>> be through a reflection mechanism:
>>
> 
> The opDot func can be extremely restrictive by looking up a former added table which are function fingerprints registered by a method call like dynamo.addMethod("myfunc", &myfunc);
> dynamo.Lenght or dynamo.mymethud would just result runtime exception, because you didn't register these functions.

The problem is a lack of notification at compile time. Runtime exceptions are the problem, not the solution.

By the way, if the opDot is a template (per Andrei's suggestion), then if it is marked as nothrow, you have a guarantee that if it compiles, it's valid.
nothrow opDot(char [])(args...) doesn't have any of the problems which Nick et. al have mentioned.
April 18, 2009
Steven Schveighoffer wrote:
> On Fri, 17 Apr 2009 21:54:52 -0400, Steven Schveighoffer <schveiguy@yahoo.com> wrote:
> 
>> Andrei wrote:
>>> We are discussing a language extension. That language extension will allow a type to choose flexibility in defining methods dynamically, while being otherwise integrated syntactically with the current values. This has advantages, but also alters the expectations.
>>
>> As long as it identifies what can be dynamic and what cannot.  I can't imagine Walter will go for this with his strict view of hijacking.
> 
> Let me add that if there was a way for syntax to easily allow for unintentional calls to be translated to compile-time errors, I think this would be a workable solution.

There is. Just mark opDot as nothrow.

> 
> For example, I don't have any problem with your Pascalize example, because you have not removed any static typing from the code (i.e. no unexpected noops or exceptions are built in).  If there were some way to enforce this, then I think it would be a usable idea.  For instance, if you only allow CTFE to specify a function that is called when certain strings are passed in, I don't have a problem with that, because you are simply dispatching the data to strongly typed functions at compile time, which provide compile-time errors when you mess up.
> 
> -Steve
April 18, 2009
 "Leandro Lucarella" <llucax@gmail.com> wrote in message
news:20090417231958.GB27625@homero.springfield.home...
> Nick Sabalausky, el 17 de abril a las 16:48 me escribiste:
>> "Leandro Lucarella" <llucax@gmail.com> wrote in message news:20090417191634.GA15139@homero.springfield.home...
>> > Steven Schveighoffer, el 17 de abril a las 11:27 me escribiste:
>> >>
>> >> Sure, but what is the reason to need dynamic methods?  I'm just trying
>> >> to
>> >> understand the usefulness of it.
>> >
>> > RPC is an example that comes into mind
>> >
>> > There is plenty of magic you can do with dynamic methods. Just try a dynamic language and see =)
>>
>> But is there any that can't be done with a dispatch function?
>
> You can write anything even with brainfuck. There are no discussion about what's possible and what's not, we are just talking about syntax. I hope the "it can be done" argument stop poping out because we all agree that it's possible to do everything right now. The question is *how* you can do it.
>

Please, please, please, let's not delve into the "everything can be done" argument. It only holds for a limited domain (theoretical turing machines and turing computable problems, ie theoretical computability), which this discussion is already well outside of. You can't rewrite Firefox in brainfuck in 3 hours. You can't write a worthwhile embedded OS entirely in JavaScript. You can't write a gameboy app to compute the movements of all the particles in the universe until the end of time and have it run to completion in three seconds. You can't. You can't. You can't. Can't can't can't can't can't. Of course there are things that can't be done.

Obviously we're all well aware that computability has nothing to do with this discussion, so I really don't see why you've brought it up. As you said, the question is how we compute whatever we're computing and how we write the code to do so. And there absolutely are indeed certain how's under certain conditions that *cannot* be done.

And you did say "There is plenty of magic you can do with dynamic methods", right? You don't want me to misuse the "it's possible to do everything" argument to respond "If there's plenty of magic you can do with dynamic methods, and everything is possible, then I can do all the same magic without anything dynamic", do you? So please, please, please, let's never, ever, ever, ever, ever get into the "everything can be done" again unless we really are entirely within the bounds of theoretical computability.

So now, let's try this again:
What is this usefulness you speak of that traditional dynamic methods and/or
opDotSrc dynamic methods have that is more useful than a dispatch method?
Or, were you already counting dispatch methods as a form of dynamic method?

>> Besides, as I see it, the opDotExp-style syntax for calling a dynamic
>> method
>> is more limited because unless you're using a scripting language, you
>> can't
>> do:
>>
>> auto foo = new Foo();
>> char[] func = /* Get from user input */;
>> foo.func(); // Call function the user specified
>
> So?
>

I was merely refuting your impliction (or maybe I misunderstood you?) that opDotExp dynamic methods were more useful.

>> But you can do that with either a dispatch method or a reflection API
>> that
>> supports invokation.
>
> I think the reflection API is needed too, but that's another topic. Both would be great.
>

Ok, glad we at least agree on the need for the reflection stuff :)


April 18, 2009
"Don" <nospam@nospam.com> wrote in message news:gsbovk$nbj$1@digitalmars.com...
> davidl wrote:
>> ÔÚ Sat, 18 Apr 2009 03:45:43 +0800£¬Nick Sabalausky <a@a.a> дµÀ:
>>
>>> "Andrei Alexandrescu" <SeeWebsiteForEmail@erdani.org> wrote in message news:gsak2p$1s8a$1@digitalmars.com...
>>>>
>>>> I think there's merit in binding via strings. It makes for very
>>>> flexible
>>>> code that is future-proof, dynamic-linking-friendly, and hot-swappable
>>>> without recompiling (e.g. you don't need to recompile because you now
>>>> implement an interface etc.) Reflection is very useful as well.
>>>>
>>>> I think D can and should allow string lookup for its methods. It's a low-complexity proposition that adds a very interesting tool to D's arsenal.
>>>>
>>>
>>> That's a separate issue. I absolutely agree with the usefulness of being
>>> able to invoke static methods via a string identifier at runtime. But I
>>> think opDotExp is an extremely flawed way to do it. A much better way
>>> would
>>> be through a reflection mechanism:
>>>
>>
>> The opDot func can be extremely restrictive by looking up a former added
>> table which are function fingerprints registered by a method call like
>> dynamo.addMethod("myfunc", &myfunc);
>> dynamo.Lenght or dynamo.mymethud would just result runtime exception,
>> because you didn't register these functions.
>
> The problem is a lack of notification at compile time. Runtime exceptions are the problem, not the solution.
>
> By the way, if the opDot is a template (per Andrei's suggestion), then if
> it is marked as nothrow, you have a guarantee that if it compiles, it's
> valid.
> nothrow opDot(char [])(args...) doesn't have any of the problems which
> Nick et. al have mentioned.

Ok, now *that* is something I can be happy with.


3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19