www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Pass range to a function

reply Chris <christophilus hotmail.com> writes:
I'm using regex `matchAll`, and mapping it to get a sequence of 
strings. I then want to pass that sequence to a function. What is 
the general "sequence of strings" type declaration I'd need to 
use?

In C#, it'd be `IEnumerable<string>`. I'd rather not do a 
to-array on the sequence, if possible. (e.g. It'd be nice to just 
pass the lazy sequence into my categorize function.)

What is the value of `???` in the following program:


```
import std.stdio, std.regex, std.string, std.algorithm.iteration;

auto regexToStrSeq(RegexMatch!string toks) {
   return toks.map!(t => t[0].strip());
}

void categorize(??? toks) {
   foreach (t; toks) {
     writeln(t);
   }
}

void main()
{
     auto reg = 
regex("[\\s,]*(~ |[\\[\\]{\\}()'`~^ ]|\"(?:\\\\.|[^\\\\\"])*\"|;.*|[^\\s\\[\\]{}('\"`,;)]*)");
     auto line = "(+ 1 (* 2 32))";
     auto baz = matchAll(line, reg);

     categorize(regexToStrSeq(baz).array);
}
```
Jul 27
next sibling parent =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 07/27/2017 02:16 PM, Chris wrote:

 What is the value of `???` in the following program:
 void categorize(??? toks) {
   foreach (t; toks) {
     writeln(t);
   }
 }
The easiest solution is to make it a template (R is a suitable template variable name for a range type): void categorize(R)(R toks) { foreach (t; toks) { writeln(t); } } Your function will work with any type that can be iterated with foreach and can be passed to writeln. However, you can use template constraints to limit its usage, document its usage, or produce better compilation errors when it's called with an incompatible type (the error message would point at the call site as opposed to the body of categorize): import std.range; import std.traits; void categorize(R)(R toks) if (isInputRange!R && isSomeString!(ElementType!R)) { foreach (t; toks) { writeln(t); } } Ali
Jul 27
prev sibling next sibling parent Seb <seb wilzba.ch> writes:
On Thursday, 27 July 2017 at 21:16:03 UTC, Chris wrote:
 In C#, it'd be `IEnumerable<string>`. I'd rather not do a 
 to-array on the sequence, if possible. (e.g. It'd be nice to 
 just pass the lazy sequence into my categorize function.)
This comparison between Linq and D ranges might help you in the future too: https://github.com/wilzbach/linq
Jul 28
prev sibling parent Meta <jared771 gmail.com> writes:
On Thursday, 27 July 2017 at 21:16:03 UTC, Chris wrote:
 I'm using regex `matchAll`, and mapping it to get a sequence of 
 strings. I then want to pass that sequence to a function. What 
 is the general "sequence of strings" type declaration I'd need 
 to use?

 In C#, it'd be `IEnumerable<string>`. I'd rather not do a 
 to-array on the sequence, if possible. (e.g. It'd be nice to 
 just pass the lazy sequence into my categorize function.)

 What is the value of `???` in the following program:


 ```
 import std.stdio, std.regex, std.string, 
 std.algorithm.iteration;

 auto regexToStrSeq(RegexMatch!string toks) {
   return toks.map!(t => t[0].strip());
 }

 void categorize(??? toks) {
   foreach (t; toks) {
     writeln(t);
   }
 }

 void main()
 {
     auto reg = 
 regex("[\\s,]*(~ |[\\[\\]{\\}()'`~^ ]|\"(?:\\\\.|[^\\\\\"])*\"|;.*|[^\\s\\[\\]{}('\"`,;)]*)");
     auto line = "(+ 1 (* 2 32))";
     auto baz = matchAll(line, reg);

     categorize(regexToStrSeq(baz).array);
 }
 ```
If for some reason you can't make categorize a template like Ali suggested, or you need runtime polymorphism, you can use std.range.interfaces: import std.range.interfaces; void categorize(InputRange!string toks) { foreach (t; toks) { writeln(t); } } void main() { //etc. categorize(inputRangeObject(regexToStrSeq(baz))); }
Jul 28