latk / p5-Util-Underscore

Util::Underscore – Common helper functions without having to import them
Other
0 stars 1 forks source link

"index" builtin – add sane wrapper #5

Closed latk closed 9 years ago

latk commented 10 years ago

Current Behaviour

The Perl builtin index $haystack, $needle, $start=0 returns the position where the $needle string was first found in the $haystack string, with searching starting at position $start. If the $needle isn't found, then -1 is returned. This makes sense when coming from C. Unfortunately, it makes for weird code:


if (0 <= (my $index = index $haystack, $needle)) {
    ... # match found
}

Suggested Behaviour

Perl can use undef to signify the absence of a value. The undef can never be a valid return index. This is preferable to the special integer -1, because we can more easily supply default values, or do conditionals (i.e. express the data flow more obviously). Also, -1 is a valid array subscript, while undef will at least cause a warning.

Out-of-band failure indicators should not be used:

This is the suggested interface, in pseudo-code:

sub _::index(Str $haystack, Str $needle, UInt $start = 0 --> Maybe[UInt]);

Examples

# Supplying a default index
my $index = (_::index $haystack, $needle) // $default_index;
# previously:
#   my $index = _::index $haystack, $needle;
#   $index = $default_index if $index < 0;

# Branching
if (defined(my $index = _::index $haystack, $needle)) { ... }
# see above for previous code
# actually, the suggested code isn't much better…

# Substring
# will at least warn if the $marker wasn't found
my $tail = substr $string, _::index $string, $marker;
# with explicit bailing:
my $tail = substr $string, (_::index $string, $marker) // _::croak "But you promised me a marker!";
# previously:
#   my $index = index $string, $marker;
#   Carp::croak "But you promised me a marker!" if $index < 0;
#    my $tail = substr $string, $index;

Exceptions