Isn't using find with retro awkward?

spir denis.spir at gmail.com
Tue Feb 15 01:58:57 PST 2011


On 02/15/2011 05:40 AM, Andrej Mitrovic wrote:
> On 2/15/11, Jonathan M Davis<jmdavisProg at gmx.com>  wrote:
>>
>> retro revereses the whole range. What you want is something like
>> findFromBack.
>> I don't think that we have any functions like findFromBack though. It's
>> probably
>> worth an enhancement request.
>
> std.string had a find and rfind, both of which are deprecated now
> (although we can still use indexOf&  lastIndexOf). So
> std.algorithm.find will take its place, but there's no rFind. There's
> retro().
>
> So I suppose rFind or lastFind would fit as a name if there's a use
> case for this.
>
> The problem is, there's 7 find templates in std.algorithm. I think
> making another 7 templates for lastFind would be too much work without
> a valid use case. It's much more than just replacing popBack and back
> calls to popFront and front, from what I can tell.
>
> Anyway, I'm posting this since I don't know if a reversed range is
> what most people want. It seems kind of strange to me to use retro to
> find a last match and then get a reversed range back, but maybe that's
> just me?
>
> I'd like to hear from people who've used find with retro - if so did
> the reversed range and its length make sense to them or not?
>
> Using retro with a string doesn't make sense since that will reverse
> the string and you won't match with your needle. It won't compile
> either, but maybe that is a bug with retro or find. Here's what I
> mean:
>
> import std.string : indexOf, lastIndexOf;
> import std.algorithm;
> import std.range;
>
> void main()
> {
>      string mystring = "foo bar doo bar yaz";
>      auto leftIndex = indexOf(mystring, "bar");
>      assert(mystring[leftIndex .. $] == "bar doo bar yaz");
>
>      auto rightIndex = lastIndexOf(mystring, "bar");
>      assert(mystring[rightIndex .. $] == "bar yaz");
>
>      // now the std.algorithm.find case:
>      auto firstRange = find(mystring, "bar");
>      assert(firstRange == "bar doo bar yaz");
>
>      // will never match, since retro reverses the string.
>      // but it also errors out
>      auto lastRange = find(retro(mystring), "bar");
>      assert(firstRange == "bar yaz");
> }
>
> D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\algorithm.d(2403): Error: variable
> std.algorithm.simpleMindedFind!(pred,Retro!(string),string).simpleMindedFind.estimatedNeedleLength
> cannot modify immutable
> D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\algorithm.d(2216): Error: template
> instance std.algorithm.simpleMindedFind!(pred,Retro!(string),string)
> error instantiating
> stringFind2.d(20):        instantiated from here: find!("a ==
> b",Retro!(string),string)
> stringFind2.d(20): Error: template instance std.algorithm.find!("a ==
> b",Retro!(string),string) error instantiating
>
> Also, std.string.indexOf conflicts with std.algorithm.indexOf, but I
> think some of these functions are getting fixed for the next release
> (IIRC there was a thread about it).
>
> Now, how would you easily get a range back so that:
>
> find("foo bar doo bar", "bar") == "bar doo bar"
> and:
> lastFind("foo bar doo bar", "bar") == "bar"
>
> without using a specialized version of find, in this case lastFind?

0. If we want a separate function for finding backwards, it should have a name 
starting with "find-", I guess, like Jonathan's findFromBack, or just findBack 
possibly?
But I guess we could instead have a 'backwards' bool param for such cases 
(probably rare). This would also save the issue of duplicating all find 
template variant. (Sure, inside the func the search loop must be duplicated, I 
gues, but still...) What do you think?

1. About the documentation saying to use retro to find last, it is just 
*incorrect*. It would be ok if find would return an element, but it doesn't. 
Actually, seems the doc writer has fallen in /this/ trap.

2. In general, I find (!) it wrong for a func called "find" to return the 
"rest" range.
   * that is certainly not what people expect --> bugs
   * that is uselessly heavy & unpracticle in typical case
In some situations, getting a rest range is probably just the right thing. Eg 
for incremental search. Even then, a findAll func would fulfill the needs in 
most cases, don't you think?. Maybe "findRest" for the current function would 
make things clearer?

Also: most libs return an index (or an interval, for pattern matching) for 
find: this lets the user choose whether to then fetch the element, a slice, 
nothing, or whatever.

Denis
-- 
_________________
vita es estrany
spir.wikidot.com



More information about the Digitalmars-d-learn mailing list