On Sunday, 9 August 2015 at 01:29:16 UTC, Christopher Davies wrote:
I'm just learning D. Something I often do in C# is have an IEnumerable (Range) of some type that is then conditionally filtered. It looks like this:

IEnumerable<Dictionary<string, string>> foo = bar;

if (baz)
{
    foo = foo.Where(d => d["key"] == value);
}

I'm trying to do the same in D. Here's what I want to do:

Range!(string[string]) records = csvReader!(string[string])(input, null);

if (where != "")
{
    records = filter!(r => r[where] == val)(records);
}
using UFCS (universal function call syntax) you would normally write that as:
records =records.filter!(r => r[where] == val)();
and then leveraging D's optional parentheses as:
records =records.filter!(r => r[where] == val)
This allows you to chain them along with map, filter, reduce etc. with ease
e.g.
auto result = someRange.filter!(e =>e.isFooCompatible).map!(e => foo(e)).map!(e => e.toBar).array;

do you care about the type of result? Not really. It's a range. meaning you can pass iterate over it, pass it to other algorithms.


But Range!(string[string]) isn't right, even though that's what the csvReader and filter statements produce. How do I declare that type?

Type inference is your friend.
      auto foo = bar;
will work for any type that does not disallow copying (@disable this(this); )

To answer your question what you probably want is not
      auto records = csvReader!(string[string])(input, null);

      if (where != "")
      {
             records = records.filter!(r => r[where] == val);
      }
but:
      auto records = csvReader!(string[string])(input, null);

      if (where != "")
      {
auto filteredRecords = records.filter!(r => r[where] == val);
             //do something with filteredRecords ...
      }
or just
      if (where != "")
      {
              // if you need the result exclude comment below
              // or if your operation is for side effects only
              // leave it.
/*auto result =*/ csvReader!(string[string])(input, null)
                                         .filter(e => somePred(e))
.continueChainingRanges(withSomeArgs)
                                         .untilYoureDone;

      }

If you just want a copy of the filtered results

if (where != "")
      {

             auto result = csvReader!(string[string])(input, null)
.filter(e => e[where] == val).array; // .array causes a separate copy of the values of the result of csvReader

      }

Nic

Reply via email to