April 18, 2009
Daniel Keep wrote:
>> Cool! I suggest the rewrite:
>>
>> c.unknownmethod(args) -> c.opDotExp!("unknownmethod")(args)
>>
>> That way you have the option of handling the method name statically or
>> dynamically.
> 
> Careful.  If you do that, you need to make sure it's possible to invoke
> a given method at runtime.  Assuming getMembers is implemented (I make
> daily sacrifices in hopes of that), each distinct opDotExpr!(s) needs to
> get an entry.
> 
> Otherwise, you've ironically created something that's HARDER to
> programatically invoke.  :P

Yeah, that's one annoying thing about the proposal. There are a couple of solutions:
 - Let types with opDotExp manipulate their type information dynamically. This would be a *lot* of work, and it wouldn't necessarily work for everything (let's say one instance of the class has some methods available and another one has different ones available).
 - Allow template instantiations to be included in type information. This will require patching type info again, for instance when you compile files separately and instantiate the templates in different modules.
April 18, 2009
Nick Sabalausky, el 18 de abril a las 02:19 me escribiste:
>  "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.

Nice speech.

> 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?

Uniform (and better) syntax. It's just about that.

-- 
Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/
----------------------------------------------------------------------------
GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145  104C 949E BFB6 5F5A 8D05)
----------------------------------------------------------------------------
JUNTAN FIRMAS Y HUELLAS POR EL CACHORRO CONDENADO A MUERTE...
	-- Crónica TV
April 18, 2009
Leandro Lucarella Wrote:

> > 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?
> 
> Uniform (and better) syntax. It's just about that.

I too am having difficulty in understanding the benefit of this particular proposal. If I understand it right, the string essentially is still static and hence known at compile time? In which case I fail to see the advantage of using this opDotSrc method instead of defining a function.

Anyways, I have wanted similar functionality for a different purpose. In graphics is common to do swizzle on vector. A float4 vector has xyzw components and some specialized languages like shaders allow you to do shuffle and replicate the components.

float4 vec = float4(1.0f,2.0f,3.0f,4.0f);
vec = vec.wzyx;
//vec is now (4.0f, 3.0f, 2.0f, 1.0f);
vec = vec.xxyy;
//vec is now (4.0f, 4.0f, 3.0f, 3.0f);

There is no good syntax to implement the swizzles in C++. You can make all of them member functions but the number of possibilities is so huge that is ridiculous to do it by hand.

With something like this proposal, it should be easy to implement.

Also, *if* there was a default opDotExp dispatcher (which automatically dispatches to the regular member functions) wouldn't it be easier to build interceptor classes? Or to implement class specific tracing? All calls to an object go through an interceptor object which can print debug trace information for example. For the default generated opDotExp the compiler can still do static type checking since it knows opDotExp will forward calls to the defined memeber functions.
April 18, 2009
SandeepK:
> I too am having difficulty in understanding the benefit of this particular proposal.

Read the thread, some of the answers give several use cases.


>If I understand it right, the string essentially is still static and hence known at compile time?<

It can be unknown at compile-time.


> Anyways, I have wanted similar functionality for a different purpose. In graphics is common to do swizzle on vector. A float4 vector has xyzw components and some specialized languages like shaders allow you to do shuffle and replicate the components.
> float4 vec = float4(1.0f,2.0f,3.0f,4.0f);
> vec = vec.wzyx;

Note that using dynamic access may be a bit slow for that.

On the other hand you can do that in D1 creating a small compile-time function that computes the cartesian product to create the strings of the names of those function methods (to be used as attributes), that you can add with a mixin (and a static foreach, if necessary).
I have shown such code here time ago, don't ask me to write it again :-) This is a starting point:

const string chars = "xyzw";
foreach (x; Range!(4))
  foreach (y; Range!(4))
    foreach (y; Range!(4))
      foreach (w; Range!(4))
        chars[x] ~ chars[y] ~ chars[w] ~ chars[w];

Bye,
bearophile
April 18, 2009
downs wrote:
> Static loops are simple, at least in functions.
> 
> import std.stdio;
> 
> template Tuple(T...) { alias T Tuple; }
> template Repeat(T, int I) { static if (!I) alias Tuple!() Repeat; else alias Tuple!(T, Repeat!(T, I-1)) Repeat; }
> 
> void main() {
>   foreach (i, bogus; Repeat!(void, 15))
>     writefln(i);
> }

I know, but at about the fiftienth one you get sick of it. And generating code in a static loop is much harder.

