Thread overview | |||||||
---|---|---|---|---|---|---|---|
|
December 04, 2013 How to use retro over findSplitBefore result? | ||||
---|---|---|---|---|
| ||||
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"); |
December 04, 2013 Re: How to use retro over findSplitBefore result? | ||||
---|---|---|---|---|
| ||||
Posted in reply to MrSmith | On Wednesday, 4 December 2013 at 17:43:22 UTC, 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; > } The casting you've placed in there scares me. The returned range is going to be of dchar, assuming you're interested in UTF support, you'll want a conversion not a cast, I recommend std.conv.to!string. But even this is too much so I've commented that out and replaced it with a somewhat lazy approach: import std.algorithm : findSplitBefore; import std.range : retro, chain; import std.array : array; import std.conv : to; // returns file path where name has suffix and prefix string withSuffixPrefix(string filePath, string prefix, string suffix) { auto splitted = filePath.retro.findSplitBefore("/"); //return splitted[1].array.retro.to!string // ~ prefix // ~ splitted[0].array.retro.to!string // ~ suffix; return chain(splitted[1].array.retro, prefix, splitted[0].array.retro, suffix).array; } void main() { assert(withSuffixPrefix("/some/random/path/to/file", "pref-", ".fl") == "/some/random/path/to/pref-file.fl"); } |
December 04, 2013 Re: How to use retro over findSplitBefore result? | ||||
---|---|---|---|---|
| ||||
Posted in reply to MrSmith | 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 |
December 04, 2013 Re: How to use retro over findSplitBefore result? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jesse Phillips | On Wednesday, 4 December 2013 at 18:01:52 UTC, Jesse Phillips wrote:
> On Wednesday, 4 December 2013 at 17:43:22 UTC, 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;
>> }
>
> The casting you've placed in there scares me. The returned range is going to be of dchar, assuming you're interested in UTF support, you'll want a conversion not a cast, I recommend std.conv.to!string. But even this is too much so I've commented that out and replaced it with a somewhat lazy approach:
>
> import std.algorithm : findSplitBefore;
> import std.range : retro, chain;
> import std.array : array;
> import std.conv : to;
>
> // returns file path where name has suffix and prefix
> string withSuffixPrefix(string filePath, string prefix, string
> suffix)
> {
> auto splitted = filePath.retro.findSplitBefore("/");
>
> //return splitted[1].array.retro.to!string
> // ~ prefix
> // ~ splitted[0].array.retro.to!string
> // ~ suffix;
> return chain(splitted[1].array.retro,
> prefix,
> splitted[0].array.retro,
> suffix).array;
> }
>
> void main() {
> assert(withSuffixPrefix("/some/random/path/to/file", "pref-",
> ".fl") == "/some/random/path/to/pref-file.fl");
> }
Thank you for help, it's working!
|
December 04, 2013 Re: How to use retro over findSplitBefore result? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | 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!
|
Copyright © 1999-2021 by the D Language Foundation