How to implement filterMap
Siarhei Siamashka
siarhei.siamashka at gmail.com
Sun Dec 31 09:47:27 UTC 2023
On Saturday, 30 December 2023 at 13:25:00 UTC, Christian Köstlin
wrote:
> On Saturday, 30 December 2023 at 01:22:31 UTC, Siarhei
> Siamashka wrote:
>> On Friday, 29 December 2023 at 23:10:47 UTC, Christian Köstlin
>> wrote:
>>> Is there a way to implement filterMap (meaning do mapping of
>>> a range, but if something happens during the map, leave this
>>> element out of the resulting range).
>>
>> It's probably not a good idea to do this in general. Expecting
>> a lot of exceptions handling happening during normal program
>> execution (if you want to filter out roughly half of the input
>> array) will result in a major performance loss. Exceptions are
>> best left to just do error handling on a very rarely used code
>> path for troubleshooting purposes.
>
> Thanks for the feedback.
>
> This might be true, but in my example I would parse the input
> always with conv.to, so I would need to handle the exception(s).
I still think that a much better design is to have a try/catch
block much higher in the call stack and print a "malformed input"
error message to the user. Or handle the error in some other way
(for example, allow the user to try again with a different input
data).
> The "original"
> https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.filter_map works with the Option(Some/None) ...
Here's an example with `Nullable`, inspired by the earlier
comment from Alexandru Ermicioi:
```D
import std;
auto toNullableInt(string s) {
try { return s.to!int.nullable; } catch (Exception e) {}
Nullable!int ret;
return ret;
}
void main() {
// prints [2, 4]
auto a = ["1", "2", "abc", ""];
a.map!toNullableInt.filter!"!a.isNull".map!"a.get * 2".writeln;
// prints [2, 4, 198]
auto b = ["1", "2", "abc", "", "99999999999999999999", "99"];
b.map!toNullableInt.filter!"!a.isNull".map!"a.get * 2".writeln;
// prints [2, 4, -294967298, 198]
auto c = ["1", "2", "abc", "", "1999999999", "99"];
c.map!toNullableInt.filter!"!a.isNull".map!"a.get * 2".writeln;
}
```
Take a look at the `b` array. With this particular design, the
"99999999999999999999" value is going to be silently filtered
out. If you or your users happen to expect only non-digit string
literals or empty strings to be filtered out, then there may be a
very nasty and difficult to debug unexpected surprise awaiting
down the road.
Also take a look at the `c` array. The handling of arithmetic
overflows is a safety problem of the D language design. Certain
types of input may cause overflows, which result in producing
bogus data as a result of running your program and are very
difficult to troubleshoot. The use of the GDC's `-ftrapv` option
surely helps in troubleshooting such cases, but some software or
D libraries may intentionally rely on the D's arithmetic
wraparound feature.
More information about the Digitalmars-d-learn
mailing list