www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - "in" operator gives a pointer result from a test against an

reply Andy Valencia <dont spam.me> writes:
tst7.d(6): Error: cannot implicitly convert expression `e in 
this.members` of type `bool*` to `bool`
tst7.d(15): Error: template instance `tst7.Foo!uint` error 
instantiating

I'm getting this for this bit of source (trimmed from the bigger 
code).  I switched to this.members.get(e, false) and that works 
fine, but I'm still curious:

struct Foo(T) {
     bool[T] members;

     bool
     has(T e) {
         return (e in this.members);
     }
}

void
main()
{
     import std.stdio : writeln;

     auto t = Foo!uint();
     writeln(t.has(123));
}
May 09
parent reply Meta <jared771 gmail.com> writes:
On Friday, 10 May 2024 at 00:18:16 UTC, Andy Valencia wrote:
 tst7.d(6): Error: cannot implicitly convert expression `e in 
 this.members` of type `bool*` to `bool`
 tst7.d(15): Error: template instance `tst7.Foo!uint` error 
 instantiating

 I'm getting this for this bit of source (trimmed from the 
 bigger code).  I switched to this.members.get(e, false) and 
 that works fine, but I'm still curious:

 struct Foo(T) {
     bool[T] members;

     bool
     has(T e) {
         return (e in this.members);
     }
 }

 void
 main()
 {
     import std.stdio : writeln;

     auto t = Foo!uint();
     writeln(t.has(123));
 }
Yes. The reason for this is that it avoids having to essentially do the same check twice. If `in` returned a bool instead of a pointer, after checking for whether the element exists (which requires searching for the element in the associative array), you'd then have to actually *get* it from the array, which would require searching again. Returning a pointer to the element if it exists (or `null` if it doesn't) cuts this down to 1 operation.
May 09
parent reply Andy Valencia <dont spam.me> writes:
On Friday, 10 May 2024 at 00:40:01 UTC, Meta wrote:
 Yes. The reason for this is that it avoids having to 
 essentially do the same check twice. If `in` returned a bool 
 instead of a pointer, after checking for whether the element 
 exists (which requires searching for the element in the 
 associative array), you'd then have to actually *get* it from 
 the array, which would require searching again. Returning a 
 pointer to the element if it exists (or `null` if it doesn't) 
 cuts this down to 1 operation.
Looking at Programming in D section 28.5, I'm guessing that pointer versus null is treated as the appropriate boolean value when consumed by an "if" test. So that example is getting a pointer to a string, or null, but the example looks exactly as the same as if it had directly gotten a bool. Thank you! Andy
May 09
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On Friday, 10 May 2024 at 01:00:09 UTC, Andy Valencia wrote:
 On Friday, 10 May 2024 at 00:40:01 UTC, Meta wrote:
 Yes. The reason for this is that it avoids having to 
 essentially do the same check twice. If `in` returned a bool 
 instead of a pointer, after checking for whether the element 
 exists (which requires searching for the element in the 
 associative array), you'd then have to actually *get* it from 
 the array, which would require searching again. Returning a 
 pointer to the element if it exists (or `null` if it doesn't) 
 cuts this down to 1 operation.
Looking at Programming in D section 28.5, I'm guessing that pointer versus null is treated as the appropriate boolean value when consumed by an "if" test. So that example is getting a pointer to a string, or null, but the example looks exactly as the same as if it had directly gotten a bool.
Yes, we say that a type has "truthiness" if it can be used in a condition (`while`, `if`, `assert`, etc). For a pointer, `null` is considered "false", whereas any other value is considered "true". So you can use statements like `if(key in aa)` to test for membership. A very nice idiom is to check if a key is in an associative array, and if so, use the value that it maps to: ```d if(auto v = key in aa) { // use *v as the value here } ``` You can change your code to `return (e in this.members) !is null;` -Steve
May 09
parent reply Andy Valencia <dont spam.me> writes:
On Friday, 10 May 2024 at 03:07:43 UTC, Steven Schveighoffer 
wrote:
 Yes, we say that a type has "truthiness" if it can be used in a 
 condition (`while`, `if`, `assert`, etc).
So if I may ask for one more small clarification... WRT "truthiness", I've observed that empty arrays are treated as false, non-empty as true. However, although I thought a string was basically an immutable array of characters, "" is treated as true, not false? Thanks again, Andy
May 10
parent reply Nick Treleaven <nick geany.org> writes:
On Friday, 10 May 2024 at 15:23:39 UTC, Andy Valencia wrote:
 On Friday, 10 May 2024 at 03:07:43 UTC, Steven Schveighoffer 
 wrote:
 Yes, we say that a type has "truthiness" if it can be used in 
 a condition (`while`, `if`, `assert`, etc).
So if I may ask for one more small clarification... WRT "truthiness", I've observed that empty arrays are treated as false, non-empty as true.
Arrays evaluate to true in boolean conditions if their `.ptr` field is non-null. This is bug-prone and I hope we can remove this in the next edition.
 However, although I thought a string was basically an immutable 
 array of characters, "" is treated as true, not false?
A string literal's `.ptr` field is always non-null, because it is null-terminated.
May 10
parent Andy Valencia <dont spam.me> writes:
On Friday, 10 May 2024 at 16:33:53 UTC, Nick Treleaven wrote:
 Arrays evaluate to true in boolean conditions if their `.ptr` 
 field is non-null. This is bug-prone and I hope we can remove 
 this in the next edition.
 ...
 A string literal's `.ptr` field is always non-null, because it 
 is null-terminated.
Thank you! Andy
May 10