How to use retro over findSplitBefore result?

Ali Çehreli acehreli at yahoo.com
Wed Dec 4 10:26:41 PST 2013


On 12/04/2013 09:43 AM, MrSmith wrote:
> I am trying to compile following code
>
> import std.algorithm : findSplitBefore;
> import std.range : retro;
> import std.array : array;
>
> // returns file path where name has suffix and prefix
> string withSuffixPrefix(string filePath, string prefix, string suffix)
> {
>      auto splitted = filePath.retro.findSplitBefore("/");
>
>      return cast(string)splitted[1].retro.array
>          ~ prefix
>          ~ cast(string)splitted[0].retro.array //Fails!
>          ~ suffix;
> }
>
> With following error:
> build.d(56): Error: template std.range.retro does not match any function
> template declaration. Candidates are:
> /phobos/std/range.d(1455):   std.range.retro(Range)(Range r) if
> (isBidirectionalRange!(Unqual!Range))
> build.d(56): Error: template std.range.retro(Range)(Range r) if
> (isBidirectionalRange!(Unqual!Range)) cannot deduce template function
> from argument types !()(Result)
>
> Seems like i need to somehow convert splitted[0] to Bidirectional range.
>
> This function will be used like this:
> assert(withSuffixPrefix("/some/random/path/to/file", "pref-", ".fl") ==
> "/some/random/path/to/pref-file.fl");

The main reason is that the ranges that findSplitBefore produces are not 
BidirectionalRanges. retro requires a BidirectionalRange and for that 
reason splitted[0].retro fails. The following solution inserts an .array 
to produce a BidirectionalRange.

However, I don't see any reason why findSplitBefore could not produce 
BidirectionalRanges when it operated on a BidirectionalRange to begin with.

Just to stay with your algorithm, you can also use std.conv.text (as 
well as std.conv.to!string, which Jesse Phillips recomended):

import std.algorithm : findSplitBefore;
import std.range;
import std.array : array;
import std.stdio;
import std.conv;

// returns file path where name has suffix and prefix
string withSuffixPrefix(string filePath, string prefix, string suffix)
{
     auto splitted = filePath.retro.findSplitBefore("/");

     static assert(!isBidirectionalRange!(typeof(splitted[0])));

     return splitted[1].retro.text
         ~ prefix
         ~ splitted[0].array.retro.text
         ~ suffix;
}

void main()
{
     writeln(withSuffixPrefix("/some/random/path/to/file", "pref-", ".fl"));
}

Alternatively, you can use std.path:

import std.path;
import std.string;

string withSuffixPrefix(string filePath, string prefix, string suffix)
{
     return format("%s/%s%s%s",
                   filePath.dirName, prefix, filePath.baseName, suffix);
}

void main()
{
     assert(withSuffixPrefix("/some/random/path/to/file", "pref-", ".fl") ==
            "/some/random/path/to/pref-file.fl");
}

Ali



More information about the Digitalmars-d-learn mailing list