www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Output range and writeln style functions

reply Jon Degenhardt <jond noreply.com> writes:
I've been increasingly using output ranges in my code (the 
"component programming" model described in several articles on 
the D site). It works very well, except that it would often be 
more convenient to use writeln style functions rather than 'put'. 
Especially when you start by drafting a sketch of code using 
writeln functions, then convert it an output range.

Seems an obvious thing, I'm wondering if I missed something. Are 
there ways to use writeln style functions with output ranges?

--Jon
Jan 22
parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 01/22/2017 01:54 PM, Jon Degenhardt wrote:
 I've been increasingly using output ranges in my code (the "component
 programming" model described in several articles on the D site). It
 works very well, except that it would often be more convenient to use
 writeln style functions rather than 'put'. Especially when you start by
 drafting a sketch of code using writeln functions, then convert it an
 output range.

 Seems an obvious thing, I'm wondering if I missed something. Are there
 ways to use writeln style functions with output ranges?

 --Jon
I don't think I understand the question. :) If you need a variadic put(), then I've come up with the following mildly tested AllAppender. Just as a reminder, I've also used std.range.tee that allows tapping into the stream to see what's flying through: import std.array : Appender, appender; import std.stdio : writeln; struct AllAppender(T) { Appender!T app; alias app this; void put(Args...)(Args args) { foreach (arg; args) { static if (__traits(compiles, app.put(arg))) { app.put(arg); } else { import std.conv : to; app.put(arg.to!T); } } } } import std.range : isOutputRange; static assert(isOutputRange!(AllAppender!string, int)); static assert(isOutputRange!(AllAppender!string, double)); auto allAppender(T)() { return AllAppender!T(); } void main() { auto a = allAppender!string(); a.put(1, "hello"); import std.range : tee; import std.algorithm : copy; [ 10, 20, 30 ] .tee!(e => writeln("appending ", e)) .copy(a); writeln(a.data); } Ali
Jan 23
parent reply Jon Degenhardt <jond noreply.com> writes:
On Monday, 23 January 2017 at 08:03:14 UTC, Ali Çehreli wrote:
 On 01/22/2017 01:54 PM, Jon Degenhardt wrote:
 I've been increasingly using output ranges in my code (the 
 "component
 programming" model described in several articles on the D 
 site). It
 works very well, except that it would often be more convenient 
 to use
 writeln style functions rather than 'put'. Especially when you 
 start by
 drafting a sketch of code using writeln functions, then 
 convert it an
 output range.

 Seems an obvious thing, I'm wondering if I missed something. 
 Are there
 ways to use writeln style functions with output ranges?

 --Jon
I don't think I understand the question. :) If you need a variadic put(), then I've come up with the following mildly tested AllAppender. Just as a reminder, I've also used std.range.tee that allows tapping into the stream to see what's flying through: [snip] Ali
So I guess the is answer is "no" :) It's mainly about consistency of the output primitives. Includes variadic args, formatting, and names of the primitives. I keep finding myself starting with something like: void writeLuckyNumber(string name, int luckyNumber) { writefln("Hello %s, your lucky number is %d", name, luckyNumber); } and then re-factoring it as: void writeLuckyNumber(OutputRange) (OutputRange outputStream, string name, int luckyNumber) if (isOutputRange!(OutputRange, char)) { import std.format; outputStream.put( format("Hello %s, your lucky number is %d\n", name, luckyNumber)); } Not bad, but the actual output statements are a bit harder to read, especially if people reading your code are not familiar with output ranges. So, what I'm really wondering is if there is built-in way to get closer to: outputStream.writefln(...); that I've overlooked. --Jon
Jan 23
parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 01/23/2017 12:48 PM, Jon Degenhardt wrote:
 On Monday, 23 January 2017 at 08:03:14 UTC, Ali Çehreli wrote:
 On 01/22/2017 01:54 PM, Jon Degenhardt wrote:
 I've been increasingly using output ranges in my code (the "component
 programming" model described in several articles on the D site). It
 works very well, except that it would often be more convenient to use
 writeln style functions rather than 'put'. Especially when you start by
 drafting a sketch of code using writeln functions, then convert it an
 output range.

 Seems an obvious thing, I'm wondering if I missed something. Are there
 ways to use writeln style functions with output ranges?

 --Jon
I don't think I understand the question. :) If you need a variadic put(), then I've come up with the following mildly tested AllAppender. Just as a reminder, I've also used std.range.tee that allows tapping into the stream to see what's flying through: [snip] Ali
So I guess the is answer is "no" :) It's mainly about consistency of the output primitives. Includes variadic args, formatting, and names of the primitives. I keep finding myself starting with something like: void writeLuckyNumber(string name, int luckyNumber) { writefln("Hello %s, your lucky number is %d", name, luckyNumber); } and then re-factoring it as: void writeLuckyNumber(OutputRange) (OutputRange outputStream, string name, int luckyNumber) if (isOutputRange!(OutputRange, char)) { import std.format; outputStream.put( format("Hello %s, your lucky number is %d\n", name, luckyNumber)); } Not bad, but the actual output statements are a bit harder to read, especially if people reading your code are not familiar with output ranges. So, what I'm really wondering is if there is built-in way to get closer to: outputStream.writefln(...); that I've overlooked. --Jon
If it's about formatted output then perhaps formattedWrite? https://dlang.org/phobos/std_format.html#.formattedWrite The same function is used with stdout and an Appender: import std.stdio; import std.range; void writeLuckyNumber(OutputRange) (OutputRange outputStream, string name, int luckyNumber) if (isOutputRange!(OutputRange, char)) { import std.format : formattedWrite; formattedWrite(outputStream, "Hello %s, your lucky number is %d\n", name, luckyNumber); } void main() { writeLuckyNumber(stdout.lockingTextWriter, "Jon", 42); auto app = appender!string(); writeLuckyNumber(app, "Jon", 42); writeln(app.data); } Ali
Jan 23
parent Jon Degenhardt <jond noreply.com> writes:
On Monday, 23 January 2017 at 22:20:59 UTC, Ali Çehreli wrote:
 On 01/23/2017 12:48 PM, Jon Degenhardt wrote:
 [snip]
 So, what I'm really wondering is if there is built-in  way
  to get closer to:

       outputStream.writefln(...);
If it's about formatted output then perhaps formattedWrite? https://dlang.org/phobos/std_format.html#.formattedWrite The same function is used with stdout and an Appender: [snip] Ali
Oh, that is better, thanks! --Jon
Jan 23