@@ -449,23 +449,19 @@ mod decl {
449
449
locals. copy ( ) . into_ref ( vm)
450
450
}
451
451
452
- #[ pyfunction]
453
- fn max ( mut args : FuncArgs , vm : & VirtualMachine ) -> PyResult {
452
+ fn min_or_max ( mut args : FuncArgs , vm : & VirtualMachine , func_name : & str , op : PyComparisonOp ) -> PyResult {
454
453
let default = args. take_keyword ( "default" ) ;
455
- let key_func = args. take_keyword ( "key" ) ;
456
- if !args. kwargs . is_empty ( ) {
457
- let invalid_keyword = args. kwargs . get_index ( 0 ) . unwrap ( ) ;
458
- return Err ( vm. new_type_error ( format ! (
459
- "'{}' is an invalid keyword argument for max()" ,
460
- invalid_keyword. 0
461
- ) ) ) ;
454
+ let mut key_func = args. take_keyword ( "key" ) ;
455
+
456
+ if let Some ( err) = args. check_kwargs_empty ( vm) {
457
+ return Err ( err) ;
462
458
}
459
+
463
460
let candidates = match args. args . len ( ) . cmp ( & 1 ) {
464
461
std:: cmp:: Ordering :: Greater => {
465
462
if default. is_some ( ) {
466
463
return Err ( vm. new_type_error (
467
- "Cannot specify a default for max() with multiple positional arguments"
468
- . to_owned ( ) ,
464
+ format ! ( "Cannot specify a default for {} with multiple positional arguments" , func_name) ,
469
465
) ) ;
470
466
}
471
467
args. args
@@ -482,7 +478,7 @@ mod decl {
482
478
Some ( x) => x,
483
479
None => {
484
480
return default
485
- . ok_or_else ( || vm. new_value_error ( "max() arg is an empty sequence". to_owned ( ) ) )
481
+ . ok_or_else ( || vm. new_value_error ( format ! ( "{} arg is an empty sequence", func_name ) ) )
486
482
}
487
483
} ;
488
484
@@ -491,14 +487,14 @@ mod decl {
491
487
let mut x_key = vm. invoke ( key_func, ( x. clone ( ) , ) ) ?;
492
488
for y in candidates_iter {
493
489
let y_key = vm. invoke ( key_func, ( y. clone ( ) , ) ) ?;
494
- if vm. bool_cmp ( & y_key, & x_key, PyComparisonOp :: Gt ) ? {
490
+ if vm. bool_cmp ( & y_key, & x_key, op ) ? {
495
491
x = y;
496
492
x_key = y_key;
497
493
}
498
494
}
499
495
} else {
500
496
for y in candidates_iter {
501
- if vm. bool_cmp ( & y, & x, PyComparisonOp :: Gt ) ? {
497
+ if vm. bool_cmp ( & y, & x, op ) ? {
502
498
x = y;
503
499
}
504
500
}
@@ -507,65 +503,15 @@ mod decl {
507
503
Ok ( x)
508
504
}
509
505
510
- #[ pyfunction]
511
- fn min ( mut args : FuncArgs , vm : & VirtualMachine ) -> PyResult {
512
- let ( candidates, default_allowed) = match args. args . len ( ) . cmp ( & 1 ) {
513
- std:: cmp:: Ordering :: Greater => ( args. args . clone ( ) , false ) ,
514
- std:: cmp:: Ordering :: Equal => ( vm. extract_elements ( & args. args [ 0 ] ) ?, true ) ,
515
- std:: cmp:: Ordering :: Less => {
516
- // zero arguments means type error:
517
- return Err ( vm. new_type_error ( "Expected 1 or more arguments" . to_owned ( ) ) ) ;
518
- }
519
- } ;
520
-
521
- let default = args. take_keyword ( "default" ) ;
522
- let mut key_func = args. take_keyword ( "key" ) ;
523
-
524
- if let Some ( err) = args. check_kwargs_empty ( vm) {
525
- return Err ( err) ;
526
- }
527
506
528
- if default. is_some ( ) && !default_allowed {
529
- return Err ( vm. new_type_error (
530
- "Specifying default not allowed with more than 1 argument" . to_owned ( ) ,
531
- ) ) ;
532
- }
533
-
534
- if candidates. is_empty ( ) {
535
- return default
536
- . ok_or_else ( || vm. new_value_error ( "min() arg is an empty sequence" . to_owned ( ) ) ) ;
537
- }
538
-
539
- if let Some ( ref obj) = key_func {
540
- if vm. is_none ( obj) {
541
- key_func = None
542
- }
543
- }
544
-
545
- let mut candidates_iter = candidates. into_iter ( ) ;
546
- let mut x = candidates_iter. next ( ) . unwrap ( ) ;
547
- // TODO: this key function looks pretty duplicate. Maybe we can create
548
- // a local function?
549
- let mut x_key = if let Some ( ref f) = & key_func {
550
- vm. invoke ( f, ( x. clone ( ) , ) ) ?
551
- } else {
552
- x. clone ( )
553
- } ;
554
-
555
- for y in candidates_iter {
556
- let y_key = if let Some ( ref f) = & key_func {
557
- vm. invoke ( f, ( y. clone ( ) , ) ) ?
558
- } else {
559
- y. clone ( )
560
- } ;
561
-
562
- if vm. bool_cmp ( & x_key, & y_key, PyComparisonOp :: Gt ) ? {
563
- x = y. clone ( ) ;
564
- x_key = y_key;
565
- }
566
- }
507
+ #[ pyfunction]
508
+ fn max ( mut args : FuncArgs , vm : & VirtualMachine ) -> PyResult {
509
+ min_or_max ( args, vm, "max()" , PyComparisonOp :: Gt )
510
+ }
567
511
568
- Ok ( x)
512
+ #[ pyfunction]
513
+ fn min ( mut args : FuncArgs , vm : & VirtualMachine ) -> PyResult {
514
+ min_or_max ( args, vm, "min()" , PyComparisonOp :: Lt )
569
515
}
570
516
571
517
#[ pyfunction]
0 commit comments