Skip to content

Inconsistent behaviour for string findnext and findprev #54584

@jakobnissen

Description

@jakobnissen

The behaviour of findnext and findprev are inconsistent between char/string pairs, bytearrays and arrays.
This is quite annoying and needless, and I'd like to fix it.
For background, here is the current behaviour for arrays:
findnext(a, b, c) raises a BoundsError if c < firstindex(b), but not if c > lastindex(b) in which case is returns nothing. Mirroring this, findprev(a, b, c) raises an error if c > lastindex(b) but not if c < firstindex(b) where it returns nothing.

However, for strings we have:

  • findnext(a, b, c) raises a BoundsError if c < firstindex(b). However, findprev(a, b, c) does not raise an error if c > lastindex(b). Instead, this raises an error if c > ncodeunits(b) + 1 which is doubly confusing (why ncodeunits and not lastindex? Why the +1?)
  • When c == ncodeunits(b) + 1, findprev(a, b, c) returns nothing unconditionally. I believe this is a bug.
  • findnext(a, b, c) raises an error when c > ncodeunits(b) + 1, and returns nothing when c == ncodeunits(b) + 1. This is inconsistent with the behaviour for arrays, but consistent with findprev which raises an error if c < firstindex(b) and returns nothing when c == firstindex(b) - 1.
  • For strings, findnext(a, b, c) raises an error if !isvalid(b, c). However, findprev does not do so.

This is a mess. I think there are two reasonable alternatives:

  1. The string behaviour is changed so it matches array behaviour, also using lastindex. There will be no check for isvalid starting index. This is the most straightforward fix.
  2. Array behaviour is changed such that findnext(a, b, c) where c < firstindex(b) is equivalent to findnext(a, b, firstindex(c)), and vice versa for findprev. String behaviour is updated to match this.

As far as I can tell, the string behaviour is specifically tested for, so it appears intentional. The array behaviour of these edge cases is, as far as I can tell, not tested for.

I can make a PR to fix this if the intended behaviour is agreed upon.

Metadata

Metadata

Assignees

No one assigned

    Labels

    designDesign of APIs or of the language itselfsearch & findThe find* family of functions

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions