@@ -376,6 +376,18 @@ defmodule Enum do
376
376
{ { _ , _ } , { _ , :stop } } ->
377
377
false
378
378
379
+ { { _ , :stop } , [ ] } ->
380
+ true
381
+
382
+ { [ ] , { _ , :stop } } ->
383
+ true
384
+
385
+ { { _ , :stop } , _ } ->
386
+ false
387
+
388
+ { _ , { _ , :stop } } ->
389
+ false
390
+
379
391
{ { a_iterator , a_pointer } , { b_iterator , b_pointer } } ->
380
392
do_equal? ( a_pointer , a_iterator , b_pointer , b_iterator )
381
393
@@ -390,6 +402,93 @@ defmodule Enum do
390
402
end
391
403
end
392
404
405
+ @ doc """
406
+ Returns true if the first collection is equal to the second, every element in
407
+ both collections is iterated through and compared with the passed function,
408
+ as soon as an element differs, it returns false.
409
+
410
+ Please note that the first parameter passed to the compare function isn't
411
+ ensured to be an element from the first collection.
412
+
413
+ ## Examples
414
+
415
+ iex> Enum.equal?([], [], &1 === &2)
416
+ true
417
+ iex> Enum.equal?([1 .. 3], [[1, 2, 3]], Enum.equal?(&1, &2))
418
+ true
419
+ iex> Enum.equal?(1 .. 3, [1.0, 2.0, 3.0], &1 === &2)
420
+ false
421
+ iex> Enum.equal?(1 .. 3, [], &1 === &2)
422
+ false
423
+
424
+ """
425
+ @ spec equal? ( t , t , ( ( term , term ) -> boolean ) ) :: boolean
426
+ def equal? ( [ ] , [ ] , _ ) do
427
+ true
428
+ end
429
+
430
+ def equal? ( a , b , _ ) when is_list ( a ) and is_list ( b ) and a == [ ] or b == [ ] do
431
+ false
432
+ end
433
+
434
+ def equal? ( a , b , fun ) when is_list ( a ) and is_list ( b ) do
435
+ do_equal_with? ( fun , a , b )
436
+ end
437
+
438
+ def equal? ( a , b , fun ) when is_list ( a ) do
439
+ equal? ( b , a , fun )
440
+ end
441
+
442
+ def equal? ( a , b , fun ) when is_list ( b ) do
443
+ case I . iterator ( a ) do
444
+ { _ , :stop } ->
445
+ b == [ ]
446
+
447
+ { iterator , pointer } ->
448
+ do_equal_with? ( fun , pointer , iterator , b )
449
+
450
+ list ->
451
+ do_equal_with? ( fun , list , b )
452
+ end
453
+ end
454
+
455
+ def equal? ( a , b , fun ) do
456
+ case { I . iterator ( a ) , I . iterator ( b ) } do
457
+ { { _ , :stop } , { _ , :stop } } ->
458
+ true
459
+
460
+ { { _ , :stop } , { _ , _ } } ->
461
+ false
462
+
463
+ { { _ , _ } , { _ , :stop } } ->
464
+ false
465
+
466
+ { { _ , :stop } , [ ] } ->
467
+ true
468
+
469
+ { [ ] , { _ , :stop } } ->
470
+ true
471
+
472
+ { { _ , :stop } , _ } ->
473
+ false
474
+
475
+ { _ , { _ , :stop } } ->
476
+ false
477
+
478
+ { { a_iterator , a_pointer } , { b_iterator , b_pointer } } ->
479
+ do_equal_with? ( fun , a_pointer , a_iterator , b_pointer , b_iterator )
480
+
481
+ { { iterator , pointer } , b } ->
482
+ do_equal_with? ( fun , pointer , iterator , b )
483
+
484
+ { a , { iterator , pointer } } ->
485
+ do_equal_with? ( fun , pointer , iterator , a )
486
+
487
+ { a , b } ->
488
+ do_equal_with? ( fun , a , b )
489
+ end
490
+ end
491
+
393
492
@ doc """
394
493
Filters the collection, i.e. returns only those elements
395
494
for which `fun` returns true.
@@ -1184,14 +1283,28 @@ defmodule Enum do
1184
1283
1185
1284
## equal?
1186
1285
1187
- defp do_equal? ( { a , _ } , _ , [ b | _ ] ) when a != b do
1286
+ # iterator : iterator
1287
+ defp do_equal? ( :stop , _ , :stop , _ ) do
1288
+ true
1289
+ end
1290
+
1291
+ defp do_equal? ( :stop , _ , _ , _ ) do
1188
1292
false
1189
1293
end
1190
1294
1191
- defp do_equal? ( { _ , a_next } , iterator , [ _ | b_next ] ) do
1192
- do_equal? ( iterator . ( a_next ) , iterator , b_next )
1295
+ defp do_equal? ( _ , _ , :stop , _ ) do
1296
+ false
1297
+ end
1298
+
1299
+ defp do_equal? ( { a , _ } , _ , { b , _ } , _ ) when a != b do
1300
+ false
1193
1301
end
1194
1302
1303
+ defp do_equal? ( { _ , a_next } , a_iterator , { _ , b_next } , b_iterator ) do
1304
+ do_equal? ( a_iterator . ( a_next ) , a_iterator , b_iterator . ( b_next ) , b_iterator )
1305
+ end
1306
+
1307
+ # iterator : list
1195
1308
defp do_equal? ( { _ , _ } , _ , [ ] ) do
1196
1309
false
1197
1310
end
@@ -1204,26 +1317,77 @@ defmodule Enum do
1204
1317
false
1205
1318
end
1206
1319
1207
- defp do_equal? ( { a , _a_next } , _a_iterator , { b , _b_next } , _b_iterator ) when a != b do
1320
+ defp do_equal? ( { a , _ } , _ , [ b | _ ] ) when a != b do
1208
1321
false
1209
1322
end
1210
1323
1211
- defp do_equal? ( { _a , a_next } , a_iterator , { _b , b_next } , b_iterator ) do
1212
- do_equal? ( a_iterator . ( a_next ) , a_iterator , b_iterator . ( b_next ) , b_iterator )
1324
+ defp do_equal? ( { _ , a_next } , iterator , [ _ | b_next ] ) do
1325
+ do_equal? ( iterator . ( a_next ) , iterator , b_next )
1213
1326
end
1214
1327
1215
- defp do_equal? ( :stop , _a_iterator , :stop , _b_iterator ) do
1328
+ # iterator : iterator
1329
+ defp do_equal_with? ( _ , :stop , _ , :stop , _ ) do
1216
1330
true
1217
1331
end
1218
1332
1219
- defp do_equal? ( :stop , _a_iterator , _b_pointer , _b_iterator ) do
1333
+ defp do_equal_with? ( _ , :stop , _ , _ , _ ) do
1220
1334
false
1221
1335
end
1222
1336
1223
- defp do_equal? ( _a_pointer , _a_iterator , :stop , _b_iterator ) do
1337
+ defp do_equal_with? ( _ , _ , _ , :stop , _ ) do
1224
1338
false
1225
1339
end
1226
1340
1341
+ defp do_equal_with? ( fun , { a , a_next } , a_iterator , { b , b_next } , b_iterator ) do
1342
+ if fun . ( a , b ) do
1343
+ do_equal_with? ( fun , a_iterator . ( a_next ) , a_iterator , b_iterator . ( b_next ) , b_iterator )
1344
+ else
1345
+ false
1346
+ end
1347
+ end
1348
+
1349
+ # iterator : list
1350
+ defp do_equal_with? ( _ , :stop , _ , [ ] ) do
1351
+ true
1352
+ end
1353
+
1354
+ defp do_equal_with? ( _ , :stop , _ , _ ) do
1355
+ false
1356
+ end
1357
+
1358
+ defp do_equal_with? ( _ , { _ , _ } , _ , [ ] ) do
1359
+ false
1360
+ end
1361
+
1362
+ defp do_equal_with? ( fun , { a , a_next } , iterator , [ b | b_next ] ) do
1363
+ if fun . ( a , b ) do
1364
+ do_equal_with? ( fun , iterator . ( a_next ) , iterator , b_next )
1365
+ else
1366
+ false
1367
+ end
1368
+ end
1369
+
1370
+ # list : list
1371
+ defp do_equal_with? ( _ , [ ] , [ ] ) do
1372
+ true
1373
+ end
1374
+
1375
+ defp do_equal_with? ( _ , [ ] , _ ) do
1376
+ false
1377
+ end
1378
+
1379
+ defp do_equal_with? ( _ , _ , [ ] ) do
1380
+ false
1381
+ end
1382
+
1383
+ defp do_equal_with? ( fun , [ a | a_next ] , [ b | b_next ] ) do
1384
+ if fun . ( a , b ) do
1385
+ do_equal_with? ( fun , a_next , b_next )
1386
+ else
1387
+ false
1388
+ end
1389
+ end
1390
+
1227
1391
## find
1228
1392
1229
1393
defp do_find ( [ h | t ] , ifnone , fun ) do
0 commit comments