@@ -1371,140 +1371,8 @@ defmodule Stream do
1371
1371
@ doc since: "1.12.0"
1372
1372
@ spec zip_with ( enumerables , ( Enumerable . t ( ) -> term ) ) :: Enumerable . t ( )
1373
1373
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 )
1508
1376
end
1509
1377
1510
1378
## Sources
0 commit comments