@@ -8,8 +8,8 @@ assert_eq(min([1, 2], [3]), [1, 2])
88assert_eq (min ([1 , 5 ], [1 , 6 ], [2 , 4 ], [0 , 6 ]), [0 , 6 ])
99assert_eq (min ([- 1 ]), - 1 )
1010assert_eq (min ([5 , 2 , 3 ]), 2 )
11- assert_eq (min ({1 : 2 , - 1 : 3 }), - 1 )
12- assert_eq (min ({2 : None }), 2 )
11+ assert_eq (min ({1 : 2 , - 1 : 3 }), - 1 ) # a single dict argument is treated as its sequence of keys
12+ assert_eq (min ({2 : None }), 2 ) # a single dict argument is treated as its sequence of keys
1313assert_eq (min (- 1 , 2 ), - 1 )
1414assert_eq (min (5 , 2 , 3 ), 2 )
1515assert_eq (min (1 , 1 , 1 , 1 , 1 , 1 ), 1 )
@@ -21,15 +21,62 @@ assert_fails(lambda: min([]), "expected at least one item")
2121assert_fails (lambda : min (1 , "2" , True ), "unsupported comparison: int <=> string" )
2222assert_fails (lambda : min ([1 , "2" , True ]), "unsupported comparison: int <=> string" )
2323
24+ # min with key
25+ assert_eq (min ("aBcDeFXyZ" .elems (), key = lambda s : s .upper ()), "a" )
26+ assert_eq (min ("test" , "xyz" , key = len ), "xyz" )
27+ assert_eq (min ([4 , 5 ], [1 ], key = lambda x : x ), [1 ])
28+ assert_eq (min ([1 , 2 ], [3 ], key = lambda x : x ), [1 , 2 ])
29+ assert_eq (min ([1 , 5 ], [1 , 6 ], [2 , 4 ], [0 , 6 ], key = lambda x : x ), [0 , 6 ])
30+ assert_eq (min ([1 , 5 ], [1 , 6 ], [2 , 4 ], [0 , 6 ], key = lambda x : x [1 ]), [2 , 4 ])
31+ assert_eq (min ([- 1 ], key = lambda x : x ), - 1 )
32+ assert_eq (min ([5 , 2 , 3 ], key = lambda x : x ), 2 )
33+ assert_eq (min ({1 : 2 , - 1 : 3 }, key = lambda x : x ), - 1 ) # a single dict argument is treated as its sequence of keys
34+ assert_eq (min ({2 : None }, key = lambda x : x ), 2 ) # a single dict argument is treated as its sequence of keys
35+ assert_eq (min (- 1 , 2 , key = lambda x : x ), - 1 )
36+ assert_eq (min (5 , 2 , 3 , key = lambda x : x ), 2 )
37+ assert_eq (min (1 , 1 , 1 , 1 , 1 , 1 , key = lambda x : - x ), 1 )
38+ assert_eq (min ([1 , 1 , 1 , 1 , 1 , 1 ], key = lambda x : - x ), 1 )
39+ assert_fails (lambda : min (1 , key = lambda x : x ), "type 'int' is not iterable" )
40+ assert_fails (lambda : min (key = lambda x : x ), "expected at least one item" )
41+ assert_fails (lambda : min ([], key = lambda x : x ), "expected at least one item" )
42+ assert_fails (lambda : min ([1 ], ["2" ], [True ], key = lambda x : x [0 ]), "unsupported comparison: (int <=> string|string <=> int)" )
43+ assert_fails (lambda : min ([[1 ], ["2" ], [True ]], key = lambda x : x [0 ]), "unsupported comparison: (int <=> string|string <=> int)" )
44+
45+ # verify min with key chooses first value with minimal key
46+ assert_eq (min (1 , - 1 , - 2 , 2 , key = abs ), 1 )
47+ assert_eq (min ([1 , - 1 , - 2 , 2 ], key = abs ), 1 )
48+
49+ # min with failing key
50+ assert_fails (lambda : min (0 , 1 , 2 , 3 , 4 , key = lambda x : "foo" .elems ()[x ]), "index out of range \\ (index is 3, but sequence has 3 elements\\ )" )
51+ assert_fails (lambda : min ([0 , 1 , 2 , 3 , 4 ], key = lambda x : "foo" .elems ()[x ]), "index out of range \\ (index is 3, but sequence has 3 elements\\ )" )
52+
53+ # min with non-callable key
54+ assert_fails (lambda : min (1 , 2 , 3 , key = "hello" ), "parameter 'key' got value of type 'string', want 'callable or NoneType'" )
55+ assert_fails (lambda : min ([1 , 2 , 3 ], key = "hello" ), "parameter 'key' got value of type 'string', want 'callable or NoneType'" )
56+
57+ # verify min with key invokes key callback exactly once per item
58+ def make_counting_identity ():
59+ call_count = {}
60+
61+ def counting_identity (x ):
62+ call_count [x ] = call_count .get (x , 0 ) + 1
63+ return x
64+
65+ return counting_identity , call_count
66+
67+ min_counting_identity , min_call_count = make_counting_identity ()
68+ assert_eq (min ("min" .elems (), key = min_counting_identity ), "i" )
69+ assert_eq (min_call_count , {"m" : 1 , "i" : 1 , "n" : 1 })
70+
2471# max
2572assert_eq (max ("abcdefxyz" .elems ()), "z" )
2673assert_eq (max ("test" , "xyz" ), "xyz" )
2774assert_eq (max ("test" , "xyz" ), "xyz" )
2875assert_eq (max ([1 , 2 ], [5 ]), [5 ])
2976assert_eq (max ([- 1 ]), - 1 )
3077assert_eq (max ([5 , 2 , 3 ]), 5 )
31- assert_eq (max ({1 : 2 , - 1 : 3 }), 1 )
32- assert_eq (max ({2 : None }), 2 )
78+ assert_eq (max ({1 : 2 , - 1 : 3 }), 1 ) # a single dict argument is treated as its sequence of keys
79+ assert_eq (max ({2 : None }), 2 ) # a single dict argument is treated as its sequence of keys
3380assert_eq (max (- 1 , 2 ), 2 )
3481assert_eq (max (5 , 2 , 3 ), 5 )
3582assert_eq (max (1 , 1 , 1 , 1 , 1 , 1 ), 1 )
@@ -40,3 +87,38 @@ assert_fails(lambda: max(), "expected at least one item")
4087assert_fails (lambda : max ([]), "expected at least one item" )
4188assert_fails (lambda : max (1 , "2" , True ), "unsupported comparison: int <=> string" )
4289assert_fails (lambda : max ([1 , "2" , True ]), "unsupported comparison: int <=> string" )
90+
91+ # max with key
92+ assert_eq (max ("aBcDeFXyZ" .elems (), key = lambda s : s .lower ()), "Z" )
93+ assert_eq (max ("test" , "xyz" , key = len ), "test" )
94+ assert_eq (max ([1 , 2 ], [5 ], key = lambda x : x ), [5 ])
95+ assert_eq (max ([- 1 ], key = lambda x : x ), - 1 )
96+ assert_eq (max ([5 , 2 , 3 ], key = lambda x : x ), 5 )
97+ assert_eq (max ({1 : 2 , - 1 : 3 }, key = lambda x : x ), 1 ) # a single dict argument is treated as its sequence of keys
98+ assert_eq (max ({2 : None }, key = lambda x : x ), 2 ) # a single dict argument is treated as its sequence of keys
99+ assert_eq (max (- 1 , 2 , key = lambda x : x ), 2 )
100+ assert_eq (max (5 , 2 , 3 , key = lambda x : x ), 5 )
101+ assert_eq (max (1 , 1 , 1 , 1 , 1 , 1 , key = lambda x : - x ), 1 )
102+ assert_eq (max ([1 , 1 , 1 , 1 , 1 , 1 ], key = lambda x : - x ), 1 )
103+ assert_fails (lambda : max (1 , key = lambda x : x ), "type 'int' is not iterable" )
104+ assert_fails (lambda : max (key = lambda x : x ), "expected at least one item" )
105+ assert_fails (lambda : max ([], key = lambda x : x ), "expected at least one item" )
106+ assert_fails (lambda : max ([1 ], ["2" ], [True ], key = lambda x : x [0 ]), "unsupported comparison: (int <=> string|string <=> int)" )
107+ assert_fails (lambda : max ([[1 ], ["2" ], [True ]], key = lambda x : x [0 ]), "unsupported comparison: (int <=> string|string <=> int)" )
108+
109+ # verify max with key chooses first value with minimal key
110+ assert_eq (max (1 , - 1 , - 2 , 2 , key = abs ), - 2 )
111+ assert_eq (max ([1 , - 1 , - 2 , 2 ], key = abs ), - 2 )
112+
113+ # max with failing key
114+ assert_fails (lambda : max (0 , 1 , 2 , 3 , 4 , key = lambda i : "xyz" .elems ()[i ]), "index out of range \\ (index is 3, but sequence has 3 elements\\ )" )
115+ assert_fails (lambda : max ([0 , 1 , 2 , 3 , 4 ], key = lambda i : "xyz" .elems ()[i ]), "index out of range \\ (index is 3, but sequence has 3 elements\\ )" )
116+
117+ # max with non-callable key
118+ assert_fails (lambda : max (1 , 2 , 3 , key = "hello" ), "parameter 'key' got value of type 'string', want 'callable or NoneType'" )
119+ assert_fails (lambda : max ([1 , 2 , 3 ], key = "hello" ), "parameter 'key' got value of type 'string', want 'callable or NoneType'" )
120+
121+ # verify max with key invokes key callback exactly once per item
122+ max_counting_identity , max_call_count = make_counting_identity ()
123+ assert_eq (max ("max" .elems (), key = max_counting_identity ), "x" )
124+ assert_eq (max_call_count , {"m" : 1 , "a" : 1 , "x" : 1 })
0 commit comments