Why does choose not work here

ag0aep6g anonymous at example.com
Thu Aug 1 21:12:51 UTC 2019


On 01.08.19 22:23, Matt wrote:
> Version 4 does not work when PairedA.previous is null. I'd love to 
> understand why.
> 
[...]
> 
> auto myFilter(R1, R2)(R1 a, R2 b)
> {
>      import std.algorithm : filter, canFind;
>      return a.filter!(c => b.canFind(c));
> }
> 
> struct A
> {
>      uint[] starts, stops;
> 
>      import std.range : ForwardRange, inputRangeObject;
>      import std.typecons : Tuple;
>      ForwardRange!(Tuple!(uint,uint)) intervalRange() @property
>      {
>          import std.algorithm : map;
>          import std.range : zip;
>          import std.typecons : tuple;
>          return zip(starts,stops).map!(a => 
> tuple(a[0],a[1])).inputRangeObject;
>      }
> }
> 
> struct PairedA
> {
[...]
>      //version 4
>      auto uniqIntervals() @property
>      {
>          import std.range : choose;
>          import std.algorithm : filter, canFind;
>          return choose(previous is null,
>              primary.intervalRange,
>              primary.intervalRange
>                  .myFilter(previous.intervalRange));
>      }
> 
>      A primary;
>      A* previous;
> }

`choose`'s parameters aren't lazy. So the second argument is evaluated 
even when `previous is null`. That means `intervalRange` is called on a 
null `previous`. And that fails, of course, because `intervalRange` 
can't access `starts` or `stops` when `this` is null.


More information about the Digitalmars-d-learn mailing list