www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - optional process

reply Taylor R Hillegeist <taylorh140 gmail.com> writes:
When using the standard library. and making command-line 
applications I find myself wanting optional processes in line. 
for me, this typically makes the following structure.

bool sortOutput;

if(sortOutput){
read(Textfile)
    .splitter("\n")
    .filter(a=>a.contains("data))
    .sort!("a < b").writeln();

}else{

read(Textfile)
    .splitter("\n")
    .filter(a=>a.contains("data))
    .writeln();
}

I know phobos has choose which is close.
But what I want is something like:

bool sortOutput;

if(sortOutput){
read(Textfile)
    .splitter("\n")
    .filter(a=>a.contains("data))
    .doif(sortOutput,sort!("a < b"))
    .writeln();
Nov 29 2019
parent reply Paul Backus <snarwin gmail.com> writes:
On Friday, 29 November 2019 at 15:17:35 UTC, Taylor R Hillegeist 
wrote:
 I know phobos has choose which is close.
 But what I want is something like:

 bool sortOutput;

 if(sortOutput){
 read(Textfile)
    .splitter("\n")
    .filter(a=>a.contains("data))
    .doif(sortOutput,sort!("a < b"))
    .writeln();
import std.functional: pipe; bool sortOutput; read(Textfile) .splitter("\n") .filter!(a=>a.contains("data)) .pipe!((output) { if (sortOutput) return output.sort!("a < b"); else return output; }) .writeln(); // maybe you meant each!writeln ?
Nov 29 2019
next sibling parent Taylor R Hillegeist <taylorh140 gmail.com> writes:
On Friday, 29 November 2019 at 15:24:31 UTC, Paul Backus wrote:
 On Friday, 29 November 2019 at 15:17:35 UTC, Taylor R 
 Hillegeist wrote:
 I know phobos has choose which is close.
 But what I want is something like:

 bool sortOutput;

 if(sortOutput){
 read(Textfile)
    .splitter("\n")
    .filter(a=>a.contains("data))
    .doif(sortOutput,sort!("a < b"))
    .writeln();
import std.functional: pipe; bool sortOutput; read(Textfile) .splitter("\n") .filter!(a=>a.contains("data)) .pipe!((output) { if (sortOutput) return output.sort!("a < b"); else return output; }) .writeln(); // maybe you meant each!writeln ?
That is actually exactly the kind of thing I was looking for. (it gets the job done without repeats) I would still like it to be in the first form though e.g. doif. it would keep the code cleaner. Thank you for this. (also yes I just made up the example so .each!writeln is appropriate it would be surprising to me if that was the only error)
Nov 29 2019
prev sibling parent reply Taylor Hillegeist <taylorh140 gmail.com> writes:
On Friday, 29 November 2019 at 15:24:31 UTC, Paul Backus wrote:

    .pipe!((output) {
       if (sortOutput)
          return output.sort!("a < b");
       else
          return output;
    })
    .writeln(); // maybe you meant each!writeln ?
Why pipe as apposed to compose? Pipes functions in sequence. It offers the same functionality as compose, but with functions specified in reverse order. This may lead to more readable code in some situation because the order of execution is the same as lexical order. How does this not reverse the range?
Dec 05 2019
parent reply Paul Backus <snarwin gmail.com> writes:
On Thursday, 5 December 2019 at 15:30:52 UTC, Taylor Hillegeist 
wrote:
 On Friday, 29 November 2019 at 15:24:31 UTC, Paul Backus wrote:

    .pipe!((output) {
       if (sortOutput)
          return output.sort!("a < b");
       else
          return output;
    })
    .writeln(); // maybe you meant each!writeln ?
Why pipe as apposed to compose? Pipes functions in sequence. It offers the same functionality as compose, but with functions specified in reverse order. This may lead to more readable code in some situation because the order of execution is the same as lexical order. How does this not reverse the range?
range .pipe!someFunction .each!writeln; is the same as range .someFunction .each!writeln; So why use pipe? Because in this case, the function we want to apply is a lambda, and you can't call lambdas with UFCS.
Dec 05 2019
parent reply Taylor Hillegeist <taylorh140 gmail.com> writes:
On Thursday, 5 December 2019 at 15:43:30 UTC, Paul Backus wrote:
 On Thursday, 5 December 2019 at 15:30:52 UTC, Taylor Hillegeist 
 wrote:
 On Friday, 29 November 2019 at 15:24:31 UTC, Paul Backus wrote:

    .pipe!((output) {
       if (sortOutput)
          return output.sort!("a < b");
       else
          return output;
    })
    .writeln(); // maybe you meant each!writeln ?
range .someFunction .each!writeln; So why use pipe? Because in this case, the function we want to apply is a lambda, and you can't call lambdas with UFCS.
I agree with this. I wasn't clear enough in my question though. I was trying to distinguish between std.functional.compose and std.functional.pipe they look very the same. Pipe says it reverses functions order. Which makes no sense to me.
Dec 05 2019
parent reply Paul Backus <snarwin gmail.com> writes:
On Thursday, 5 December 2019 at 17:27:45 UTC, Taylor Hillegeist 
wrote:
 I agree with this.

 I wasn't clear enough in my question though.
 I was trying to distinguish between std.functional.compose and 
 std.functional.pipe
 they look very the same. Pipe says it reverses functions order. 
 Which makes no sense to me.
input.pipe!(f, g, h) == input.f.g.h == h(g(f(input))) input.compose!(f, g, h) == input.h.g.f == f(g(h(input)))
Dec 05 2019
parent Taylor Hillegeist <taylorh140 gmail.com> writes:
On Friday, 6 December 2019 at 05:09:58 UTC, Paul Backus wrote:
 On Thursday, 5 December 2019 at 17:27:45 UTC, Taylor Hillegeist 
 wrote:
 I agree with this.

 I wasn't clear enough in my question though.
 I was trying to distinguish between std.functional.compose and 
 std.functional.pipe
 they look very the same. Pipe says it reverses functions 
 order. Which makes no sense to me.
input.pipe!(f, g, h) == input.f.g.h == h(g(f(input))) input.compose!(f, g, h) == input.h.g.f == f(g(h(input)))
This is surprisingly clear. I guess I never thought to put multiple functions into pipe that way. It also makes sense why pipe would be the default choice. Thank you, Paul, for the great answer.
Dec 05 2019