View mode: basic / threaded / horizontal-split · Log in · Help
January 27, 2007
Re: Real World usage of D, Today (was Re: challenge #2: implement the varargs_reduce metafunction)
Andrei Alexandrescu (See Website For Email) wrote:
> Kevin Bealer wrote:
>> Andrei Alexandrescu (See Website For Email) wrote:
> [about deducing storage types]
>>> The syntax that I am proposing does away with storageof and is very 
>>> much in spirit with the current D:
>>>
>>> S int foo(S, T)(S T t) { }
>>>
>>> It does exactly what it says it does, in a clear and terse manner, 
>>> and is 100% within the spirit of existing D:
>>>
>>> * It's customized on symbols S and T
>>>
>>> * It's matching (by sheer position of S and T) the storage (i.e., all 
>>> of the gooey fuzzy nice information about the argument passed) and 
>>> the type of the incoming argument
>>>
>>> * In this example it uses the storage in the result type (e.g. const 
>>> goes to const)
>>>
>>> * Inside the function can easily use either T separately or S T as a 
>>> group that transports the storage around. You have total flexibility 
>>> (and don't forget that juxtaposition is always easier than extraction).
>>>
>>> So far we're only thinking of storage-like attributes, but a good 
>>> deal of information can be encoded under the loose declaration of 
>>> "storage".
>>>
>>>
>>> Andrei
>>
>> I like this; does this mean that when declaring an instance, you would 
>> do something like this?  Or do the 'const' parts get deduced?
>>
>> alias Foo!(const, int) TheFoo;
> 
> The intent is to deduce the storage, but specifying it explicitly works 
> just as well.
> 
> There is strong resistance against my notation because manipulating the 
> storage class separately is something entirely new, which means a lot of 
> work in the compiler implementation. Also, S is not a type but a (new 
> kind of) alias, which might confuse people who read:
> 
> template Foo(S, T)
> {
>   ...
> }
> 
> and expect S and T to be types, just to discover in the body of the 
> template that S is actually a qualifier.
> 
> The strawman we're discussing now looks like this:
> 
> void foo(auto T)(T t) { }
> 
> meaning, T will match whatever you throw at foo, including storage:
> 
> int a = 5;
> foo(a);     // T == inout int
> foo(a + 1); // T == int

So how would one declare such a type?  typeof(T) perhaps?  I imagine 
there must be some way to separate the storage class from the type for 
this to work.


Sean
January 27, 2007
Re: Issues with constants, and inout (was Real World usage of D, Today)
Frits van Bommel wrote:
> kris wrote:
> 
>> Andrei Alexandrescu (See Website For Email) wrote:
>>
>>> kris wrote:
>>> [about implicit conversion rules]
>>>
>>>> extern (C) int printf (char*, ...);
>>>>
>>>> class Foo
>>>> {
>>>>         void write (int x) {printf("int\n");}
>>>>         void write (uint x) {printf("uint\n");}
>>>>         void write (long x) {printf("long\n");}
>>>>         void write (char x) {printf("char\n");}
>>>>         void write (wchar x) {printf("wchar\n");}
>>>>         void write (double x) {printf("double\n");}
>>>>
>>>>         void write (char[] x) {printf("char[]\n");}
>>>>         void write (wchar[] x) {printf("wchar[]\n");}
>>>> }
>>>>
>>>> void main()
>>>> {
>>>>         auto foo = new Foo;
>>>>
>>>>         foo.write ('c');
>>>>         foo.write (1);
>>>>         foo.write (1u);
>>>>         foo.write (3.14);
>>>>         //foo.write ("asa");
>>>> }
>>>>
>>>> prints:
>>>>
>>>> char
>>>> int
>>>> uint
>>>> double
> 
> [snip]
> 
>>>> Now for the broken part. When you uncomment the string constant, the 
>>>> compiler gets all confused about whether it's a char[] or wchar[]. 
>>>> There is no defaulting to one type, as there is for other constants 
>>>> (such as char). It /is/ possible to decorate the string constant in 
>>>> a similar manner to decorating integer constants:
>>>>
>>>> foo.write ("qwe"c);
>>>>
>>>> And this, of course, compiles. It's a PITA though, and differs from 
>>>> the rules for other constants.
>>>
>>>
>>> I talked to Walter about this and it's not a bug, it's a feature :o). 
>>> Basically it's hard to decide what to do with an unadorned string 
>>> when both wchar[] and char[] would want to "attract" it. I understand 
>>> you're leaning towards defaulting to char[]? Then probably others 
>>> will be unhappy.
>>
>>
>> You'll have noticed that the constant 'c' defaults to /char/, and that 
>> there's no compile-time conflict between the write(char) & 
>> write(wchar)?  Are people unhappy about that too? Perhaps defaulting 
>> of char constants and int constants should be abolished also?
> 
> 
> It's a bit more complicated with character literals than just defaulting 
> to 'char':
> -----
> import std.stdio;
> void main() {
>     writefln(typeid(typeof('a')));          // c <= \u007f
>     writefln(typeid(typeof('\uabcd')));     // c <= \uffff
>     writefln(typeid(typeof('\U000abcde'))); // c <= \U0010ffff
> 
> }
> -----
> outputs:
> """
> char
> wchar
> dchar
> """
> So it defaults to the *smallest* character type that can hold it in one 
> element.
> Pretty cool, actually.
> 
> This also applies to other types, by the way. If you type an integer 
> literal that won't fit into an 'int', it'll be a 'long' constant 
> (assuming it fits), not an 'int' constant.

Yes. Kinda glossed over that part, didn't I <g>


> Perhaps we should do something similar with string literals, defaulting 
> it to use an array of the smallest character type that can hold all of 
> the characters in the string (i.e. the maximum "character type" of the 
> component characters) ?
> That seems like a reasonable rule. And it has the added benefit that 
> "some string constant".length will always be the number of characters in 
> the string.


