Skip to content

Commit 24c4bc3

Browse files
author
José Valim
committed
Merge pull request #2412 from christhekeele/empty-string-slice
Ensures String.slice always returns a string
2 parents b126e3b + 000a174 commit 24c4bc3

File tree

2 files changed

+32
-40
lines changed

2 files changed

+32
-40
lines changed

lib/elixir/lib/string.ex

Lines changed: 19 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -974,7 +974,7 @@ defmodule String do
974974
@doc """
975975
Returns a substring starting at the offset given by the first, and
976976
a length given by the second.
977-
If the offset is greater than string length, than it returns `nil`.
977+
If the offset is greater than string length, than it returns `""`.
978978
979979
## Examples
980980
@@ -985,13 +985,13 @@ defmodule String do
985985
"lixir"
986986
987987
iex> String.slice("elixir", 10, 3)
988-
nil
988+
""
989989
990990
iex> String.slice("elixir", -4, 4)
991991
"ixir"
992992
993993
iex> String.slice("elixir", -10, 3)
994-
nil
994+
""
995995
996996
iex> String.slice("a", 0, 1500)
997997
"a"
@@ -1000,16 +1000,13 @@ defmodule String do
10001000
""
10011001
10021002
iex> String.slice("a", 2, 1500)
1003-
nil
1003+
""
10041004
10051005
"""
1006-
@spec slice(t, integer, integer) :: grapheme | nil
1006+
@spec slice(t, integer, integer) :: grapheme
10071007

1008-
def slice(string, start, 0) do
1009-
case abs(start) <= length(string) do
1010-
true -> ""
1011-
false -> nil
1012-
end
1008+
def slice(_, _, 0) do
1009+
""
10131010
end
10141011

10151012
def slice(string, start, len) when start >= 0 and len >= 0 do
@@ -1020,7 +1017,7 @@ defmodule String do
10201017
real_start_pos = length(string) - abs(start)
10211018
case real_start_pos >= 0 do
10221019
true -> do_slice(next_grapheme(string), real_start_pos, real_start_pos + len - 1, 0, "")
1023-
false -> nil
1020+
false -> ""
10241021
end
10251022
end
10261023

@@ -1029,7 +1026,7 @@ defmodule String do
10291026
range to the offset given by the end of the range.
10301027
10311028
If the start of the range is not a valid offset for the given
1032-
string or if the range is in reverse order, returns `nil`.
1029+
string or if the range is in reverse order, returns `""`.
10331030
10341031
## Examples
10351032
@@ -1040,7 +1037,7 @@ defmodule String do
10401037
"lixir"
10411038
10421039
iex> String.slice("elixir", 10..3)
1043-
nil
1040+
""
10441041
10451042
iex> String.slice("elixir", -4..-1)
10461043
"ixir"
@@ -1052,10 +1049,10 @@ defmodule String do
10521049
"ixir"
10531050
10541051
iex> String.slice("elixir", -1..-4)
1055-
nil
1052+
""
10561053
10571054
iex> String.slice("elixir", -10..-7)
1058-
nil
1055+
""
10591056
10601057
iex> String.slice("a", 0..1500)
10611058
"a"
@@ -1064,10 +1061,10 @@ defmodule String do
10641061
""
10651062
10661063
iex> String.slice("a", 2..1500)
1067-
nil
1064+
""
10681065
10691066
"""
1070-
@spec slice(t, Range.t) :: t | nil
1067+
@spec slice(t, Range.t) :: t
10711068

10721069
def slice(string, range)
10731070

@@ -1088,11 +1085,13 @@ defmodule String do
10881085

10891086
if first >= 0 do
10901087
do_slice(next_grapheme(string), first, last, 0, "")
1088+
else
1089+
""
10911090
end
10921091
end
10931092

10941093
defp do_slice(_, start_pos, last_pos, _, _) when start_pos > last_pos do
1095-
nil
1094+
""
10961095
end
10971096

10981097
defp do_slice({_, rest}, start_pos, last_pos, current_pos, acc) when current_pos < start_pos do
@@ -1106,16 +1105,9 @@ defmodule String do
11061105
defp do_slice({char, _}, start_pos, last_pos, current_pos, acc) when current_pos >= start_pos and current_pos == last_pos do
11071106
acc <> char
11081107
end
1109-
1110-
defp do_slice(nil, start_pos, _, current_pos, acc) when start_pos == current_pos do
1111-
acc
1112-
end
1113-
1108+
11141109
defp do_slice(nil, _, _, _, acc) do
1115-
case acc do
1116-
"" -> nil
1117-
_ -> acc
1118-
end
1110+
acc
11191111
end
11201112

11211113
@doc """

lib/elixir/test/elixir/string_test.exs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -311,18 +311,18 @@ defmodule StringTest do
311311
assert String.slice("elixir", -3, 2) == "xi"
312312
assert String.slice("あいうえお", -4, 3) == "いうえ"
313313
assert String.slice("ειξήριολ", -5, 3) == "ήρι"
314-
assert String.slice("elixir", -10, 1) == nil
315-
assert String.slice("あいうえお", -10, 2) == nil
316-
assert String.slice("ειξήριολ", -10, 3) == nil
317-
assert String.slice("elixir", 8, 2) == nil
318-
assert String.slice("あいうえお", 6, 2) == nil
314+
assert String.slice("elixir", -10, 1) == ""
315+
assert String.slice("あいうえお", -10, 2) == ""
316+
assert String.slice("ειξήριολ", -10, 3) == ""
317+
assert String.slice("elixir", 8, 2) == ""
318+
assert String.slice("あいうえお", 6, 2) == ""
319319
assert String.slice("ειξήριολ", 8, 1) == ""
320-
assert String.slice("ειξήριολ", 9, 1) == nil
320+
assert String.slice("ειξήριολ", 9, 1) == ""
321321
assert String.slice("elixir", 0, 0) == ""
322322
assert String.slice("elixir", 5, 0) == ""
323323
assert String.slice("elixir", -5, 0) == ""
324324
assert String.slice("", 0, 1) == ""
325-
assert String.slice("", 1, 1) == nil
325+
assert String.slice("", 1, 1) == ""
326326

327327
assert String.slice("elixir", 0..-2) == "elixi"
328328
assert String.slice("elixir", 1..3) == "lix"
@@ -336,14 +336,14 @@ defmodule StringTest do
336336
assert String.slice("elixir", -3..-2) == "xi"
337337
assert String.slice("あいうえお", -4..-2) == "いうえ"
338338
assert String.slice("ειξήριολ", -5..-3) == "ήρι"
339-
assert String.slice("elixir", 8..9) == nil
340-
assert String.slice("あいうえお", 6..7) == nil
339+
assert String.slice("elixir", 8..9) == ""
340+
assert String.slice("あいうえお", 6..7) == ""
341341
assert String.slice("ειξήριολ", 8..8) == ""
342-
assert String.slice("ειξήριολ", 9..9) == nil
342+
assert String.slice("ειξήριολ", 9..9) == ""
343343
assert String.slice("", 0..0) == ""
344-
assert String.slice("", 1..1) == nil
345-
assert String.slice("あいうえお", -2..-4) == nil
346-
assert String.slice("あいうえお", -10..-15) == nil
344+
assert String.slice("", 1..1) == ""
345+
assert String.slice("あいうえお", -2..-4) == ""
346+
assert String.slice("あいうえお", -10..-15) == ""
347347
end
348348

349349
test :valid? do

0 commit comments

Comments
 (0)