Description
Tested versions
- Reproducible in: 4.4.stable.official, 4.3.stable.official
System information
N/A
Issue description
String.get_slice
returns the entire original string when delimiter
does not occur in the string. This behavior is inconsistent and can cause a number of subtle and confusing bugs in user code.
I propose that this special case when the delimiter is not found is effectively a bug and should be removed. Instead, get_slice
should follow the general rule when the delimiter is not found (i.e. return the entire string if slice == 0
, otherwise return the empty string).
Steps to reproduce
Consider the following examples that illustrate issues that this behavior can cause:
A simple function that returns the third element from a comma separated list:
func third_element(values):
return values.get_slice(",", 2)
This produces the following output:
third_element("0,1,2,3") == "2" # correct
third_element("0,1,2") == "2" # correct
third_element("0,1") == "" # correct
third_element("0") == "0" # incorrect, the first element shows up as the third element
A simple function that extracts and concatenates the first and third element:
func extract_pair(values):
values.get_slice(",", 0) + "," + values.get_slice(",", 2)
This produces the following output:
extract_pair("0,1,2,3") == "0,2" # correct
extract_pair("0,1,2") == "0,2" # correct
extract_pair("0,1") == "0," # correct
extract_pair("0") == "0,0" # incorrect, the first element unexpectedly appears to be the third element as well
In addition, the current behavior breaks the intuitive expectation that get_slice
is equivalent to split
followed by getting the respective element or empty string if there is no such element:
func get_slice(value, delimiter, slice):
var parts = value.split(delimiter)
return parts[slice] if slice < len(parts) else ""
This produces the following output:
"0,1,2,3".get_slice(",", 2) == get_slice("0,1,2,3", ",", 2) == "2" # matches
"0,1,2".get_slice(",", 2) == get_slice("0,1,2", ",", 2) == "2" # matches
"0,1".get_slice(",", 2) == get_slice("0,1", ",", 2) == "" # matches
"0".get_slice(",", 2) != get_slice("0", ",", 2) # does not match (built-in get_slice returns "0", while the split-based implementation returns "")
Minimal reproduction project (MRP)
N/A