www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - A pass() identity range?

reply "bearophile" <bearophileHUGS lycos.com> writes:
I sometimes write code like:

auto data = File("data.txt")
             .byLine()
             .map!(r => r.strip().dup)()
             .filter!(r => !r.empty)()
             .array();


To help writing/improving/debugging such code maybe it's useful 
to create a pass() range in Phobos. It's like a "identity range" 
that just passes its inputs to its output, but also runs a given 
lambda to the items that pass through it (the lambda receives a 
const item, to avoid modifications of the data passing through 
the chain):


auto data = File("data.txt")
             .byLine()
             .pass(r => writeln("A: ", r))
             .map!(r => r.strip().dup)()
             .pass(r => writeln("B: ", r))
             .filter!(r => !r.empty)()
             .array();


This usage of pass() allows to introduce debug prints inside very 
long chains of such iterables, with no need to break them apart 
and assign the parts to temporary variables just to see what's 
going on in that chain.

But it's not hard to do it with a not pure map:

                 .map!((r){ writeln("B: ", r); return r; })()

Or even with an evil comma operator:

                 .map!(r => (writeln("B: ", r), r))()

So I don't know how much useful that pass() is.

Bye,
bearophile
Dec 22 2012
next sibling parent "monarch_dodra" <monarchdodra gmail.com> writes:
On Saturday, 22 December 2012 at 08:55:35 UTC, bearophile wrote:
 I sometimes write code like:

 auto data = File("data.txt")
             .byLine()
             .map!(r => r.strip().dup)()
             .filter!(r => !r.empty)()
             .array();


 To help writing/improving/debugging such code maybe it's useful 
 to create a pass() range in Phobos. It's like a "identity 
 range" that just passes its inputs to its output, but also runs 
 a given lambda to the items that pass through it (the lambda 
 receives a const item, to avoid modifications of the data 
 passing through the chain):


 auto data = File("data.txt")
             .byLine()
             .pass(r => writeln("A: ", r))
             .map!(r => r.strip().dup)()
             .pass(r => writeln("B: ", r))
             .filter!(r => !r.empty)()
             .array();


 This usage of pass() allows to introduce debug prints inside 
 very long chains of such iterables, with no need to break them 
 apart and assign the parts to temporary variables just to see 
 what's going on in that chain.

 But it's not hard to do it with a not pure map:

                 .map!((r){ writeln("B: ", r); return r; })()

 Or even with an evil comma operator:

                 .map!(r => (writeln("B: ", r), r))()

 So I don't know how much useful that pass() is.

 Bye,
 bearophile
Bug reporting aside, it can be useful in the sense of *doing* something to each element, as opposed to "call a function and re-assign to original element". This would be especially true for say: Mutating functions that return void, or just plain calling member functions. I think it's a legit request. If anything, *map* could be re-implemented in terms of *call*.
Dec 22 2012
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
See also:

http://tech.blinemedical.com/debugging-piped-sequences-f/

Bye,
bearophile
Dec 22 2012
prev sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 12/22/2012 12:55 AM, bearophile wrote:

 To help writing/improving/debugging such code maybe it's useful to
 create a pass() range in Phobos.
I liked the idea yesterday but I thought that the name was a little off. How about a name like tap()? We tap into data as it's flowing through? Ali
Dec 22 2012
parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Saturday, 22 December 2012 at 21:21:21 UTC, Ali Çehreli wrote:
 On 12/22/2012 12:55 AM, bearophile wrote:

 To help writing/improving/debugging such code maybe it's
useful to
 create a pass() range in Phobos.
I liked the idea yesterday but I thought that the name was a little off.
Ditto.
 How about a name like tap()? We tap into data as it's flowing 
 through?
Niiice. I like it.
Dec 24 2012
parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Mon, Dec 24, 2012 at 02:35:29PM +0100, monarch_dodra wrote:
 On Saturday, 22 December 2012 at 21:21:21 UTC, Ali «ehreli wrote:
On 12/22/2012 12:55 AM, bearophile wrote:

 To help writing/improving/debugging such code maybe it's
 useful to create a pass() range in Phobos.
I liked the idea yesterday but I thought that the name was a little off.
Ditto.
How about a name like tap()? We tap into data as it's flowing
through?
Niiice. I like it.
This response is a year late ;-) but I thought tee() might be a better name. It has a precedent in the Unix tee command, which copies stdin into a file and also passes it along to stdout, quite similar to what is being done here (except that instead of a file it's a delegate/function). T -- To err is human; to forgive is not our policy. -- Samuel Adler
Jan 02 2013
parent reply "bearophile" <bearophileHUGS lycos.com> writes:
H. S. Teoh:

 This response is a year late ;-)
No problem.
 but I thought tee() might be a better name.
Python programmers have this "tee": http://docs.python.org/3/library/itertools.html#itertools.tee Bye, bearophile
Jan 02 2013
parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Wed, Jan 02, 2013 at 07:19:31PM +0100, bearophile wrote:
 H. S. Teoh:
[...]
but I thought tee() might be a better name.
Python programmers have this "tee": http://docs.python.org/3/library/itertools.html#itertools.tee
[...] Hmm. But isn't that just the same as repeatedly calling .save with D's forward ranges? T -- If you want to solve a problem, you need to address its root cause, not just its symptoms. Otherwise it's like treating cancer with Tylenol...
Jan 02 2013