Isn't using find with retro awkward?

Jonathan M Davis jmdavisProg at gmx.com
Mon Feb 14 20:52:32 PST 2011


On Monday 14 February 2011 20:40:02 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).simpleMindedFi
> nd.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?

Of _course_ you get a reversed range back. You _reversed the range_. That's what 
retro _does_. If you use it with find, of _course_ you're going to get a reversed 
range back. Complaining about that is like complaining that your range is sorted 
after you sorted it. It did exactly what it's supposed to do.

If we don't have an rFind, we should add one. If that means matching all of the 
versions of find, then so be it. On the bright side, the documentation for them 
would be simple, because they could pretty much refer to find and say that 
they're doing the same thing except from the back. A good rfFnd algorithm would 
not use retro at all. You could probably get away with using retro on both the 
haystack and the needle and then retro again on the result of find, but I'd have 
to test it to be sure (I _think_ that my logic is correct on that, but I'm not 
100% certain).

Really, we should have an rFind. It's probably missing because it's not useful 
as often as find is, but it would be perfectly normal (and likely expected) that 
if we have a find, we have an rFind.

- Jonathan M Davis


More information about the Digitalmars-d-learn mailing list