On Wednesday, 24 June 2015 at 08:18:52 UTC, Stefan wrote:
I tried to refactor some existing code to use more of the functional patterns/style (map, filter, reduce, ..). The task is to read in some sort of a simple property file and present the result as an associative array.
My attempt is:

import std.stdio;
import std.algorithm.iteration : filter, map, reduce;
import std.algorithm.mutation : split;
import std.string : indexOf, strip;
import std.stdio : File, writeln;
import std.algorithm : startsWith;

string[string] add( ref string[string] result, in string line) {
    int assignmentIndex = indexOf( line, "=" );
    if ( assignmentIndex > 0 ) {
        string key = line[ 0 .. assignmentIndex ];
string value = line[ assignmentIndex + 1 .. line.length ];
        result[ key ] = value;
   }
   return result;
}


void main() {
   auto input = File( "test.ini", "r" );
   auto lines = input.byLine()
.filter!( line => !startsWith( line, "#" ) && !startsWith( line, "!") && line.length > 0 )
      .map!( line => strip( line ) );
   string[string] props;
   auto result = reduce!(add)( props, lines );
}

result should now contain the associative array.

However, it fails with an error in the "reduce" line:

c:\develop\dmd2.067.1\windows\bin\..\..\src\phobos\std\algorithm\iteration.d(2536): 
Error: static assert  "Incompatible function/seed/element: 
prop.add/string[string]/char[]"
c:\develop\dmd2.067.1\windows\bin\..\..\src\phobos\std\algorithm\iteration.d(2521):
        instantiated from here: reduceImpl!(false, MapResult!(__lambda2, 
FilterResult!(__lambda1, ByLine!(char, char))), string[string])
c:\develop\dmd2.067.1\windows\bin\..\..\src\phobos\std\algorithm\iteration.d(2505):
        instantiated from here: reducePreImpl!(MapResult!(__lambda2, 
FilterResult!(__lambda1, ByLine!(char, char))), string[string])
source\prop.d(30): instantiated from here: reduce!(string[string], MapResult!(__lambda2, FilterResult!(__lambda1, ByLine!(char, char))))

I have no idea how to resolve this.

input.byLine() yields char[]'s as range elements, while props is (correctly) indexed by strings, i.e. immutable(char)[]. Use .idup to create an immutable copy of the property name, e.g.:

   auto lines = input.byLine()
.filter!( line => !startsWith( line, "#" ) && !startsWith( line, "!") && line.length > 0 )
      .map!( line => strip( line.idup ) );

Reply via email to