@@ -1371,140 +1371,8 @@ defmodule Stream do
13711371 @ doc since: "1.12.0"
13721372 @ spec zip_with ( enumerables , ( Enumerable . t ( ) -> term ) ) :: Enumerable . t ( )
13731373 when enumerables: [ Enumerable . t ( ) ] | Enumerable . t ( )
1374- def zip_with ( enumerables , zip_fun ) when is_function ( zip_fun , 1 ) do
1375- if is_list ( enumerables ) and :lists . all ( & is_list / 1 , enumerables ) do
1376- & zip_list ( enumerables , & 1 , & 2 , zip_fun )
1377- else
1378- & zip_enum ( enumerables , & 1 , & 2 , zip_fun )
1379- end
1380- end
1381-
1382- defp zip_list ( _enumerables , { :halt , acc } , _fun , _zip_fun ) do
1383- { :halted , acc }
1384- end
1385-
1386- defp zip_list ( enumerables , { :suspend , acc } , fun , zip_fun ) do
1387- { :suspended , acc , & zip_list ( enumerables , & 1 , fun , zip_fun ) }
1388- end
1389-
1390- defp zip_list ( [ ] , { :cont , acc } , _fun , _zip_fun ) , do: { :done , acc }
1391-
1392- defp zip_list ( enumerables , { :cont , acc } , fun , zip_fun ) do
1393- case zip_list_heads_tails ( enumerables , [ ] , [ ] ) do
1394- { heads , tails } -> zip_list ( tails , fun . ( zip_fun . ( heads ) , acc ) , fun , zip_fun )
1395- :error -> { :done , acc }
1396- end
1397- end
1398-
1399- defp zip_list_heads_tails ( [ [ head | tail ] | rest ] , heads , tails ) do
1400- zip_list_heads_tails ( rest , [ head | heads ] , [ tail | tails ] )
1401- end
1402-
1403- defp zip_list_heads_tails ( [ [ ] | _rest ] , _heads , _tails ) do
1404- :error
1405- end
1406-
1407- defp zip_list_heads_tails ( [ ] , heads , tails ) do
1408- { :lists . reverse ( heads ) , :lists . reverse ( tails ) }
1409- end
1410-
1411- defp zip_enum ( enumerables , acc , fun , zip_fun ) do
1412- step = fn x , acc ->
1413- { :suspend , :lists . reverse ( [ x | acc ] ) }
1414- end
1415-
1416- enum_funs =
1417- Enum . map ( enumerables , fn enum ->
1418- { & Enumerable . reduce ( enum , & 1 , step ) , [ ] , :cont }
1419- end )
1420-
1421- do_zip_enum ( enum_funs , acc , fun , zip_fun )
1422- end
1423-
1424- # This implementation of do_zip_enum/4 works for any number of streams to zip
1425- defp do_zip_enum ( zips , { :halt , acc } , _fun , _zip_fun ) do
1426- do_zip_close ( zips )
1427- { :halted , acc }
1428- end
1429-
1430- defp do_zip_enum ( zips , { :suspend , acc } , fun , zip_fun ) do
1431- { :suspended , acc , & do_zip_enum ( zips , & 1 , fun , zip_fun ) }
1432- end
1433-
1434- defp do_zip_enum ( [ ] , { :cont , acc } , _callback , _zip_fun ) do
1435- { :done , acc }
1436- end
1437-
1438- defp do_zip_enum ( zips , { :cont , acc } , callback , zip_fun ) do
1439- try do
1440- do_zip_next ( zips , acc , callback , [ ] , [ ] , zip_fun )
1441- catch
1442- kind , reason ->
1443- do_zip_close ( zips )
1444- :erlang . raise ( kind , reason , __STACKTRACE__ )
1445- else
1446- { :next , buffer , acc } ->
1447- do_zip_enum ( buffer , acc , callback , zip_fun )
1448-
1449- { :done , _acc } = other ->
1450- other
1451- end
1452- end
1453-
1454- # do_zip_next/6 computes the next tuple formed by
1455- # the next element of each zipped stream.
1456- defp do_zip_next (
1457- [ { _ , [ ] , :halt } | zips ] ,
1458- acc ,
1459- _callback ,
1460- _yielded_elems ,
1461- buffer ,
1462- _zip_fun
1463- ) do
1464- do_zip_close ( :lists . reverse ( buffer , zips ) )
1465- { :done , acc }
1466- end
1467-
1468- defp do_zip_next ( [ { fun , [ ] , :cont } | zips ] , acc , callback , yielded_elems , buffer , zip_fun ) do
1469- case fun . ( { :cont , [ ] } ) do
1470- { :suspended , [ elem | next_acc ] , fun } ->
1471- next_buffer = [ { fun , next_acc , :cont } | buffer ]
1472- do_zip_next ( zips , acc , callback , [ elem | yielded_elems ] , next_buffer , zip_fun )
1473-
1474- { _ , [ elem | next_acc ] } ->
1475- next_buffer = [ { fun , next_acc , :halt } | buffer ]
1476- do_zip_next ( zips , acc , callback , [ elem | yielded_elems ] , next_buffer , zip_fun )
1477-
1478- { _ , [ ] } ->
1479- # The current zipped stream terminated, so we close all the streams
1480- # and return {:halted, acc} (which is returned as is by do_zip/3).
1481- do_zip_close ( :lists . reverse ( buffer , zips ) )
1482- { :done , acc }
1483- end
1484- end
1485-
1486- defp do_zip_next (
1487- [ { fun , zip_acc , zip_op } | zips ] ,
1488- acc ,
1489- callback ,
1490- yielded_elems ,
1491- buffer ,
1492- zip_fun
1493- ) do
1494- [ elem | rest ] = zip_acc
1495- next_buffer = [ { fun , rest , zip_op } | buffer ]
1496- do_zip_next ( zips , acc , callback , [ elem | yielded_elems ] , next_buffer , zip_fun )
1497- end
1498-
1499- defp do_zip_next ( [ ] = _zips , acc , callback , yielded_elems , buffer , zip_fun ) do
1500- # "yielded_elems" is a reversed list of results for the current iteration of
1501- # zipping. That is to say, the nth element from each of the enums being zipped.
1502- # It needs to be reversed and passed to the zipping function so it can do it's thing.
1503- { :next , :lists . reverse ( buffer ) , callback . ( zip_fun . ( :lists . reverse ( yielded_elems ) ) , acc ) }
1504- end
1505-
1506- defp do_zip_close ( zips ) do
1507- :lists . foreach ( fn { fun , _ , _ } -> fun . ( { :halt , [ ] } ) end , zips )
1374+ def zip_with ( enumerables , zip_fun ) do
1375+ R . zip_with ( enumerables , zip_fun )
15081376 end
15091377
15101378 ## Sources
0 commit comments