Yes, that would seem eminently reasonable.
January 27, 2007
Re: Real World usage of D, Today (was Re: challenge #2: implement the varargs_reduce metafunction)
Frits van Bommel wrote:
> Bill Baxter wrote:
>> Andrei Alexandrescu (See Website For Email) wrote:
>>> You will be able to cherry-pick with "is" tests. Walter is opposed to 
>>> manipulating the raw storage attributes.
>>
>> If you have to cherry pick with "is" tests to separate the bits out of 
>> the S above, then why not just use "is" tests to pick the S info off 
>> the type to begin with?
> 
> Because just 'S' is much shorter when you don't want to cherry-pick?

Just wondering if there are that many cases where all want to do is pick 
off S without 'deconstructing' it further.  Especially given Andrei's 
statement "there are lots of things that could go under the vague 
heading of storage class", it seems like it may be rare that you can 
actually just use S as-is without picking out the particular attributes 
you care about -- const or inout or any one of the 'lots of other things'.

And if that's the case then maybe the benefits of having the "template 
foo(S T)(S T x)" syntax are not so huge.  You could get S using
    alias storageof(T) S
in the first line of the template instead.  Or lets say you just want to 
use the constness part of S, which seems like a fairly common thing to 
want.  Then you'll still need something like:
     constof(S) template foo(S T)(S T v) { ... }
But if you have to say constof(S) you might as well just make constof 
operate on T directly instead.
     constof(T) template foo(T)(T v) { ... }

I'm willing to be convinced, but so far it's not clear to me that 
"template xx(S T)" would be all that useful in practice.

--bb
January 27, 2007
Re: Issues with constants, and inout (was Real World usage of D, Today)
Frits van Bommel wrote:

> So it defaults to the *smallest* character type that can hold it in one 
> element.
> Pretty cool, actually.
> 
> This also applies to other types, by the way. If you type an integer 
> literal that won't fit into an 'int', it'll be a 'long' constant 
> (assuming it fits), not an 'int' constant.
> 
> Perhaps we should do something similar with string literals, defaulting 
> it to use an array of the smallest character type that can hold all of 
> the characters in the string (i.e. the maximum "character type" of the 
> component characters) ?

And while you're at it do the same for integer and float literals -- use 
the "best" type considering _all_ the elements rather than just the 
first one so that this doesn't mean an array with two 1 integers.

   [1, 1.5];

--bb
January 29, 2007
Re: Issues with constants, and inout (was Real World usage of D, Today)
Frits van Bommel wrote:
> kris wrote:
>> Andrei Alexandrescu (See Website For Email) wrote:
>>> kris wrote:
>>> [about implicit conversion rules]
>>>>         void write (char[] x) {printf("char[]\n");}
>>>>         void write (wchar[] x) {printf("wchar[]\n");}
>>>>         //foo.write ("asa");
>>>> And this, of course, compiles. It's a PITA though, and differs from 
>>>> the rules for other constants.
>>> I talked to Walter about this and it's not a bug, it's a feature :o). 
>>> Basically it's hard to decide what to do with an unadorned string 
>>> when both wchar[] and char[] would want to "attract" it. I understand 
>>> you're leaning towards defaulting to char[]? Then probably others 
>>> will be unhappy.

A slight inconsistency here is that:

foo("test");

gives a syntax error, while:

auto t = "test";
foo(t);

compiles and selects the char[] overload. Also:

void bar(T)(T x) { foo(x); }
...
bar("test");

compiles and selects the char[] overload.

> It's a bit more complicated with character literals than just defaulting 
> to 'char':
[snip typeof('e') == char, typeof('é') == wchar, ...]]
> So it defaults to the *smallest* character type that can hold it in one 
> element.
> Pretty cool, actually.

A problem related to this, that might actually warrant a bug report, is 
that given:

char[] str = "abcd";

str ~= 'e';
writefln(str);

Is OK, while

str ~= 'é';
writefln(str);

Generates an invalid UTF-8 string ant gives the runtime "Error: 4invalid 
UTF-8 sequence"

It seems like the wchar 'é' gets int-promoted to 0xE9 that is different 
from the char[] (utf-8) representation of "é", that would be x"C3 A9".

-- 
/Oskar
January 29, 2007
Re: Issues with constants, and inout (was Real World usage of D, Today)
Oskar Linde wrote:
> Frits van Bommel wrote:
>> It's a bit more complicated with character literals than just 
>> defaulting to 'char':
> [snip typeof('e') == char, typeof('é') == wchar, ...]]
>> So it defaults to the *smallest* character type that can hold it in 
>> one element.
>> Pretty cool, actually.
> 
> A problem related to this, that might actually warrant a bug report, is 
> that given:
> 
> char[] str = "abcd";
> 
> str ~= 'e';
> writefln(str);
> 
> Is OK, while
> 
> str ~= 'é';
> writefln(str);
> 
> Generates an invalid UTF-8 string ant gives the runtime "Error: 4invalid 
> UTF-8 sequence"
> 
> It seems like the wchar 'é' gets int-promoted to 0xE9 that is different 
> from the char[] (utf-8) representation of "é", that would be x"C3 A9".

Yes, that probably warrants a bug report. Either an error should be 
produced (something like "Invalid operation: str ~= 'é', cannot 
concatenate wchar to char[]"), or (preferably) it should just work.
The latter can (for example) be implemented by doing the equivalent of 
std.utf.encode(str, 'é'), or the equivalent of str ~= "é" (note the 
quotes, implicitly converting it to char[] instead of wchar).
Next ›   Last »
3 4 5 6 7
Top | Discussion index | About this forum | D home