@@ -3420,10 +3420,7 @@ defmodule Enum do
3420
3420
"""
3421
3421
@ spec zip ( t , t ) :: [ { any , any } ]
3422
3422
def zip ( enumerable1 , enumerable2 ) when is_list ( enumerable1 ) and is_list ( enumerable2 ) do
3423
- reducer = fn l , r , acc -> { :cont , [ { l , r } | acc ] } end
3424
-
3425
- zip_reduce_while ( enumerable1 , enumerable2 , [ ] , reducer )
3426
- |> :lists . reverse ( )
3423
+ zip_list ( enumerable1 , enumerable2 )
3427
3424
end
3428
3425
3429
3426
def zip ( enumerable1 , enumerable2 ) do
@@ -3492,7 +3489,12 @@ defmodule Enum do
3492
3489
3493
3490
"""
3494
3491
@ doc since: "1.12.0"
3495
- @ spec zip_with ( t , t , ( enumerable1_elem :: term , enumerable2_elem :: term -> term ) ) :: [ term ]
3492
+ @ spec zip_with ( t , t , ( enum1_elem :: term , enum2_elem :: term -> term ) ) :: [ term ]
3493
+ def zip_with ( enumerable1 , enumerable2 , zip_fun )
3494
+ when is_list ( enumerable1 ) and is_list ( enumerable2 ) and is_function ( zip_fun , 2 ) do
3495
+ zip_list ( enumerable1 , enumerable2 , zip_fun )
3496
+ end
3497
+
3496
3498
def zip_with ( enumerable1 , enumerable2 , zip_fun ) when is_function ( zip_fun , 2 ) do
3497
3499
reducer = fn l , r , acc -> { :cont , [ zip_fun . ( l , r ) | acc ] } end
3498
3500
@@ -3572,7 +3574,15 @@ defmodule Enum do
3572
3574
iex> Enum.zip_reduce([1, 2], [3, 4], [], fn x, y, acc -> [x + y |acc] end)
3573
3575
[6, 4]
3574
3576
"""
3575
- def zip_reduce ( left , right , acc , reducer ) do
3577
+ @ doc since: "1.12.0"
3578
+ @ spec zip_reduce ( t , t , acc , ( enum1_elem :: term , enum2_elem :: term , acc -> acc ) ) :: acc
3579
+ when acc: term
3580
+ def zip_reduce ( left , right , acc , reducer )
3581
+ when is_list ( left ) and is_list ( right ) and is_function ( reducer , 3 ) do
3582
+ zip_reduce_list ( left , right , acc , reducer )
3583
+ end
3584
+
3585
+ def zip_reduce ( left , right , acc , reducer ) when is_function ( reducer , 3 ) do
3576
3586
non_stop_reducer = & { :cont , reducer . ( & 1 , & 2 , & 3 ) }
3577
3587
zip_reduce_while ( left , right , acc , non_stop_reducer )
3578
3588
end
@@ -3612,7 +3622,11 @@ defmodule Enum do
3612
3622
...> end)
3613
3623
[{2, {:b, 4}, 6}, {1, {:a, 3}, 5}]
3614
3624
"""
3615
- def zip_reduce ( enums , acc , reducer ) do
3625
+ @ doc since: "1.12.0"
3626
+ @ spec zip_reduce ( t , acc , ( [ term ] , acc -> acc ) ) :: acc when acc: term
3627
+ def zip_reduce ( [ ] , acc , reducer ) when is_function ( reducer , 2 ) , do: acc
3628
+
3629
+ def zip_reduce ( enums , acc , reducer ) when is_function ( reducer , 2 ) do
3616
3630
non_stop_reducer = & { :cont , reducer . ( & 1 , & 2 ) }
3617
3631
zip_reduce_while ( enums , acc , non_stop_reducer )
3618
3632
end
@@ -3653,18 +3667,17 @@ defmodule Enum do
3653
3667
...> end)
3654
3668
[3]
3655
3669
3656
- iex> left = [1, 2]
3657
- ...> right = [3, 4]
3658
- ...> Enum.zip_reduce_while(left, right, [], fn l, r, acc ->
3659
- ...> {:suspend, [l + r | acc]}
3660
- ...> end)
3661
- [4]
3662
3670
"""
3663
- def zip_reduce_while ( left , right , acc , reducer ) when is_list ( left ) and is_list ( right ) do
3664
- zip_reduce_while_list ( left , right , { :cont , acc } , reducer ) |> elem ( 1 )
3671
+ @ doc since: "1.12.0"
3672
+ @ spec zip_reduce_while ( t , t , acc , ( enum1_elem :: term , enum2_elem :: term , acc -> acc ) ) ::
3673
+ { :cont | :halt , acc }
3674
+ when acc: term
3675
+ def zip_reduce_while ( left , right , acc , reducer )
3676
+ when is_list ( left ) and is_list ( right ) and is_function ( reducer , 3 ) do
3677
+ zip_reduce_while_list ( left , right , { :cont , acc } , reducer )
3665
3678
end
3666
3679
3667
- def zip_reduce_while ( left , right , acc , reducer ) do
3680
+ def zip_reduce_while ( left , right , acc , reducer ) when is_function ( reducer , 3 ) do
3668
3681
reduce = fn [ l , r ] , acc -> reducer . ( l , r , acc ) end
3669
3682
Stream . zip_with ( [ left , right ] , & & 1 ) . ( { :cont , acc } , reduce ) |> elem ( 1 )
3670
3683
end
@@ -3711,26 +3724,14 @@ defmodule Enum do
3711
3724
...> Enum.zip_reduce_while(enums, [], reducer)
3712
3725
[4]
3713
3726
"""
3714
- def zip_reduce_while ( [ ] , acc , _reducer ) , do: acc
3727
+ @ doc since: "1.12.0"
3728
+ @ spec zip_reduce_while ( [ t ] , acc , ( [ term ] , acc -> acc ) ) :: { :cont | :halt , acc } when acc: term
3729
+ def zip_reduce_while ( [ ] , acc , reducer ) when is_function ( reducer , 2 ) , do: acc
3715
3730
3716
- def zip_reduce_while ( enums , acc , reducer ) do
3731
+ def zip_reduce_while ( enums , acc , reducer ) when is_function ( reducer , 2 ) do
3717
3732
Stream . zip_with ( enums , & & 1 ) . ( { :cont , acc } , reducer ) |> elem ( 1 )
3718
3733
end
3719
3734
3720
- # This speeds things up when zip reducing two lists.
3721
- defp zip_reduce_while_list ( _left , _right , { :halt , acc } , _ ) , do: { :halted , acc }
3722
-
3723
- defp zip_reduce_while_list ( left , right , { :suspend , acc } , reducer ) do
3724
- { :suspended , acc , & zip_reduce_while_list ( left , right , & 1 , reducer ) }
3725
- end
3726
-
3727
- defp zip_reduce_while_list ( [ ] , _right , { :cont , acc } , _ ) , do: { :done , acc }
3728
- defp zip_reduce_while_list ( _left , [ ] , { :cont , acc } , _ ) , do: { :done , acc }
3729
-
3730
- defp zip_reduce_while_list ( [ l_head | l_tail ] , [ r_head | r_tail ] , { :cont , acc } , reducer ) do
3731
- zip_reduce_while_list ( l_tail , r_tail , reducer . ( l_head , r_head , acc ) , reducer )
3732
- end
3733
-
3734
3735
## Helpers
3735
3736
3736
3737
@ compile { :inline , entry_to_string: 1 , reduce: 3 , reduce_by: 3 , reduce_enumerable: 3 }
@@ -4332,6 +4333,34 @@ defmodule Enum do
4332
4333
defp uniq_list ( [ ] , _set , _fun ) do
4333
4334
[ ]
4334
4335
end
4336
+
4337
+ ## zip
4338
+
4339
+ defp zip_list ( enumerable1 , enumerable2 ) do
4340
+ zip_list ( enumerable1 , enumerable2 , fn x , y -> { x , y } end )
4341
+ end
4342
+
4343
+ defp zip_list ( [ head1 | next1 ] , [ head2 | next2 ] , fun ) do
4344
+ [ fun . ( head1 , head2 ) | zip_list ( next1 , next2 , fun ) ]
4345
+ end
4346
+
4347
+ defp zip_list ( _ , [ ] , _fun ) , do: [ ]
4348
+ defp zip_list ( [ ] , _ , _fun ) , do: [ ]
4349
+
4350
+ defp zip_reduce_list ( [ head1 | next1 ] , [ head2 | next2 ] , acc , fun ) do
4351
+ zip_reduce_list ( next1 , next2 , fun . ( head1 , head2 , acc ) , fun )
4352
+ end
4353
+
4354
+ defp zip_reduce_list ( _ , [ ] , acc , _fun ) , do: acc
4355
+ defp zip_reduce_list ( [ ] , _ , acc , _fun ) , do: acc
4356
+
4357
+ defp zip_reduce_while_list ( _left , _right , { :halt , acc } , _ ) , do: acc
4358
+ defp zip_reduce_while_list ( [ ] , _right , { :cont , acc } , _ ) , do: acc
4359
+ defp zip_reduce_while_list ( _left , [ ] , { :cont , acc } , _ ) , do: acc
4360
+
4361
+ defp zip_reduce_while_list ( [ l_head | l_tail ] , [ r_head | r_tail ] , { :cont , acc } , reducer ) do
4362
+ zip_reduce_while_list ( l_tail , r_tail , reducer . ( l_head , r_head , acc ) , reducer )
4363
+ end
4335
4364
end
4336
4365
4337
4366
defimpl Enumerable , for: List do
0 commit comments