How to use retro over findSplitBefore result?

MrSmith mrsmith33 at yandex.ru
Wed Dec 4 10:36:11 PST 2013


On Wednesday, 4 December 2013 at 18:26:43 UTC, Ali Çehreli wrote:
> 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

Thanks Ali!


More information about the Digitalmars-d-learn mailing list