@@ -1310,29 +1310,37 @@ defmodule Enum do
13101310 """
13111311 @ spec slice ( t , integer , integer ) :: list
13121312
1313- def slice ( _coll , _start , 0 ) , do: [ ]
1313+ def slice ( coll , start , count ) when start < 0 do
1314+ { list , new_start } = iterate_and_count_oob ( coll , start )
1315+ if new_start >= 0 , do: slice ( list , new_start , count )
1316+ end
13141317
1315- def slice ( coll , start , count ) when is_list ( coll ) and start >= 0 and count >= 0 do
1318+ def slice ( coll , start , count ) when is_list ( coll ) and start >= 0 and count > 0 do
13161319 do_slice ( coll , start , count )
13171320 end
13181321
1319- def slice ( coll , start , count ) when start >= 0 and count >= 0 do
1320- { _ , _ , list } = Enumerable . reduce ( coll , { start , count , [ ] } , fn
1322+ def slice ( coll , start , count ) when start >= 0 and count > 0 do
1323+ { start , _ , list } = Enumerable . reduce ( coll , { start , count , [ ] } , fn
13211324 _entry , { start , count , _list } when start > 0 ->
13221325 { start - 1 , count , [ ] }
13231326 entry , { start , count , list } when count > 1 ->
13241327 { start , count - 1 , [ entry | list ] }
13251328 entry , { _start , _count , list } ->
13261329 throw { :enum_slice , [ entry | list ] }
13271330 end )
1328- :lists . reverse ( list )
1331+
1332+ if start <= 0 , do: :lists . reverse ( list )
13291333 catch
13301334 { :enum_slice , list } -> :lists . reverse ( list )
13311335 end
13321336
1333- def slice ( coll , start , count ) when start < 0 do
1334- { list , start } = iterate_and_count ( coll , start )
1335- slice ( list , start , count )
1337+ def slice ( coll , start , 0 ) do
1338+ Enumerable . reduce ( coll , start , fn _ , start ->
1339+ if start > 0 , do: start - 1 , else: throw :enum_slice
1340+ end )
1341+ nil
1342+ catch
1343+ :enum_slice -> [ ]
13361344 end
13371345
13381346 ## Helpers
@@ -1357,6 +1365,11 @@ defmodule Enum do
13571365 { acc , buffer , i }
13581366 end
13591367
1368+ defp iterate_and_count_oob ( collection , count ) do
1369+ { list , total_items } = do_iterate_and_count ( collection )
1370+ { list , total_items - abs ( count ) }
1371+ end
1372+
13601373 defp iterate_and_count ( collection , count ) do
13611374 { list , total_items } = do_iterate_and_count ( collection )
13621375 { list , Kernel . max ( 0 , total_items - abs ( count ) ) }
@@ -1680,9 +1693,13 @@ defmodule Enum do
16801693
16811694 ## slice
16821695
1683- defp do_slice ( [ ] , _start , _count ) , do: [ ]
1696+ defp do_slice ( [ ] , start , _count ) do
1697+ if start == 0 , do: [ ]
1698+ end
16841699
1685- defp do_slice ( _list , _start , 0 ) , do: [ ]
1700+ defp do_slice ( list , start , 0 ) do
1701+ if start < length ( list ) , do: [ ]
1702+ end
16861703
16871704 defp do_slice ( [ h | t ] , 0 , count ) do
16881705 [ h | do_slice ( t , 0 , count - 1 ) ]
0 commit comments