December 27, 2011
ProxyOf rewrites the expression

> obj.foo!(bar, baz)(a, b);
to

obj.opDispatch!("foo").opDispatch!(bar, baz)(a, b)
// opDispatch!("foo").opDispatch generates a temporary member template
for forwarding.
// And it is actually processed as 'eponymous template'.

Thanks.

Kenji Hara

2011/12/28 Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org>:
> On 12/27/11 5:27 AM, kenji hara wrote:
>>
>> I've already posted a dmd patch to fix all of opDispatch problems:
>>
>> https://github.com/D-Programming-Language/dmd/pull/280
>
>
> As far a I understand you pass the whole template as a string inside opDispatch? For example, say obj defines opDispatch:
>
> obj.foo!(bar, baz)(a, b);
>
> Would that be rewritten as
>
> obj.opDispatch!("foo!(bar, baz)")(a, b);
>
> ?
>
> That would be great.
>
>
>> With it, I've posted a useful library utility to implement 'super-type' like D1 typedef:
>>
>> https://github.com/D-Programming-Language/phobos/pull/300
>>
>> I'm naming it 'ProxyOf', and it supports various of forwardings, function call, property access, and specialized template member function.
>>
>> Kenji Hara
>
>
> Thanks! Sorry I didn't look over ProxyOf first, it might have saved me some work. I'll do so soon.
>
> Andrei
>
December 27, 2011
Le 27/12/2011 18:03, Peter Alexander a écrit :
> On 27/12/11 4:32 PM, deadalnix wrote:
>> Le 27/12/2011 16:09, Andrei Alexandrescu a écrit :
>>> On 12/27/11 5:27 AM, kenji hara wrote:
>>>> I've already posted a dmd patch to fix all of opDispatch problems:
>>>>
>>>> https://github.com/D-Programming-Language/dmd/pull/280
>>>
>>> As far a I understand you pass the whole template as a string inside
>>> opDispatch? For example, say obj defines opDispatch:
>>>
>>> obj.foo!(bar, baz)(a, b);
>>>
>>> Would that be rewritten as
>>>
>>> obj.opDispatch!("foo!(bar, baz)")(a, b);
>>>
>>> ?
>>>
>>> That would be great.
>>>
>>
>> I think a variadoic template is a better option because of scope issues.
>> You may not know anymore what is bar or baz within opDispatch.
>
> How would that work? opDispatch already has variadic templates for the
> normal function parameters. Make opDispatch a template inside a template?

You are right, that was stupid of me.

I'm afraid that something like the template inside a template is something we should consider. Or passing templates arguements as a Tuple to opDispatch.
December 27, 2011
On 2011-12-27 02:09, Peter Alexander wrote:
> On 26/12/11 5:25 PM, Andrei Alexandrescu wrote:
>> (a) All interaction with the held object is done via opDispatch. In fact
>> opDispatch can be engineered to statically enforce no reference to the
>> held object escapes.
>
> I have a separate, but very much related concern:
>
> If the held object has a method with the same name as RefCounted (e.g.
> asConst) then how do you call the held object's method instead of
> RefCounted's method?

You can always call opDispatch directly.

-- 
/Jacob Carlborg
December 27, 2011
On 2011-12-27 02:30, Peter Alexander wrote:
> On 27/12/11 1:14 AM, Robert Jacques wrote:
>> On Mon, 26 Dec 2011 17:09:02 -0800, Peter Alexander
>>> If the held object has a method with the same name as RefCounted (e.g.
>>> asConst) then how do you call the held object's method instead of
>>> RefCounted's method?
>>
>> You, can't. Looking at the source code asConst is a private member
>> function and therefore, given we are using opDispatch for forwarding,
>> these methods should have _ or __ prepended onto them.
>
> Identifiers starting with __ are reserved, which leaves you with _,
> which could be used by the held object also.

It's not enforced by the compiler.

-- 
/Jacob Carlborg
December 27, 2011
On 2011-12-27 15:48:56 +0000, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> said:

> On 12/27/11 9:27 AM, Michel Fortin wrote:
> 
>> It can't be a library feature because it requires the compiler to
>> implicitly add a "ref" to functions parameters when they are of a "ref
>> struct" type. That's pretty much all it does: add a flag to struct
>> types, implicitly add "ref" to parameters based on that flag.
> 
> Anyhow, I think a feature would need to be tremendously justified and with a huge power/weight ratio.
> This one I actually find ill-designed because now I can't look at the body of a function to figure pass-by-value vs. pass-by-reference I also need to look at the definition (what if it was a ref struct?). One more non-modular thing to keep in mind. This is not going to fly.

I think the appeal is that it solves two common problems cleanly.

