May 18, 2009
Christian Kamm wrote:
> Andrei Alexandrescu wrote:
> 
>> Ok, now with the advent (or rediscovery) of allMembers which I had no
>> idea existed, we're ready to start some serious butt-kick reflection
>> facilities.
>>
>> For starters, I'd like to present you with the following challenge.
> 
> Unless there's been a change in D2 I have missed, I don't think you can forward functions with ref/out or default arguments correctly unless you parse certain mangles or stringofs.
> 
> 

Time for a bug report.

Andrei
May 18, 2009
>> Unless there's been a change in D2 I have missed, I don't think you can forward functions with ref/out or default arguments correctly unless you parse certain mangles or stringofs.
>> 
>> 
> 
> Time for a bug report.
> 
> Andrei

See
http://d.puremagic.com/issues/show_bug.cgi?id=1818
or the related
http://d.puremagic.com/issues/show_bug.cgi?id=1411
http://d.puremagic.com/issues/show_bug.cgi?id=1424

Treating default arguments or storage classes with the current scheme is difficult though - they are not part of the type. While the concept of an 'function argument description' including type, storage class, default argument and identifier (!) exists in the frontend, it is not exposed to the user - except through tuples in a fairly accidental and inconsistent manner.


May 18, 2009
Christian Kamm wrote:
>>> Unless there's been a change in D2 I have missed, I don't think you can
>>> forward functions with ref/out or default arguments correctly unless you
>>> parse certain mangles or stringofs.
>>>
>>>
>> Time for a bug report.
>>
>> Andrei
> 
> See
> http://d.puremagic.com/issues/show_bug.cgi?id=1818
> or the related
> http://d.puremagic.com/issues/show_bug.cgi?id=1411
> http://d.puremagic.com/issues/show_bug.cgi?id=1424
> 
> Treating default arguments or storage classes with the current scheme is difficult though - they are not part of the type. While the concept of an 'function argument description' including type, storage class, default argument and identifier (!) exists in the frontend, it is not exposed to the user - except through tuples in a fairly accidental and inconsistent manner.

Yes. All we need is a module std.reflection that does all that gruntwork and exposes a simple and nice interface for people who want to use reflection.

Andrei
May 18, 2009
On Mon, May 18, 2009 at 1:23 PM, Jarrett Billingsley <jarrett.billingsley@gmail.com> wrote:

> The first is a more general statement about trying to generate functions with D's metaprogramming.  It is a huge pain in the ass to actually create a function with a given name, because the only way that I know this can be done is with a string mixin.  As soon as we venture into that territory, we have to consider things like how to convert a parameter type tuple into a string, and whether or not the .stringof a type will be correctly qualified (I've run into problems with this before, where some code in a library is not able to mix in a string because it doesn't import the same modules that the calling code does, and then you just get undefined identifier errors).  For the love of all that is holy, can we PLEASE get something like __ident("blah")?  This would be so much easier and would probably drastically reduce my use of string mixins in general.

What about this front?  Is it out of the realm of possibility to get an identifier-izer?
May 18, 2009
Jarrett Billingsley wrote:
> On Mon, May 18, 2009 at 1:23 PM, Jarrett Billingsley
> <jarrett.billingsley@gmail.com> wrote:
> 
>> The first is a more general statement about trying to generate
>> functions with D's metaprogramming.  It is a huge pain in the ass to
>> actually create a function with a given name, because the only way
>> that I know this can be done is with a string mixin.  As soon as we
>> venture into that territory, we have to consider things like how to
>> convert a parameter type tuple into a string, and whether or not the
>> .stringof a type will be correctly qualified (I've run into problems
>> with this before, where some code in a library is not able to mix in a
>> string because it doesn't import the same modules that the calling
>> code does, and then you just get undefined identifier errors).  For
>> the love of all that is holy, can we PLEASE get something like
>> __ident("blah")?  This would be so much easier and would probably
>> drastically reduce my use of string mixins in general.
> 
> What about this front?  Is it out of the realm of possibility to get
> an identifier-izer?

I want this too, but first let's become able to do things we can't do and then to do things we can do, easier. The __ident thing has been on the table for literally years, I seem to recall I called it new alias("blah").

Andrei
May 18, 2009
On Mon, 18 May 2009 12:12:40 -0400, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:

