On Friday, 27 December 2024 at 19:55:41 UTC, Andy Valencia wrote:
> One thing I learned which is somewhat topical--"x in y" is not a boolean expression; its value of the expression is a pointer to the value in the AA. This would break for "string in string" searches, but seems OK for regular arrays.
Andy
"in" only works for associative arrays by checking for existence of a provided key in an associative array. E.g.:
```
void main()
{
string[string] nameAddressMapping = ["John": "New York"];
assert("John" in nameAddressMapping);
assert("Mary" in nameAddressMapping); // assert failure
}
```
Naturally, a user will try to use it to check for existence of a value in an array, such as:
```
string[] names = ["John", "Alice", "Bob"];
assert("John" in names);
```
But that won't work, because:
onlineapp.d(7): Error: incompatible types for `("John") in (names)`: `string` and `string[]`
onlineapp.d(7): `in` is only allowed on associative arrays
onlineapp.d(7): perhaps use `std.algorithm.find("John", names)` instead
Okay, so the user will try the suggestion of the compiler:
```
string[] names = ["John", "Alice", "Bob"];
assert(std.algorithm.find("John", names));
```
This will fail in compilation, because in std.algorithm.find, the haystack comes first, then the needle. And the error isn't even obvious, because it's a template spew.
```
onlineapp.d(6): Error: none of the overloads of template `std.algorithm.searching.find` are callable using argument types `!()(string, string[])`
/dlang/dmd/linux/bin64/../../src/phobos/std/algorithm/searching.d(1598): Candidates are: `find(alias pred, InputRange)(InputRange haystack)`
/dlang/dmd/linux/bin64/../../src/phobos/std/algorithm/searching.d(1685): `find(alias pred = "a == b", InputRange, Element)(InputRange haystack, scope Element needle)`
with `pred = "a == b",
InputRange = string,
Element = string[]`
must satisfy the following constraint:
` is(typeof(binaryFun!pred(haystack.front, needle)) : bool)`
/dlang/dmd/linux/bin64/../../src/phobos/std/algorithm/searching.d(1953): `find(alias pred = "a == b", R1, R2)(R1 haystack, scope R2 needle)`
with `pred = "a == b",
R1 = string,
R2 = string[]`
must satisfy the following constraint:
` is(typeof(binaryFun!pred(haystack.front, needle.front)) : bool)`
/dlang/dmd/linux/bin64/../../src/phobos/std/algorithm/searching.d(2412): `find(alias pred = "a == b", Range, Needles...)(Range haystack, Needles needles)`
with `pred = "a == b",
Range = string,
Needles = (string[])`
must satisfy the following constraint:
` Needles.length > 1`
/dlang/dmd/linux/bin64/../../src/phobos/std/algorithm/searching.d(2527): `find(RandomAccessRange, alias pred, InputRange)(RandomAccessRange haystack, scope BoyerMooreFinder!(pred, InputRange) needle)`
```
So let's try to re-order the function arguments so it's as it should be:
```
string[] names = ["John", "Alice", "Bob"];
assert(std.algorithm.find(names, "John"));
```
It's fine now, right? Oh wait, it isn't.
```
string[] names = ["John", "Alice", "Bob"];
assert(std.algorithm.find(names, "Mary")); // no assert failure
```
find returns empty haystack when no match is found and empty arrays in D evaluate to true. So the find replacement proposed by the compiler doesn't do what we wanted in the first place.
At the very least, the compiler message should be fixed, the args to std.algorithm.find should be swapped
Still, the fix with find doesn't exactly work how the user would expect it. I think the compiler message should recommend std.algorithm.canFind instead.
Can we make "in" to just work for arrays? things like if (3 in [1,2,3]) and if ("abc" in "abcdef") should just work...