Why 'in' works only for assoc arrays?
JN
666total at wp.pl
Sat Dec 28 02:14:34 UTC 2024
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...
More information about the Digitalmars-d-learn
mailing list