> Ok, now with the advent (or rediscovery) of allMembers which I had no idea existed, we're ready to start some serious butt-kick reflection facilities.
>
> For starters, I'd like to present you with the following challenge. Given any class C, e.g.:
>
> class C
> {
>      void foo(int) { ... }
>      int bar(string) { ... }
> }
>
> define a template class Finalize(T) such that Finalize!(C) is the same as the following hand-written class:
>
> final class FinalizeC : C
> {
>      final void foo(int a) { return super.foo(a); }
>      final int bar(string a) { return super.bar(a); }
> }
>
> Finalize is cool when you need some functionality from an exact class and you don't want to pay indirect calls throughout. All calls through Finalize!(C)'s methods will resolve to static calls.
>
>
> Have at it!

1 minor issue, if super.foo(a) calls bar, then it's still a virtual call...

Not that it's not a good idea, but you might get a lot less mileage out of it than you think.

I think you'd need compiler help to get rid of that problem.  It'd be like a flattening of a class to recompile all base class virtual calls with the notion that any internal calls it makes are final.  If you casted to a base class, the initial call would be virtual, but the internal calls would be nonvirtual.  This would be impossible unless you had the source to all the base classes, it might just be better to do it as a separate code-generator tool.

Back to your idea...

This feature that you suggest seems very trivial for the compiler to implement, while extremely hard to do it via reflection.  I've longed for this for a while:

interface I
{
  int foo();
}

class A
{
  int foo() {return 0;}
}

class B: A, I
{
  alias A.foo foo;
}

which makes B implement the interface by simply copying the vtable entry from A's.  This even saves on the double call (having a derived class function that simply calls the base class function).  You could then allow:

class B: A, I
{
  final alias A.foo foo;
}

and the compiler knows it doesn't need a virtual lookup.  Then the template to do it to all virtual methods would be trivial.

-Steve
May 18, 2009
On Mon, May 18, 2009 at 2:20 PM, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:
>
> I want this too, but first let's become able to do things we can't do and then to do things we can do, easier. The __ident thing has been on the table for literally years, I seem to recall I called it new alias("blah").

I'm more worried that this will just slip through the cracks and not make it into D2.  Then it'd be implemented in some post-D2 version of DMD, and then D3 will be forked, so it'll _kind of_ be part of D2 but not _really_ since it wasn't part of the spec when it was 'frozen'.. we've been here before :P

It seems like such low-hanging fruit.  So many of my string mixins only exist to parameterize the names of things that this would almost completely replace them.  It's on the same level as static foreach - not essential, but it'd certainly make a lot of metaprogramming simpler.
May 18, 2009
Jarrett Billingsley wrote:
> On Mon, May 18, 2009 at 2:20 PM, Andrei Alexandrescu
> <SeeWebsiteForEmail@erdani.org> wrote:
>> I want this too, but first let's become able to do things we can't do and
>> then to do things we can do, easier. The __ident thing has been on the table
>> for literally years, I seem to recall I called it new alias("blah").
> 
> I'm more worried that this will just slip through the cracks and not
> make it into D2.  Then it'd be implemented in some post-D2 version of
> DMD, and then D3 will be forked, so it'll _kind of_ be part of D2 but
> not _really_ since it wasn't part of the spec when it was 'frozen'..
> we've been here before :P
> 
> It seems like such low-hanging fruit.  So many of my string mixins
> only exist to parameterize the names of things that this would almost
> completely replace them.  It's on the same level as static foreach -
> not essential, but it'd certainly make a lot of metaprogramming
> simpler.

I think you need to operate exclusively with string mixins in Finalize, so __ident would be of marginal help there. Also, static foreach is much more necessary.

Andrei
May 18, 2009
Steven Schveighoffer wrote:
> Back to your idea...
> 
> This feature that you suggest seems very trivial for the compiler to implement, while extremely hard to do it via reflection.

The problem is, there are a million things that are trivial for the compiler to implement and harder with libraries. But that approach just doesn't scale. Finalize is only the beginning and pretty much a working example to flesh out library primitives. Don't get bogged down by it.

Andrei
May 18, 2009
On Mon, May 18, 2009 at 2:34 PM, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:

> I think you need to operate exclusively with string mixins in Finalize, so __ident would be of marginal help there. Also, static foreach is much more necessary.

I have used string mixins extensively in my own code, not just in this one example.  Most of the time it's to replace a name.  With something like __ident, I wouldn't have to use them nearly as much, and in fact I probably wouldn't need them here.  Think about it:

template CreateOverload(alias func, char[] name)
{
	ReturnType!(func) __ident(name)(ParameterTypeTuple!(func) args)
	{
		return super.__ident(name)(args);
	}
}

Then later, I could just use a template mixin.

You say static foreach is much more necessary than this.  Why?  It's just a convenience, so you don't have to use template recursion.  Is it more important because you want to use it?