It can solve the passing of rvalue by reference so you wouldn't need to add yet another parameter attribute for that (if the type is a ref struct, this is done implicitly). And it solves the problem of passing containers to functions (they'd be implicitly passed by ref).

Basically, it solves the general problem where you have to decide every time you write a function accepting a struct whether it should be by value or by reference. The designer of the type chooses one behaviour and that behaviour is the same everywhere.

It's true that it blurs a little more the line between by-value and by-ref. But note that the line is already quite blurry:

You already don't know by looking at a type name whether a type is an alias or a class. Or even a struct that mimics reference semantics through internal trickery (like RefCounted). And what about dynamic arrays? or ranges? That whole pass-by-value vs. pass-by-reference dichotomy isn't as black and white as we'd like to think. You can never tell just by looking at the name what semantics the type has when "copied".

One thing it does change is it makes function parameters a special case where there was none before. But why do you think "const T &" is used all over the place for parameters but almost none elsewhere in C++? Simply because function parameters *are* a special case. Function parameters need to be passed around efficiently (hence the "&"), and they need to accept rvalues (hence the "const").

Everyone forget to write the "&" and the "const" once in a while in C++, and like you I'd like to avoid this mess in D. I'd say just make the best way the default: make types that should be passed by reference passed by reference by default. Trying to force everyone to use heap-allocated objects, reference counting, or other wrapping schemes is adding also adding much complexity, probably more than what I'm proposing.

For containers, the "ref struct" solution prevents fragmentation by packaging because whatever packaging you use for your container (GC, RefCounted, COW, or no packaging at all) the underlying implementation can always be passed by "ref" to a function. And peeling the packaging part also makes it easier to add const to the container (no mutable reference counter to update).

If you can find a better idea to solve the fragmentation problem and the const problem (and separately the rvalue problem), then go on. I'm just pointing at what seems a good idea to me. You're still free to find better solutions, even though I'm not convinced there are, at least not without forcing a one-size-fit-all packaging to everyone.

- - -

Note that I still am in agreement with your current container prototype design. One important criterion to me is whether I can use the "Impl" part of it directly and pass it around by ref if I want. Seems like I can.

-- 
Michel Fortin
michel.fortin@michelf.com
http://michelf.com/

December 28, 2011
On Tue, 27 Dec 2011 07:10:14 -0800, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:

> On 12/27/11 4:32 AM, Peter Alexander wrote:
>> On 27/12/11 3:05 AM, Andrei Alexandrescu wrote:
>>> On 12/26/11 8:23 PM, Peter Alexander wrote:
>>>> I am
>>>> not convinced that it can be used seamlessly without some relatively
>>>> large changes to the language.
>>>
>>> I repeat that opDispatch and auto ref were invented for this, so
>>> anything that doesn't work now is a bug. There are no changes needed to
>>> the language, only fix the bugs :o).
>>
>> How do you call template member functions of the held object without
>> changing opDispatch?
>
> The idea is to pass the entire template instantiation as the string.
>
> obj.foo!(bar, baz)(a, b);
>
> ->
>
> obj.opDispatch!("foo!(bar, baz)")(a, b);
>
>
>
> Andrei
>
I would have thought that the template parameters would be passed to opDispatch i.e.

obj.opDispatch!("foo",bar,baz)(a,b);

although I don't know how opDispatch would be written to handle such a call in a generic manner, i.e. I would want to define it as

obj.opDispatch!(string name, Targs..,Vargs..)(Vargs args) { ... }

but stuff like that isn't possible currently.

That said, parsing the string for "bar" and "baz" is both difficult and doesn't provide access inside opDispatch to "bar" and "baz".
December 28, 2011
On 12/28/11 12:59 AM, Robert Jacques wrote:
> I would have thought that the template parameters would be passed to
> opDispatch i.e.
>
> obj.opDispatch!("foo",bar,baz)(a,b);
>
> although I don't know how opDispatch would be written to handle such a
> call in a generic manner, i.e. I would want to define it as
>
> obj.opDispatch!(string name, Targs..,Vargs..)(Vargs args) { ... }
>
> but stuff like that isn't possible currently.
>
> That said, parsing the string for "bar" and "baz" is both difficult and
> doesn't provide access inside opDispatch to "bar" and "baz".

I think we all ought to look closely at ProxyOf.

https://github.com/D-Programming-Language/phobos/pull/300


Andrei
December 29, 2011
"Peter Alexander" <peter.alexander.au@gmail.com> wrote in message news:jdct6a$2230$1@digitalmars.com...
> How would that work? opDispatch already has variadic templates for the normal function parameters. Make opDispatch a template inside a template?

I suppose that's what this is for. http://d.puremagic.com/issues/show_bug.cgi?id=2599


March 13, 2012
Is work ongoing on this container prototype? Sounds quite interesting...

1 2 3 4 5 6
Next ›   Last »