Re: Pass range to a function

2017-07-28 Thread Meta via Digitalmars-d-learn

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`. 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)));
}


Re: Pass range to a function

2017-07-28 Thread Seb via Digitalmars-d-learn

On Thursday, 27 July 2017 at 21:16:03 UTC, Chris wrote:
In C#, it'd be `IEnumerable`. 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


Re: Pass range to a function

2017-07-27 Thread Ali Çehreli via Digitalmars-d-learn

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



Pass range to a function

2017-07-27 Thread Chris via Digitalmars-d-learn
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`. 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);
}
```