On Thursday, 3 September 2015 at 23:54:44 UTC, H. S. Teoh wrote:
On Thu, Sep 03, 2015 at 11:38:54PM +0000, Namal via
Digitalmars-d-learn wrote:
On Thursday, 3 September 2015 at 23:31:27 UTC, Jordan Wilson
wrote:
>On Thursday, 3 September 2015 at 23:28:37 UTC, Namal wrote:
>>On Thursday, 3 September 2015 at 23:25:52 UTC, Jordan Wilson
>>wrote:
>>>And also:
>>>import std.algorithm
>>>
>>>Sorry, I should have taken the time to answer properly and
>>>fully.
>>
>>import std.file, std.stdio, std.string, std.conv,
>>std.algorithm;
>>
>>void main(){
>>
>> auto file = File("text.txt");
>> auto numbers = file.byLine()
>> .map!(a => a.split)
>> .map!(a => map!(a => to!int(a))(a))
>> .array();
>>
>> writeln(numbers);
>>}
>>
>>Error: no property 'array' for type 'MapResult!(__lambda2,
>>MapResult!(__lambda1, ByLine!(char, char)))'
>>
>>Still an error.
>
>import std.array
Thx, finaly, this is so much harder to understand than c++
iostream
I would have written it slightly differently, to emphasize what
exactly is going on:
auto numbers = File("text.txt") // read file
.byLine() // line by line
.map!(a => a.split // split each line into words
.map!(a => to!int(a)) // convert each word into int
.array) // collect the ints into an array (per
line)
.array; // collect all line arrays into one big
array
This is the functional way of doing it, of course. If you're
more comfortable with the C++-style imperative approach, you
could do this instead:
auto file = File("text.txt");
int[][] numbers;
foreach (line; file.byLine) {
auto words = line.split;
int[] lineNums;
foreach (word; words) {
lineNums ~= word.to!int;
}
numbers ~= lineNums;
}
The functional approach is admittedly a bit harder to
understand at first, but it's extremely powerful because it
processes everything in a pipeline, and you can compose
operators on the pipeline easily, rearrange the sequence of
operations, etc..
In the imperative nested-loop approach, things quickly get out
of hand once the loop is nested about 2-3 levels deep. A nested
loop of 6-7 levels deep would be basically impossible to
understand, maintain, or debug without major refactoring into
smaller functions. (In fact, split() is a library-provided
function that basically encapsulates one of those nested
loops.) But if you take the refactoring to its logical
conclusion, you'll eventually end up with a whole bunch of tiny
functions with only a single loop each, each calling the next
function in a chain -- in other words, you arrive at the
functional pipeline approach. :-)
D allows you to do it either way, but the superior approach IMO
is to learn the functional pipeline approach.
T
Thx Theo, this and the lack of foolproof tutorials were the
reason why I gave up on D 2 years ago and went instead to C++.
But I am not giving up this time. That being said, when do I have
to import std.array and std.string? Every time I use std.array? I
can obviously use arrays and strings without those libs.