digitalmars.D.learn - input range from stdin
- krzaq (4/4) Sep 17 2014 I'd like to have something similar to C++'s
- "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> (5/9) Sep 17 2014 import std.stdio;
- krzaq (6/16) Sep 17 2014 What happens if I later have some strings that I want to read
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (35/51) Sep 17 2014 The following worked:
- krzaq (19/77) Sep 18 2014 Thank you for your reply.
- "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> (7/16) Sep 18 2014 You should be able to use `std.algorithm.take` to read exactly 5
- krzaq (6/23) Sep 18 2014 Okay, I think I'll simply skip this for now.
- "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> (6/8) Sep 18 2014 Because (fixed-sized) arrays don't have a range interface (empty,
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (43/56) Sep 18 2014 And quietly ignored some of the things you were doing. :)
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (3/4) Sep 18 2014 And *I* quietly ignored
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
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
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: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/130e14c927f3I'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
On 09/17/2014 08:30 AM, krzaq wrote:On Wednesday, 17 September 2014 at 14:37:21 UTC, Marc Schütz wrote: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); AliOn Wednesday, 17 September 2014 at 12:44:00 UTC, krzaq wrote: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/130e14c927f3I'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
On Wednesday, 17 September 2014 at 18:05:36 UTC, Ali Çehreli wrote:On 09/17/2014 08:30 AM, krzaq wrote: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;On Wednesday, 17 September 2014 at 14:37:21 UTC, Marc Schütz wrote: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); AliOn Wednesday, 17 September 2014 at 12:44:00 UTC, krzaq wrote: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/130e14c927f3I'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 18 2014
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
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: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?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
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
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/ff42FoyKgqJK60smHere 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
On 09/18/2014 11:22 AM, Ali Çehreli wrote:And quietly ignoredAnd *I* quietly ignored Ali
Sep 18 2014