Andrei
April 18, 2009
Michel Fortin wrote:
> On 2009-04-18 03:23:21 -0400, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> said:
> 
>> If you want to invoke a method known as a string variable, opDot or whatever has nothing to do with it. You don't need any change to the language at all, because you'd write:
>>
>> string foo = "bar";
>> d.call(foo); // call method bar
>>
>> What opDot does is to allow the regular member syntax while still allowing the callee to look up the name statically or dynamically (assuming the method name is passed into opDot as a template parameter).   Note, again, that opDot has everything to do with the syntax and next to nothing to do with the semantics, which is realizable without any change in the language. And that's how the cookie crumbles. I understand you don't like that, but at least we should be clear on where the feature starts and where it ends.
> 
> Andrei, I think you, and perhaps everyone here, are overlooking one small but important detail.
> 
> opDotExp, if a template like you're adovcating, undermines future runtime dynamic call capabilities (which are part of most runtime reflection systems).
> 
> If you're going to have something such as
> 
>     d.invoke("foo");
> 
> available on any type (using some yet-to-see runtime reflection), it will work for a non-template opDotExp (invoke would just forward to opDotExp with the string "foo" if it doesn't find the member through reflection), but it cannot work for an opDotExp template using "foo" as a template argument since string "foo" is a runtime argument. (In fact, I don't see how any template can be callable from runtime reflection.)
> 
> It ensues that if later we add runtime reflection to D, dynamic calls won't work for template opDotExp.
> 
> So I'm not really convinced that template is the way to go, even though it would allow great things. Almost all you can do with a template, you already can do by adding members using a mixin. And adding members using a mixin will also work with runtime reflection, unlike templated opDotExp. The only use case left unadressed by mixins and runtime opDotExp is the function with an infinite number of members which want compile time dispatching.
> 
> Perhaps we need both template and runtime opDotExp...
> 
> Anyway, I like the general concept so I hope we'll get it, template or not. I just feel the point above has been neglected in the discussion.

I'm confused. Isn't it clear that at the moment we "have" the ability to pass a function name as a runtime string? What we're lacking is the ability to implement that using reflection, but that's an entirely separated discussion!

And no, you're not supposed to forward from invoke(string, Variant[]...) to opDotExp - it's precisely the other way around! I'm not sure where I'm wrong in explaining this, it looks like I'm unable to remove a very persisting confusion.

So let me restate: opDotExp taking a runtime string does not EXPAND your options, it severely LIMITS them. It's very simple: with the former you have strictly LESS options and no NOTHING in terms of added power. It's simple, I swear.


Andrei
April 18, 2009
Andrei Alexandrescu:
> I know, but at about the fiftienth one you get sick of it.

In some situations static loops can be useful, but in general isn't the compiler supposed to be able to perform loop unrolling by itself, according to compilation arguments and according to how much code is present into the loop? (if it's too much code then loop unrolling is to be avoided).

Bye,
bearophile
April 18, 2009
bearophile wrote:
> SandeepK:
>> I too am having difficulty in understanding the benefit of this particular proposal.
> 
> Read the thread, some of the answers give several use cases.
> 
> 
>> If I understand it right, the string essentially is still static and hence known at compile time?<
> 
> It can be unknown at compile-time.

How on earth could that happen? It's always known at compile time.

> 
> 
>> Anyways, I have wanted similar functionality for a different purpose. In graphics is common to do swizzle on vector. A float4 vector has xyzw components and some specialized languages like shaders allow you to do shuffle and replicate the components.
>> float4 vec = float4(1.0f,2.0f,3.0f,4.0f);
>> vec = vec.wzyx; 
> 
> Note that using dynamic access may be a bit slow for that.

I don't see _anything_ dynamic in this proposal, actually.

> 
> On the other hand you can do that in D1 creating a small compile-time function that computes the cartesian product to create the strings of the names of those function methods (to be used as attributes), that you can add with a mixin (and a static foreach, if necessary).
> I have shown such code here time ago, don't ask me to write it again :-) This is a starting point:

Yes, but the syntax isn't quite as nice as with this proposal.
April 18, 2009
Hello bearophile,

> Andrei Alexandrescu:
> 
>> I know, but at about the fiftienth one you get sick of it.
>> 
> In some situations static loops can be useful, but in general isn't
> the compiler supposed to be able to perform loop unrolling by itself,
> according to compilation arguments and according to how much code is
> present into the loop? (if it's too much code then loop unrolling is
> to be avoided).
> 
> Bye,
> bearophile

It's not just loop unrolling as some loops can't be "rolled" in the first place, like when one of the loop variables is a type or you need to static if on the index.


April 18, 2009
Hello Andrei,

> The dynamic behavior is indicated by the use of opDotExp. The
> redundancy of the two notations doesn't quite sit well.
> 
> Andrei
> 

not exactly 1-to-1 but:

abstract class C { void foo(); } // works

class D { void foo(); } // fails: link error