Re: "in" operator gives a pointer result from a test against an Associative Array?

2024-05-10 Thread Andy Valencia via Digitalmars-d-learn

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


Re: "in" operator gives a pointer result from a test against an Associative Array?

2024-05-10 Thread Nick Treleaven via Digitalmars-d-learn

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.


Re: "in" operator gives a pointer result from a test against an Associative Array?

2024-05-10 Thread Andy Valencia via Digitalmars-d-learn
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



Re: "in" operator gives a pointer result from a test against an Associative Array?

2024-05-09 Thread Steven Schveighoffer via Digitalmars-d-learn

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


Re: "in" operator gives a pointer result from a test against an Associative Array?

2024-05-09 Thread Andy Valencia via Digitalmars-d-learn

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



Re: "in" operator gives a pointer result from a test against an Associative Array?

2024-05-09 Thread Meta via Digitalmars-d-learn

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.


"in" operator gives a pointer result from a test against an Associative Array?

2024-05-09 Thread Andy Valencia via Digitalmars-d-learn
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));
}