www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Char literals

reply Eldar Insafutdinov <e.insafutdinov gmail.com> writes:
I've just written a simple replicate function (the one from std.range does not
work in CTFE):
T[] replicate(T)(int n, T value)
{
    T[] ret;
    if (n > 0)
    {
        for(int i = 0; i < n; i++)
            ret ~= value;
    }
    return ret;
}
it's not the best implementation, but that's not the thing I want to say today.
When I call it

string str = replicate(5, 'a');

I get

moc.d(370): Error: cannot implicitly convert expression (replicate(5,',')) of
type char[] to string

That means that char literals are "char", but not "immutable(char)". I remember
the whole conversation about array literals, but char literals are closer to
those of the string. What's the reasoning behind leaving them as mutable char?
Nov 06 2009
next sibling parent Michal Minich <michal.minich gmail.com> writes:
Hello Eldar,

 I've just written a simple replicate function (the one from std.range
 does not work in CTFE):
 T[] replicate(T)(int n, T value)
 {
 T[] ret;
 if (n > 0)
 {
 for(int i = 0; i < n; i++)
 ret ~= value;
 }
 return ret;
 }
 it's not the best implementation, but that's not the thing I want to
 say today. When I call it
 
 string str = replicate(5, 'a');
 
 I get
 
 moc.d(370): Error: cannot implicitly convert expression
 (replicate(5,',')) of type char[] to string
 
 That means that char literals are "char", but not "immutable(char)". I
 remember the whole conversation about array literals, but char
 literals are closer to those of the string. What's the reasoning
 behind leaving them as mutable char?
 

no builtin type is immutable by default. string is not builtin type, it is defined as "alias immutable(char)[] string;" in object.d file.
Nov 06 2009
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 06 Nov 2009 06:24:51 -0500, Eldar Insafutdinov  
<e.insafutdinov gmail.com> wrote:

 I've just written a simple replicate function (the one from std.range  
 does not work in CTFE):
 T[] replicate(T)(int n, T value)
 {
     T[] ret;
     if (n > 0)
     {
         for(int i = 0; i < n; i++)
             ret ~= value;
     }
     return ret;
 }
 it's not the best implementation, but that's not the thing I want to say  
 today. When I call it

 string str = replicate(5, 'a');

 I get

 moc.d(370): Error: cannot implicitly convert expression  
 (replicate(5,',')) of type char[] to string

 That means that char literals are "char", but not "immutable(char)". I  
 remember the whole conversation about array literals, but char literals  
 are closer to those of the string. What's the reasoning behind leaving  
 them as mutable char?

a value type such as char makes no sense as an immutable entity. First of all, an immutable char can be implicitly cast to and from a mutable char. Although it might seem incorrect, since it is a value type, assigning it to an immutable variable makes a copy anyways, so the mutability/immutability of the original variable stays intact. You bring up a legitimate concern. However, you are probably never going to see 'a' by itself typed as an immutable char, because mutable makes the most sense as the default constancy of a value type literal. It seems that string literals being typed as immutable(char)[] is an inconsistency in the world of D literals that always needs to be handled specially. What you probably want to have is a specialization for your template. Again, another use case for unique(T)... BTW, you can save a loop by doing this: T[] ret = new T[n]; ret[] = value; // assign value to all elements of ret -Steve
Nov 06 2009
prev sibling parent reply Bill Baxter <wbaxter gmail.com> writes:
On Fri, Nov 6, 2009 at 3:24 AM, Eldar Insafutdinov
<e.insafutdinov gmail.com> wrote:
 I've just written a simple replicate function (the one from std.range doe=

 T[] replicate(T)(int n, T value)
 {
 =A0 =A0T[] ret;
 =A0 =A0if (n > 0)
 =A0 =A0{
 =A0 =A0 =A0 =A0for(int i =3D 0; i < n; i++)
 =A0 =A0 =A0 =A0 =A0 =A0ret ~=3D value;
 =A0 =A0}
 =A0 =A0return ret;
 }
 it's not the best implementation, but that's not the thing I want to say =

 string str =3D replicate(5, 'a');

 I get

 moc.d(370): Error: cannot implicitly convert expression (replicate(5,',')=

 That means that char literals are "char", but not "immutable(char)". I re=

loser to those of the string. What's the reasoning behind leaving them as m= utable char? In Phobos they use std.contracts.assumeUnique to turn char[] to string at the end of string processing functions. It's actually just a cast to immutable(char)[]. But the idea is you're asserting that you know the char[] data is not referenced by anyone else (your reference is unique) so it's safe to make it immutable. So it documents the intent better than a straight cast. It's also better because if you later change the underlying type say from char[] to dchar[], assumeUnique will still do the right thing (become a cast to immutable(dchar)[]), but cast(string) would silently become bogus. --bb
Nov 06 2009
parent Eldar Insafutdinov <e.insafutdinov gmail.com> writes:
Bill Baxter Wrote:

 On Fri, Nov 6, 2009 at 3:24 AM, Eldar Insafutdinov
 <e.insafutdinov gmail.com> wrote:
 I've just written a simple replicate function (the one from std.range does not
work in CTFE):
 T[] replicate(T)(int n, T value)
 {
    T[] ret;
    if (n > 0)
    {
        for(int i = 0; i < n; i++)
            ret ~= value;
    }
    return ret;
 }
 it's not the best implementation, but that's not the thing I want to say
today. When I call it

 string str = replicate(5, 'a');

 I get

 moc.d(370): Error: cannot implicitly convert expression (replicate(5,',')) of
type char[] to string

 That means that char literals are "char", but not "immutable(char)". I
remember the whole conversation about array literals, but char literals are
closer to those of the string. What's the reasoning behind leaving them as
mutable char?

In Phobos they use std.contracts.assumeUnique to turn char[] to string at the end of string processing functions. It's actually just a cast to immutable(char)[]. But the idea is you're asserting that you know the char[] data is not referenced by anyone else (your reference is unique) so it's safe to make it immutable. So it documents the intent better than a straight cast. It's also better because if you later change the underlying type say from char[] to dchar[], assumeUnique will still do the right thing (become a cast to immutable(dchar)[]), but cast(string) would silently become bogus. --bb

Yes you are right, I used cast(string) eventually and made it non-template. There were other bugs that are specific to CTFE that I could not track down though.
Nov 06 2009