www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Deciding one member of iteration chain at runtime

reply Chris Piker <chris hoopjump.com> writes:
Hi D

I have a main "loop" for a data processing program that looks 
much as follows:
```d
sourceRange
   .operatorA
   .operatorB
   .operatorC
   .operatorD
   .operatorE
   .operatorF
   .operatorG
   .operatorH
   .copy(destination);
```
Where all `operator` items above are InputRange structs that take 
an upstream range, and the pipeline really is 9 operations deep.

In order to handle new functionality it turns out that operatorG 
needs to be of one of two different types at runtime.  How would 
I do something like the following:

```d
auto virtualG;  // <-- probably invalid code, illustrating the 
idea
if(runtime_condition)
    virtualG = operatorG1;
else
    virtualG = operatorG2;

sourceRange
   .operatorA
   .operatorB
   .operatorC
   .operatorD
   .operatorE
   .operatorF
   .virtualG
   .operatorH
   .copy(destination);
```
?

I've tried various usages of `range.InputRangeObject` but haven't 
been able to get the syntax right.  Any suggestions on the best 
way to proceed?  Maybe the whole chain should be wrapped in 
InputRangeObject classes, I don't know.

Thanks,
Feb 17 2023
next sibling parent reply "H. S. Teoh" <hsteoh qfbox.info> writes:
On Fri, Feb 17, 2023 at 05:30:40PM +0000, Chris Piker via Digitalmars-d-learn
wrote:
[...]
 In order to handle new functionality it turns out that operatorG needs
 to be of one of two different types at runtime.  How would I do
 something like the following:
 
 ```d
 auto virtualG;  // <-- probably invalid code, illustrating the idea
 if(runtime_condition)
    virtualG = operatorG1;
 else
    virtualG = operatorG2;
[...]
 ```
 ?
 
 I've tried various usages of `range.InputRangeObject` but haven't been
 able to get the syntax right.  Any suggestions on the best way to
 proceed?  Maybe the whole chain should be wrapped in InputRangeObject
 classes, I don't know.
[...] Here's an actual function taken from my own code, that returns a different range type depending on a runtime condition, maybe this will help you? ```d /** * Expands ' '-directives in a range of strings. * * Returns: A range of strings with lines that begin with ' ' * substituted with the contents of the file named by the rest of the * line. */ auto expandFileDirectives(File = std.stdio.File, R)(R args) if (isInputRange!R && is(ElementType!R : const(char)[])) { import std.algorithm.iteration : joiner, map; import std.algorithm.searching : startsWith; import std.range : only; import std.range.interfaces : InputRange, inputRangeObject; import std.typecons : No; return args.map!(arg => arg.startsWith(' ') ? cast(InputRange!string) inputRangeObject( File(arg[1 .. $]).byLineCopy(No.keepTerminator)) : cast(InputRange!string) inputRangeObject(only(arg))) .joiner; } ``` Note that the cast is to a common base class of the two different subclasses returned by inputRangeObject(). This function is used in the rest of the code as part of a UFCS chain of ranges. T -- Long, long ago, the ancient Chinese invented a device that lets them see through walls. It was called the "window".
Feb 17 2023
parent Chris Piker <chris hoopjump.com> writes:
On Friday, 17 February 2023 at 17:44:20 UTC, H. S. Teoh wrote:
 Here's an actual function taken from my own code, that returns 
 a different range type depending on a runtime condition, maybe 
 this will help you?
Thanks, this was helpful. I keep forgetting to expand my horizons on what can be returned from an auto function. I'm still unlearning C & Java. Cheers,
Feb 17 2023
prev sibling parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 2/17/23 09:30, Chris Piker wrote:

 operatorG needs
 to be of one of two different types at runtime
std.range.choose may be useful but I think it requires creating two variables like g1 and g2 below: import std.range; import std.algorithm; void main(string[] args) { const condition = (args.length > 1); // The first part of the algorithm auto r = iota(10) .filter!(n => n % 2); // Two different steps auto g1 = r.map!((int n) => n * n); auto g2 = r.map!((int n) => n * 10); // The rest of the algoritm auto result = choose(condition, g1, g2) .array; } Ali
Feb 17 2023
parent Chris Piker <chris hoopjump.com> writes:
On Friday, 17 February 2023 at 17:42:19 UTC, Ali Çehreli wrote:
     // Two different steps
     auto g1 = r.map!((int n) => n * n);
     auto g2 = r.map!((int n) => n * 10);

     // The rest of the algoritm
     auto result = choose(condition, g1, g2)
                   .array;
Now that's a handy construct. There's many little goodies in phobos I've yet to learn, thanks for the tip!
Feb 17 2023