Re: Output range and writeln style functions

2017-01-23 Thread Jon Degenhardt via Digitalmars-d-learn

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



Re: Output range and writeln style functions

2017-01-23 Thread Ali Çehreli via Digitalmars-d-learn

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



Re: Output range and writeln style functions

2017-01-23 Thread Jon Degenhardt via Digitalmars-d-learn

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


Re: Output range and writeln style functions

2017-01-23 Thread Ali Çehreli via Digitalmars-d-learn

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