www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - string and char[]

reply Morlan <home valentimex.com> writes:
It is OK if I write

  int[char[]] asr;
  asr["hello"] = 10;

but the following does not compile:

  char[] car = "hello";

What is the explanation for this behaviour?
Apr 08 2011
next sibling parent reply "Simen kjaeraas" <simen.kjaras gmail.com> writes:
On Fri, 08 Apr 2011 12:46:08 +0200, Morlan <home valentimex.com> wrote:

 It is OK if I write

   int[char[]] asr;
   asr["hello"] = 10;

 but the following does not compile:

   char[] car = "hello";

 What is the explanation for this behaviour?

The first should not be allowed. It is a mistake to use non-immutable keys for an associative array. -- Simen
Apr 08 2011
next sibling parent reply simendsjo <simen.endsjo pandavre.com> writes:
 It is a mistake to use non-immutable keys for an associative array.

But a string literal isn't mutable..?
Apr 08 2011
parent reply Morlan <home valentimex.com> writes:
int[char[]] is consistently used D's Language
reference to illustrate associative arrays. For me it
looks like something that should not compile. Of
course int[string] works without problem so I wonder
why int[char[]] was used as an example. Was it carried
over from D1 reference perhaps?
Apr 08 2011
parent Morlan <home valentimex.com> writes:
Of course, by saying it should not compile I mean
things like asr["hello"] should not compile.
Apr 08 2011
prev sibling next sibling parent spir <denis.spir gmail.com> writes:
On 04/08/2011 03:13 PM, Steven Schveighoffer wrote:
 On Fri, 08 Apr 2011 06:44:42 -0400, Simen kjaeraas <simen.kjaras gmail.com>
wrote:

 On Fri, 08 Apr 2011 12:46:08 +0200, Morlan <home valentimex.com> wrote:

 It is OK if I write

 int[char[]] asr;
 asr["hello"] = 10;

 but the following does not compile:

 char[] car = "hello";

 What is the explanation for this behaviour?

The first should not be allowed. It is a mistake to use non-immutable keys for an associative array.

int[char[]] asr; pragma(msg, typeof(asr).stringof); outputs: AssociativeArray!(const(char)[],int) So the compiler adds const to the keys, which is why it works. Do I think this is the correct behavior? Absolutely not. First, it prevents nothing as far as modifying keys (const accepts mutable keys as well as const and mutable ones). Second, I believe you should be able to use whatever key constancy you want. We should just say if you do the wrong thing, it's undefined. Maybe safe code can only use immutable keys. Third, if it must be illegal to have an AA with mutable keys, it should be an error, not silently change to const.

I agree on points 1 & 3. "Second" looks dangerous to me. Denis -- _________________ vita es estrany spir.wikidot.com
Apr 08 2011
prev sibling next sibling parent spir <denis.spir gmail.com> writes:
On 04/08/2011 03:40 PM, Denis Koroskin wrote:
 What about storing objects as keys? There is nothing wrong to modify those
 objects as long as their order stays the same.

I think if referenced objects are to be used as keys, they should be compared by pointer/identity (hash would return their address?). Then, it's up to the programmer to be coherent. After all, that is the sense of "reference" isn't it? Denis -- _________________ vita es estrany spir.wikidot.com
Apr 08 2011
prev sibling parent spir <denis.spir gmail.com> writes:
On 04/08/2011 09:20 PM, Steven Schveighoffer wrote:
 On Fri, 08 Apr 2011 14:57:52 -0400, spir <denis.spir gmail.com> wrote:

 On 04/08/2011 03:13 PM, Steven Schveighoffer wrote:
 On Fri, 08 Apr 2011 06:44:42 -0400, Simen kjaeraas <simen.kjaras gmail.com>
 wrote:

 On Fri, 08 Apr 2011 12:46:08 +0200, Morlan <home valentimex.com> wrote:

 It is OK if I write

 int[char[]] asr;
 asr["hello"] = 10;

 but the following does not compile:

 char[] car = "hello";

 What is the explanation for this behaviour?

The first should not be allowed. It is a mistake to use non-immutable keys for an associative array.

int[char[]] asr; pragma(msg, typeof(asr).stringof); outputs: AssociativeArray!(const(char)[],int) So the compiler adds const to the keys, which is why it works. Do I think this is the correct behavior? Absolutely not. First, it prevents nothing as far as modifying keys (const accepts mutable keys as well as const and mutable ones). Second, I believe you should be able to use whatever key constancy you want. We should just say if you do the wrong thing, it's undefined. Maybe safe code can only use immutable keys. Third, if it must be illegal to have an AA with mutable keys, it should be an error, not silently change to const.

I agree on points 1 & 3. "Second" looks dangerous to me.

Dangerous, yes. But immutable objects are typically not easy to deal with. For one, you can't have tail-immutable objects (currently), so implementation of such a container is going to be a pain. In fact, dcollections simply doesn't work if you have fully immutable types as keys. In reality, most times you are not using something as a key and somewhere else simultaneously. So while theoretically dangerous, it's easy to write code that isn't dangerous.

