www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - input range from stdin

reply "krzaq" <dlangmailinglist krzaq.cc> writes:
I'd like to have something similar to C++'s 
std::istream_iterator<int>(std::cin)

Is it possible? I'm relatively indifferent to efficiency of the 
solution.
Sep 17 2014
parent reply "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Wednesday, 17 September 2014 at 12:44:00 UTC, krzaq wrote:
 I'd like to have something similar to C++'s 
 std::istream_iterator<int>(std::cin)

 Is it possible? I'm relatively indifferent to efficiency of the 
 solution.
import std.stdio; import std.algorithm; import std.conv; writeln(stdin.byLine.map!(to!int));
Sep 17 2014
parent reply "krzaq" <dlangmailinglist krzaq.cc> writes:
On Wednesday, 17 September 2014 at 14:37:21 UTC, Marc Schütz 
wrote:
 On Wednesday, 17 September 2014 at 12:44:00 UTC, krzaq wrote:
 I'd like to have something similar to C++'s 
 std::istream_iterator<int>(std::cin)

 Is it possible? I'm relatively indifferent to efficiency of 
 the solution.
import std.stdio; import std.algorithm; import std.conv; writeln(stdin.byLine.map!(to!int));
What happens if I later have some strings that I want to read from the same line? How can I use the resultant range with std.fill? My idea doesn't seem to work: http://dpaste.dzfl.pl/130e14c927f3
Sep 17 2014
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 09/17/2014 08:30 AM, krzaq wrote:
 On Wednesday, 17 September 2014 at 14:37:21 UTC, Marc Schütz wrote:
 On Wednesday, 17 September 2014 at 12:44:00 UTC, krzaq wrote:
 I'd like to have something similar to C++'s
 std::istream_iterator<int>(std::cin)

 Is it possible? I'm relatively indifferent to efficiency of the
 solution.
import std.stdio; import std.algorithm; import std.conv; writeln(stdin.byLine.map!(to!int));
What happens if I later have some strings that I want to read from the same line? How can I use the resultant range with std.fill? My idea doesn't seem to work: http://dpaste.dzfl.pl/130e14c927f3
The following worked: import std.stdio; import std.format; import std.exception; import std.string; import std.algorithm; struct Data { int i; string s; } Data toData(char[] line) { int i; string s; auto slice = line; const items = formattedRead(line, " %s %s", &i, &s); enforce (items == 2, format("Incomplete line: %s", slice)); return Data(i, s); } void main() { auto data = stdin.byLine.map!toData; writeln(data); } I could not get it work with fill because fill requires specific types of ranges, which neither the destination nor the source were. For example, I wanted to use std.array.Appender but fill wants an InputRange. Also, the source is not a ForwardRange because it is consuming from stdin. However, it is easy to make an array with std.array.array: import std.array; writeln(data.array); Ali
Sep 17 2014
parent reply "krzaq" <dlangmailinglist krzaq.cc> writes:
On Wednesday, 17 September 2014 at 18:05:36 UTC, Ali Çehreli 
wrote:
 On 09/17/2014 08:30 AM, krzaq wrote:
 On Wednesday, 17 September 2014 at 14:37:21 UTC, Marc Schütz 
 wrote:
 On Wednesday, 17 September 2014 at 12:44:00 UTC, krzaq wrote:
 I'd like to have something similar to C++'s
 std::istream_iterator<int>(std::cin)

 Is it possible? I'm relatively indifferent to efficiency of 
 the
 solution.
import std.stdio; import std.algorithm; import std.conv; writeln(stdin.byLine.map!(to!int));
What happens if I later have some strings that I want to read from the same line? How can I use the resultant range with std.fill? My idea doesn't seem to work: http://dpaste.dzfl.pl/130e14c927f3
The following worked: import std.stdio; import std.format; import std.exception; import std.string; import std.algorithm; struct Data { int i; string s; } Data toData(char[] line) { int i; string s; auto slice = line; const items = formattedRead(line, " %s %s", &i, &s); enforce (items == 2, format("Incomplete line: %s", slice)); return Data(i, s); } void main() { auto data = stdin.byLine.map!toData; writeln(data); } I could not get it work with fill because fill requires specific types of ranges, which neither the destination nor the source were. For example, I wanted to use std.array.Appender but fill wants an InputRange. Also, the source is not a ForwardRange because it is consuming from stdin. However, it is easy to make an array with std.array.array: import std.array; writeln(data.array); Ali
Thank you for your reply. That's not what I wanted. Maybe I should explain instead of expecting you to divine my intentions, though :) I am trying to rewrite the following program in D--making it more elegant: http://melpon.org/wandbox/permlink/ff42FoyKgqJK60sm As you can see, I can have one input line consisting of n words and then n integers and I can read from it easily. My question whether stdin.byLine allows me to do this remains unanswered (or I failed to understand the answer), although I am not hopeful. As to std.fill: I find myself surprised. Any idea why the input range is considered incorrect? In any case, should integers[0..$].fill(...) not make it correct, at least in regards to the first argument? Docs have an example with int[] I expected my D code to look more or less like the following: words.fill(stdin.by!string); integers.fill(stdin.by!int); zip(integers,words).map!(p => p[1][p[0]]).join.writeln;
Sep 18 2014
next sibling parent reply "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Thursday, 18 September 2014 at 09:21:17 UTC, krzaq wrote:
 That's not what I wanted. Maybe I should explain instead of 
 expecting you to divine my intentions, though :) I am trying to 
 rewrite the following program in D--making it more elegant: 
 http://melpon.org/wandbox/permlink/ff42FoyKgqJK60sm

 As you can see, I can have one input line consisting of n words 
 and then n integers and I can read from it easily. My question 
 whether stdin.byLine allows me to do this remains unanswered 
 (or I failed to understand the answer), although I am not 
 hopeful.
