On 9/27/20 11:54 AM, tastyminerals wrote:

> I have a collection of functions that all have the same input, a string.
> The output however is different and depending on what the function does
> it can be ulong, double or bool.

The following approach overcomes the different return type issue by creating delegates that take string and return string:

auto numberOfPunctChars(string text) {
  return 42;
}

auto ratioOfDigitsToChars(string text) {
  return 1.5;
}

auto hasUnbalancedParens(string text) {
  return true;
}

struct FeatureSet {
  alias TakesString = string delegate(string);
  TakesString[] features;

  void register(Func)(Func func) {
    // Here, we convert from a function returning any type
    // to a delegate returning string:
    features ~= (string s) {
      import std.conv : text;
      return func(s).text;
    };
  }

  // Here, we apply all feature delegates and put the outputs
  // into the provided output range.
  void apply(O)(ref O outputRange, string s) {
    import std.format : formattedWrite;
    import std.algorithm : map;
    outputRange.formattedWrite!"%-(%s\n%|%)"(features.map!(f => f(s)));
  }
}

void main() {
  auto featureSet = FeatureSet();

  featureSet.register(&numberOfPunctChars);
  featureSet.register(&ratioOfDigitsToChars);
  featureSet.register(&hasUnbalancedParens);

  // lockingTextWriter() just makes an output range from
  // an output stream.
  import std.stdio;
  auto output = stdout.lockingTextWriter;
  featureSet.apply(output, "hello world");

  // As another example, you can use an Appender as well:
  import std.array : Appender;
  auto app = Appender!(char[])();
  featureSet.apply(app, "goodbye moon");
  writefln!"Appender's content:\n%s"(app.data);
}

Ali

Reply via email to