What about ref'ed objects used as keys be compared (at least as keys) by ref -- and only by ref. This is how Lua tables work (and the reason why they're so fast): a = {1,1} ; b = {2,2} t = {[a]=1 , [b]=2} print (t[a], t[{1,1}]) --> 1 nil a and the second {1,1} key are distinct objects. This is not often what we mean, in the general case. Composite objects actually often are, conceptually, *values*, like a position or color; thus, should be compared by value. But they sometimes represent unique "entities", like a game character, which should be compared (as keys and everywhere else) by "unicity" -- and only that way. Comparing their state simply makes no sense. Denis -- _________________ vita es estrany spir.wikidot.com
Apr 08 2011
prev sibling next sibling parent "Simen kjaeraas" <simen.kjaras gmail.com> writes:
On Fri, 08 Apr 2011 13:01:41 +0200, simendsjo <simen.endsjo pandavre.com>  
wrote:

 It is a mistake to use non-immutable keys for an associative array.

But a string literal isn't mutable..?

This is correct. I'm referring to line 1, int[char[]] asr;. This declaration is wrong, and should be rejected by the compiler. Also note that I'm saying non-immutable. const is not good enough, as it may come from a mutable source. -- Simen
Apr 08 2011
prev sibling next sibling parent "Simen kjaeraas" <simen.kjaras gmail.com> writes:
On Fri, 08 Apr 2011 13:37:10 +0200, Morlan <home valentimex.com> wrote:

 int[char[]] is consistently used D's Language
 reference to illustrate associative arrays. For me it
 looks like something that should not compile. Of
 course int[string] works without problem so I wonder
 why int[char[]] was used as an example. Was it carried
 over from D1 reference perhaps?

Probably it was. Could you please file a bug report on that? http://d.puremagic.com/issues/enter_bug.cgi -- Simen
Apr 08 2011
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 08 Apr 2011 06:44:42 -0400, Simen kjaeraas  
<simen.kjaras gmail.com> wrote:

 On Fri, 08 Apr 2011 12:46:08 +0200, Morlan <home valentimex.com> wrote:

 It is OK if I write

   int[char[]] asr;
   asr["hello"] = 10;

 but the following does not compile:

   char[] car = "hello";

 What is the explanation for this behaviour?

The first should not be allowed. It is a mistake to use non-immutable keys for an associative array.

int[char[]] asr; pragma(msg, typeof(asr).stringof); outputs: AssociativeArray!(const(char)[],int) So the compiler adds const to the keys, which is why it works. Do I think this is the correct behavior? Absolutely not. First, it prevents nothing as far as modifying keys (const accepts mutable keys as well as const and mutable ones). Second, I believe you should be able to use whatever key constancy you want. We should just say if you do the wrong thing, it's undefined. Maybe safe code can only use immutable keys. Third, if it must be illegal to have an AA with mutable keys, it should be an error, not silently change to const. -Steve
Apr 08 2011
prev sibling next sibling parent "Denis Koroskin" <2korden gmail.com> writes:
On Fri, 08 Apr 2011 17:13:19 +0400, Steven Schveighoffer  
<schveiguy yahoo.com> wrote:

 On Fri, 08 Apr 2011 06:44:42 -0400, Simen kjaeraas  
 <simen.kjaras gmail.com> wrote:

 On Fri, 08 Apr 2011 12:46:08 +0200, Morlan <home valentimex.com> wrote:

 It is OK if I write

   int[char[]] asr;
   asr["hello"] = 10;

 but the following does not compile:

   char[] car = "hello";

 What is the explanation for this behaviour?

The first should not be allowed. It is a mistake to use non-immutable keys for an associative array.

int[char[]] asr; pragma(msg, typeof(asr).stringof); outputs: AssociativeArray!(const(char)[],int) So the compiler adds const to the keys, which is why it works. Do I think this is the correct behavior? Absolutely not. First, it prevents nothing as far as modifying keys (const accepts mutable keys as well as const and mutable ones). Second, I believe you should be able to use whatever key constancy you want. We should just say if you do the wrong thing, it's undefined. Maybe safe code can only use immutable keys. Third, if it must be illegal to have an AA with mutable keys, it should be an error, not silently change to const. -Steve

What about storing objects as keys? There is nothing wrong to modify those objects as long as their order stays the same. Immutable works, but that's an overkill, tail const would suffice in most cases (where an indirection isn't used). E.g.: int[void*] example; All that is required is that "int compare(T)(T lhs, T rhs)" is pure (i.e. returns same result for same inputs). In future, compiler could statically enforce that int compare(void* lhs, void* rhs) pure { if (lhs < rhs) return 1; if (lhs > rhs) return -1; return 0; } is correct and int compare(char[] lhs, char[] rhs) pure { if (lhs < rhs) return 1; if (lhs > rhs) return -1; return 0; } is not. For some reason (bug?), both compile with 2.052.
Apr 08 2011
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 08 Apr 2011 09:40:32 -0400, Denis Koroskin <2korden gmail.com>  
wrote:

 On Fri, 08 Apr 2011 17:13:19 +0400, Steven Schveighoffer  
 <schveiguy yahoo.com> wrote:

 On Fri, 08 Apr 2011 06:44:42 -0400, Simen kjaeraas  
 <simen.kjaras gmail.com> wrote:

 On Fri, 08 Apr 2011 12:46:08 +0200, Morlan <home valentimex.com> wrote:

 It is OK if I write

   int[char[]] asr;
   asr["hello"] = 10;

 but the following does not compile:

   char[] car = "hello";

 What is the explanation for this behaviour?

