On Wed, 16 Nov 2011 17:39:16 -0500, Timon Gehr <timon.g...@gmx.ch> wrote:

On 11/16/2011 10:56 PM, Steven Schveighoffer wrote:
On Wed, 16 Nov 2011 16:16:48 -0500, Timon Gehr <timon.g...@gmx.ch> wrote:

On 11/16/2011 09:00 PM, Steven Schveighoffer wrote:
On Wed, 16 Nov 2011 14:26:57 -0500, Timon Gehr <timon.g...@gmx.ch>
wrote:

On 11/16/2011 02:22 PM, Steven Schveighoffer wrote:
On Tue, 15 Nov 2011 13:45:02 -0500, Timon Gehr <timon.g...@gmx.ch>
wrote:

Note that this is an explicit allocation:

int[] a = [1,2,3]; // just as explicit as a NewExpression

Only the enums "hide" it sometimes, but actually you should know the
involved types.

As I've said, there are already ways to explicitly allocate memory. A
suggested replacement for this is:

int[] a = array(1, 2, 3);

And you could always do:

int[] a = [1, 2, 3].dup;

Nobody complains about having to do:

char[] a = "hello".dup;

I don't see why we couldn't do the same for all array literals.


Because 'immutable' behaves nicely on built-in value types, but not on
arbitrary reference types.

string is a reference type. We hear no complaints about strings being
stored in ROM and the type of literals being immutable.


string is not an immutable type. It is immutable(char)[] and char is a
built-in value type.

static assert(isMutable!string);

It fits my definition of a valid enum reference type (immutable or
implicitly castable to immutable). The point is that the data referenced
is stored in ROM and therefore a) immutable and b) fully defined at
compile-time.

Indeed. But fact is, the data that is qualified with immutable is not of reference type therefore it behaves nicely. And you don't get that in the general case.

In the general case, there is always a library function for construction. In other words, what the compiler currently does for array literals can be done in a library. But a library cannot create ROM space. The compiler-based features (and CTFE in general) should be helping us create things at compile time, not at run time. We already have the tools to construct arrays at runtime.


I am looking for something like this:

template writeln(T...)(T){
     alias writelnImpl!(writelnInferConst!T) writeln;
}

(it is even trivial to parse, unlike normal function definitions!)

What does writelnInferConst!T do? I'm afraid I'm not getting what you are saying.

I was thinking writeln should do this:

void writeln(T...)(const T args) {...}

I have an enhancement request in for intercepting IFTI (not sure if it
applies here): http://d.puremagic.com/issues/show_bug.cgi?id=4998


It has a complexity of at least 2^numparams and probably all kinds of odd implications for the compiler internals that would lead to a buggy implementation.

I'm not a compiler writer, but I don't see how this is the case.


I think this is a better solution:

void foo2(T: ParameterTypeTuple!foo[0])(T t){foo(t);}

Then it is just a matter of applying proper value range propagation for IFTY:

void bar(T: short)(T t){...}

void main(){
     bar(1); // ok
}

The issue with all this is, IFTI doesn't work that way:

void foo(T: short)(T t) {}

void main()
{
   foo(1);
}

testifti.d(5): Error: template testifti.foo(T : short) does not match any function template declaration testifti.d(5): Error: template testifti.foo(T : short) cannot deduce template function from argument types !()(int)

IFTI decides the types of literals before trying to find a proper template to instantiate. Any possibility to intercept the decision of literal type or of instantiation would be useful. I think that it's better suited to the constraints, because there is more power there. But I'm not sure. If you can find a more straightforward way, I'm all for it.

In any case, I need to update the bug report, because the general case is if foo has an overload. For instance:

foo(short s);
foo(wstring w);

foo2 should be able to call both with 1 and "hello" without issue.

My driving use case to create the enhancement was creating a wrapper type that intercepted function calls. I planned to use opDispatch, but it didn't quite work with literals.

I think the bloat is a wash. Every time I use an array literal, there is
a complete instantiation of what would be in an array template inline in
the calling function.

With the template function you have that too because the calling function builds the arguments. It is just that you also get the template bloat and an additional function call. Unless it is inlined, of course.

You are right, I hadn't thought of that. But what about this: most array literals are actually literals (made up of CTFE-decided values). Making them ROM-stored would *eliminate* bloat as compared to the current implementation.

Also, given how template-centric D and phobos are, I think at some point we need to examine how to minimize template bloat in general, by coalescing identical code into one function, or not emitting functions that are always inlined, not to mention avoiding storing templates only used at compile-time in the code (e.g. isInputRange).

Yes, it breaks code. It's worth it. To avoid a heap allocation for [1,
2, 3] is worth breaking code that uses runtime data in an array literal.
The compiler can be helpful in the error message:

Error somefile.d(345): array literals cannot contain runtime data. Maybe
you meant:
array(new Foo, new Bar, new Qux);

I want to point out that currently there is *NO* way to make an
immutable array literal that lives in ROM. This is unacceptable.


There is:

void main(){
     static immutable x = [1,2,3];
}

Seems rather odd you should have to jump through these hoops to get the compiler to use ROM space. But I concede that I did not know of this trick. It does not sway my opinion that CTFE should produce ROM-stored references, and library function should be used for runtime-constructed references.

-Steve

Reply via email to