You should be able to use `std.algorithm.take` to read exactly 5 integers. However, in order to read up to the first empty line, for example, the input would have to be a forward range (= "rewindable"), which stdin.byLine of course is not. Maybe you could constructor a wrapper range that caches input lines as necessary.
Sep 18 2014
parent reply "krzaq" <dlangmailinglist krzaq.cc> writes:
On Thursday, 18 September 2014 at 11:13:36 UTC, Marc Schütz wrote:
 On Thursday, 18 September 2014 at 09:21:17 UTC, krzaq wrote:
 That's not what I wanted. Maybe I should explain instead of 
 expecting you to divine my intentions, though :) I am trying 
 to rewrite the following program in D--making it more elegant: 
 http://melpon.org/wandbox/permlink/ff42FoyKgqJK60sm

 As you can see, I can have one input line consisting of n 
 words and then n integers and I can read from it easily. My 
 question whether stdin.byLine allows me to do this remains 
 unanswered (or I failed to understand the answer), although I 
 am not hopeful.
You should be able to use `std.algorithm.take` to read exactly 5 integers. However, in order to read up to the first empty line, for example, the input would have to be a forward range (= "rewindable"), which stdin.byLine of course is not. Maybe you could constructor a wrapper range that caches input lines as necessary.
Okay, I think I'll simply skip this for now. I hoped that there would be a way of reading stdin composable with std.algorithms, as is the case in C++. I guess this works for now http://dpaste.dzfl.pl/6801615160e3 I have a follow-up question: why does zip not accept an array?
Sep 18 2014
parent "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Thursday, 18 September 2014 at 13:10:06 UTC, krzaq wrote:
 I guess this works for now http://dpaste.dzfl.pl/6801615160e3

 I have a follow-up question: why does zip not accept an array?
Because (fixed-sized) arrays don't have a range interface (empty, front & popFront()), in particular, popFront cannot be used on them. That's why a slice is needed. Btw, you can just write `array_name[]` without `0 .. $` to get a slice of the entire array.
Sep 18 2014
prev sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 09/18/2014 02:21 AM, krzaq wrote:

 That's not what I wanted. Maybe I should explain instead of expecting
 you to divine my intentions, though :)
And quietly ignored some of the things you were doing. :) For example, I did not think it was necessary to fill an existing array when the range object can produce the objects one by one lazily. If an actual array is needed, it is as simple as calling .array on the range. An if the destination already exists, the array-wise operations can fill it anyway. So, actually fill is not needed in the original case: import std.array; import std.range; Data[5] existingArray; existingArray = data.takeExactly(5).array;
 I am trying to rewrite the
 following program in D--making it more elegant:
 http://melpon.org/wandbox/permlink/ff42FoyKgqJK60sm
Here is my attempt: import std.stdio; import std.algorithm; import std.range; import std.conv; auto secretWord(R)(R line) { auto tokens = line.splitter; auto words = tokens .takeExactly(5); // Question: Why do I need this? tokens.popFrontN(words.length); auto integers = tokens .takeExactly(words.length) .map!(to!size_t); return zip(words, integers).map!(t => t[0][t[1]]); } unittest { assert(secretWord("cheap energy can cause problems 4 2 1 0 5") .equal("peace")); } void main() { writeln(stdin.byLine.map!secretWord); }
 As you can see, I can have one input line consisting of n words and then
 n integers and I can read from it easily. My question whether
 stdin.byLine allows me to do this remains unanswered (or I failed to
 understand the answer), although I am not hopeful.
byLine's purpose is to present the input line by line. Parsing the line should be the responsibility of something else. However, you are right that we don't have a generic formetted range reader yet. There has been a number of talks about it but nobody has completed it yet.
 I expected my D code to look more or less like the following:

 words.fill(stdin.by!string);
 integers.fill(stdin.by!int);
 zip(integers,words).map!(p => p[1][p[0]]).join.writeln;
I wrote my code without looking yours. :) Ali
Sep 18 2014
parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 09/18/2014 11:22 AM, Ali Çehreli wrote:

 And quietly ignored
And *I* quietly ignored Ali
Sep 18 2014