The first should not be allowed. It is a mistake to use non-immutable keys for an associative array.

int[char[]] asr; pragma(msg, typeof(asr).stringof); outputs: AssociativeArray!(const(char)[],int) So the compiler adds const to the keys, which is why it works. Do I think this is the correct behavior? Absolutely not. First, it prevents nothing as far as modifying keys (const accepts mutable keys as well as const and mutable ones). Second, I believe you should be able to use whatever key constancy you want. We should just say if you do the wrong thing, it's undefined. Maybe safe code can only use immutable keys. Third, if it must be illegal to have an AA with mutable keys, it should be an error, not silently change to const. -Steve

What about storing objects as keys? There is nothing wrong to modify those objects as long as their order stays the same.

I agree with you. See my second point. But even if that isn't what the committee decides, the current behavior guarantees absolutely nothing. -Steve
Apr 08 2011
prev sibling next sibling parent Jesse Phillips <jessekphillips+d gmail.com> writes:
On Fri, 08 Apr 2011 17:40:32 +0400, Denis Koroskin wrote:

 int compare(char[] lhs, char[] rhs) pure {
      if (lhs < rhs) return 1;
      if (lhs > rhs) return -1;
      return 0;
 }
 
 is not.
 
 For some reason (bug?), both compile with 2.052.

Purity has nothing to do with the type. "Hello" and a char[] storing "Hello" will always produce the same results when passed to this function. The fact that it can be changed to "Byelo" does not effect the results for when "Hello" is passed in. I agree that Objects make for great mutable keys, but how can you guarantee the hash won't change when the contents change, toHash is overridable after all.
Apr 08 2011
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 08 Apr 2011 14:57:52 -0400, spir <denis.spir gmail.com> wrote:

 On 04/08/2011 03:13 PM, Steven Schveighoffer wrote:
 On Fri, 08 Apr 2011 06:44:42 -0400, Simen kjaeraas  
 <simen.kjaras gmail.com> wrote:

 On Fri, 08 Apr 2011 12:46:08 +0200, Morlan <home valentimex.com> wrote:

 It is OK if I write

 int[char[]] asr;
 asr["hello"] = 10;

 but the following does not compile:

 char[] car = "hello";

 What is the explanation for this behaviour?

The first should not be allowed. It is a mistake to use non-immutable keys for an associative array.

int[char[]] asr; pragma(msg, typeof(asr).stringof); outputs: AssociativeArray!(const(char)[],int) So the compiler adds const to the keys, which is why it works. Do I think this is the correct behavior? Absolutely not. First, it prevents nothing as far as modifying keys (const accepts mutable keys as well as const and mutable ones). Second, I believe you should be able to use whatever key constancy you want. We should just say if you do the wrong thing, it's undefined. Maybe safe code can only use immutable keys. Third, if it must be illegal to have an AA with mutable keys, it should be an error, not silently change to const.

I agree on points 1 & 3. "Second" looks dangerous to me.

Dangerous, yes. But immutable objects are typically not easy to deal with. For one, you can't have tail-immutable objects (currently), so implementation of such a container is going to be a pain. In fact, dcollections simply doesn't work if you have fully immutable types as keys. In reality, most times you are not using something as a key and somewhere else simultaneously. So while theoretically dangerous, it's easy to write code that isn't dangerous. -Steve
Apr 08 2011
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 08 Apr 2011 16:12:27 -0400, spir <denis.spir gmail.com> wrote:

 On 04/08/2011 09:20 PM, Steven Schveighoffer wrote:
 In reality, most times you are not using something as a key and  
 somewhere else
 simultaneously. So while theoretically dangerous, it's easy to write  
 code that
 isn't dangerous.

What about ref'ed objects used as keys be compared (at least as keys) by ref -- and only by ref. This is how Lua tables work (and the reason why they're so fast): a = {1,1} ; b = {2,2} t = {[a]=1 , [b]=2} print (t[a], t[{1,1}]) --> 1 nil a and the second {1,1} key are distinct objects. This is not often what we mean, in the general case. Composite objects actually often are, conceptually, *values*, like a position or color; thus, should be compared by value. But they sometimes represent unique "entities", like a game character, which should be compared (as keys and everywhere else) by "unicity" -- and only that way. Comparing their state simply makes no sense.

I believe objects are compared that way by default. But you may want to compare them based on their values. For example, a container may want to compare equal to another container if it has all of the same elements, regardless of whether they are the same exact instance. In any case, allowing non-immutable keys in the case where it's just the references being compared is a good use case. -Steve
Apr 08 2011