@@ -3447,7 +3447,7 @@ defmodule Enum do
3447
3447
def zip ( [ ] ) , do: [ ]
3448
3448
3449
3449
def zip ( enumerables ) do
3450
- zip_reduce_while ( enumerables , [ ] , & { :cont , [ List . to_tuple ( & 1 ) | & 2 ] } )
3450
+ zip_reduce ( enumerables , [ ] , & [ List . to_tuple ( & 1 ) | & 2 ] )
3451
3451
|> :lists . reverse ( )
3452
3452
end
3453
3453
@@ -3497,9 +3497,7 @@ defmodule Enum do
3497
3497
end
3498
3498
3499
3499
def zip_with ( enumerable1 , enumerable2 , zip_fun ) when is_function ( zip_fun , 2 ) do
3500
- reducer = fn l , r , acc -> { :cont , [ zip_fun . ( l , r ) | acc ] } end
3501
-
3502
- zip_reduce_while ( enumerable1 , enumerable2 , [ ] , reducer )
3500
+ zip_reduce ( enumerable1 , enumerable2 , [ ] , fn l , r , acc -> [ zip_fun . ( l , r ) | acc ] end )
3503
3501
|> :lists . reverse ( )
3504
3502
end
3505
3503
@@ -3529,15 +3527,19 @@ defmodule Enum do
3529
3527
def zip_with ( [ ] , _fun ) , do: [ ]
3530
3528
3531
3529
def zip_with ( enumerables , zip_fun ) do
3532
- reducer = fn values , acc -> { :cont , [ zip_fun . ( values ) | acc ] } end
3533
-
3534
- zip_reduce_while ( enumerables , [ ] , reducer )
3530
+ zip_reduce ( enumerables , [ ] , fn values , acc -> [ zip_fun . ( values ) | acc ] end )
3535
3531
|> :lists . reverse ( )
3536
3532
end
3537
3533
3538
3534
@ doc """
3539
3535
Reduces over two enumerables halting as soon as either enumerable is empty.
3540
3536
3537
+ In practice, the behaviour provided by this function can be achieved with:
3538
+
3539
+ Enum.reduce(Stream.zip(left, right), acc, reducer)
3540
+
3541
+ But `zip_reduce/4` exists for convenience purposes.
3542
+
3541
3543
## Examples
3542
3544
3543
3545
iex> Enum.zip_reduce([1, 2], [3, 4], 0, fn x, y, acc -> x + y + acc end)
@@ -3555,8 +3557,8 @@ defmodule Enum do
3555
3557
end
3556
3558
3557
3559
def zip_reduce ( left , right , acc , reducer ) when is_function ( reducer , 3 ) do
3558
- non_stop_reducer = & { :cont , reducer . ( & 1 , & 2 , & 3 ) }
3559
- zip_reduce_while ( left , right , acc , non_stop_reducer )
3560
+ reduce = fn [ l , r ] , acc -> { :cont , reducer . ( l , r , acc ) } end
3561
+ Stream . zip_with ( [ left , right ] , & & 1 ) . ( { :cont , acc } , reduce ) |> elem ( 1 )
3560
3562
end
3561
3563
3562
3564
@ doc """
@@ -3565,6 +3567,12 @@ defmodule Enum do
3565
3567
The reducer will receive 2 args, a list of elements (one from each enum) and the
3566
3568
accumulator.
3567
3569
3570
+ In practice, the behaviour provided by this function can be achieved with:
3571
+
3572
+ Enum.reduce(Stream.zip(enums), acc, reducer)
3573
+
3574
+ But `zip_reduce/4` exists for convenience purposes.
3575
+
3568
3576
## Examples
3569
3577
3570
3578
iex> enums = [[1, 1], [2, 2], [3, 3]]
@@ -3584,80 +3592,7 @@ defmodule Enum do
3584
3592
def zip_reduce ( [ ] , acc , reducer ) when is_function ( reducer , 2 ) , do: acc
3585
3593
3586
3594
def zip_reduce ( enums , acc , reducer ) when is_function ( reducer , 2 ) do
3587
- non_stop_reducer = & { :cont , reducer . ( & 1 , & 2 ) }
3588
- zip_reduce_while ( enums , acc , non_stop_reducer )
3589
- end
3590
-
3591
- @ doc """
3592
- Reduces over two enumerables halting if the accumulator returns
3593
- `{:halt, value}` or if either of the enumerables is empty.
3594
-
3595
- The reducer will receive 3 args, the left enumerable's element,
3596
- the right enumberable's element and the accumulator. It should
3597
- return one of:
3598
-
3599
- * `{:halt, value}` - This will halt the reduction and return `value`
3600
- * `{:cont, value}` - This will continue with the next step of the reduction
3601
-
3602
- ## Examples
3603
-
3604
- iex> reducer = fn left, right, acc -> {:cont, [left + right | acc ]} end
3605
- ...> Enum.zip_reduce_while([1], [2], [], reducer)
3606
- [3]
3607
-
3608
- iex> Enum.zip_reduce_while([1, 2], [2, 2], [], fn left, right, acc ->
3609
- ...> if left <= 1, do: {:cont, [left + right | acc]}, else: {:halt, acc}
3610
- ...> end)
3611
- [3]
3612
-
3613
- """
3614
- @ doc since: "1.12.0"
3615
- @ spec zip_reduce_while ( t , t , acc , ( enum1_elem :: term , enum2_elem :: term , acc -> acc ) ) ::
3616
- { :cont | :halt , acc }
3617
- when acc: term
3618
- def zip_reduce_while ( left , right , acc , reducer )
3619
- when is_list ( left ) and is_list ( right ) and is_function ( reducer , 3 ) do
3620
- zip_reduce_while_list ( left , right , { :cont , acc } , reducer )
3621
- end
3622
-
3623
- def zip_reduce_while ( left , right , acc , reducer ) when is_function ( reducer , 3 ) do
3624
- reduce = fn [ l , r ] , acc -> reducer . ( l , r , acc ) end
3625
- Stream . zip_with ( [ left , right ] , & & 1 ) . ( { :cont , acc } , reduce ) |> elem ( 1 )
3626
- end
3627
-
3628
- @ doc """
3629
- Reduces over all enumerables halting if the accumulator returns
3630
- `{:halt, value}` or if any of the enumerables is empty.
3631
-
3632
- The reducer will receive 2 args, a list of the yielded elements
3633
- and the accumulator. It should return one of:
3634
-
3635
- * `{:halt, value}` - This will halt the reduction and return `value`
3636
- * `{:cont, value}` - This will continue with the next step of the reduction
3637
-
3638
- ## Examples
3639
-
3640
- iex> enums = [[1, 2],[3, 4]]
3641
- ...> reducer = fn values, acc -> {:cont, Enum.sum(values) + acc} end
3642
- ...> Enum.zip_reduce_while(enums, 0, reducer)
3643
- 10
3644
-
3645
- iex> enums = [[1, 2],[3, 4]]
3646
- ...> reducer = fn values, acc -> {:suspend, [Enum.sum(values) | acc]} end
3647
- ...> Enum.zip_reduce_while(enums, [], reducer)
3648
- [4]
3649
-
3650
- iex> enums = [[1, 2],[3, 4]]
3651
- ...> reducer = fn values, acc -> {:halt, [Enum.sum(values) | acc]} end
3652
- ...> Enum.zip_reduce_while(enums, [], reducer)
3653
- [4]
3654
- """
3655
- @ doc since: "1.12.0"
3656
- @ spec zip_reduce_while ( [ t ] , acc , ( [ term ] , acc -> acc ) ) :: { :cont | :halt , acc } when acc: term
3657
- def zip_reduce_while ( [ ] , acc , reducer ) when is_function ( reducer , 2 ) , do: acc
3658
-
3659
- def zip_reduce_while ( enums , acc , reducer ) when is_function ( reducer , 2 ) do
3660
- Stream . zip_with ( enums , & & 1 ) . ( { :cont , acc } , reducer ) |> elem ( 1 )
3595
+ Stream . zip_with ( enums , & & 1 ) . ( { :cont , acc } , & { :cont , reducer . ( & 1 , & 2 ) } ) |> elem ( 1 )
3661
3596
end
3662
3597
3663
3598
## Helpers
@@ -4281,14 +4216,6 @@ defmodule Enum do
4281
4216
4282
4217
defp zip_reduce_list ( _ , [ ] , acc , _fun ) , do: acc
4283
4218
defp zip_reduce_list ( [ ] , _ , acc , _fun ) , do: acc
4284
-
4285
- defp zip_reduce_while_list ( _left , _right , { :halt , acc } , _ ) , do: acc
4286
- defp zip_reduce_while_list ( [ ] , _right , { :cont , acc } , _ ) , do: acc
4287
- defp zip_reduce_while_list ( _left , [ ] , { :cont , acc } , _ ) , do: acc
4288
-
4289
- defp zip_reduce_while_list ( [ l_head | l_tail ] , [ r_head | r_tail ] , { :cont , acc } , reducer ) do
4290
- zip_reduce_while_list ( l_tail , r_tail , reducer . ( l_head , r_head , acc ) , reducer )
4291
- end
4292
4219
end
4293
4220
4294
4221
defimpl Enumerable , for: List do
0 commit comments