Thread overview | ||||||
---|---|---|---|---|---|---|
|
July 27, 2017 Pass range to a function | ||||
---|---|---|---|---|
| ||||
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); } ``` |
July 27, 2017 Re: Pass range to a function | ||||
---|---|---|---|---|
| ||||
Posted in reply to Chris | 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 |
July 28, 2017 Re: Pass range to a function | ||||
---|---|---|---|---|
| ||||
Posted in reply to Chris | 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 |
July 29, 2017 Re: Pass range to a function | ||||
---|---|---|---|---|
| ||||
Posted in reply to Chris | 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))); } |
Copyright © 1999-2021 by the D Language Foundation