Thread overview | |||||||
---|---|---|---|---|---|---|---|
|
December 05, 2014 std.algorithm.map with side-effects | ||||
---|---|---|---|---|
| ||||
Here's a little experiment I was trying out earlier today in order to try and convert foreach-style code to using UFCS of ranges: ////////////////////////////////////////////// import std.algorithm, std.range, std.stdio; void main() { size_t s = 0; void essify(size_t n) { writeln("n = ", n); ++s; } auto filteredRange = iota(0, 10).filter!(a => (a % 2)); filteredRange.map!(a => essify(a)); writeln(s); foreach (n; filteredRange) { essify(n); } writeln(s); } ////////////////////////////////////////////// I'd assumed the two uses of filteredRange would produce equivalent results, but in fact the transformation using map does nothing -- the writeln statement inside the essify() function never gets triggered, suggesting the function body is never executed. Can anyone advise why, and whether there's a nice range iteration option to ensure that this function gets called using each element of the filteredRange? |
December 05, 2014 Re: std.algorithm.map with side-effects | ||||
---|---|---|---|---|
| ||||
Posted in reply to Joseph Rushton Wakeling | Joseph Rushton Wakeling: > Can anyone advise why, map is lazy, like most other ranges. > and whether there's a nice range iteration option to ensure that this function gets called using each element of the filteredRange? Lazy higher order functions like map/filter should be used only with pure functions. There are bugs/troubles in using them on impure code. There was a proposal for a "each" function to terminate a range chain with something effectful, but I think it has gone nowhere. This means you have to use a foreach on a range. Bye, bearophile |
December 06, 2014 Re: std.algorithm.map with side-effects | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | On 06/12/14 00:58, bearophile via Digitalmars-d-learn wrote: > Joseph Rushton Wakeling: > >> Can anyone advise why, > > map is lazy, like most other ranges. Ah, I see. That function would only be called on consumption of the results of the map. > Lazy higher order functions like map/filter should be used only with pure > functions. There are bugs/troubles in using them on impure code. Yes, I did wonder about that. I'll post up the actual code tomorrow -- I was having some fun playing with one of the metrics in my Dgraph library and trying to see to what extent I could simplify it (reading-wise) with a range-based approach. > There was a proposal for a "each" function to terminate a range chain with > something effectful, but I think it has gone nowhere. This means you have to use > a foreach on a range. Yes, I remember you requesting that. Were there ever any PRs, or was it just spec? |
December 06, 2014 Re: std.algorithm.map with side-effects | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | map won't actually compute anything until you start asking for individual elements with front, back, or opIndex. Personally I like to use something like ref transform (alias action, R, T...)(ref R range, T addl_args) { range = action (range, addl_args); return range; } to do mutation in the middle of UFCS chains. Its more flexible and more obvious than an impure map. range.callchain.array.transform!(x => x.map!whatever).filter.etc |
December 06, 2014 Re: std.algorithm.map with side-effects | ||||
---|---|---|---|---|
| ||||
Posted in reply to Joseph Rushton Wakeling | Joseph Rushton Wakeling: > Yes, I remember you requesting that. Were there ever any PRs, or was it just spec? I think two different persons implemented something like "each". A similar function is used very commonly in F#, where it's named "iter": http://msdn.microsoft.com/en-us/library/ee340469.aspx Bye, bearophile |
Copyright © 1999-2021 by the D Language Foundation