Skip to content

Commit 5093a84

Browse files
committed
add FLIP for adding minOf/maxOf functions to Cadence
1 parent a911bbc commit 5093a84

1 file changed

Lines changed: 225 additions & 0 deletions

File tree

Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
---
2+
status: draft
3+
flip: 357
4+
authors: Bastian Müller (bastian.mueller@flowfoundation.org)
5+
updated: 2026-02-09
6+
---
7+
8+
# FLIP 357: Add minOf and maxOf Functions to Cadence
9+
10+
## Objective
11+
12+
Add `minOf` and `maxOf` functions to the Cadence standard library,
13+
providing a convenient way to find the minimum or maximum of two comparable values.
14+
15+
## Motivation
16+
17+
Finding the minimum or maximum of two values is a common operation in smart contract development.
18+
Currently, developers must implement this logic manually using conditional expressions:
19+
20+
```cadence
21+
// Current approach: manual comparison
22+
let smaller = a < b ? a : b
23+
let larger = a > b ? a : b
24+
```
25+
26+
While this works, it has several drawbacks:
27+
- **Verbose**: Requires writing the comparison logic repeatedly
28+
- **Error-prone**: Easy to make mistakes with the comparison operators or the ternary expression
29+
- **Less readable**: The intent isn't immediately clear, especially in complex expressions
30+
31+
Other programming languages provide built-in or standard library functions for this common operation.
32+
Having standard functions improves code readability and reduces the likelihood of errors.
33+
34+
## User Benefit
35+
36+
The `minOf` and `maxOf` functions provide several benefits:
37+
38+
**Improved Readability**: The intent is immediately clear from the function name:
39+
```cadence
40+
let price = minOf(bidPrice, maxPrice) // Clearer than: bidPrice < maxPrice ? bidPrice : maxPrice
41+
```
42+
43+
**Reduced Errors**: Eliminates the risk of swapping comparison operators or ternary branches,
44+
or accidentally comparing the wrong variables.
45+
46+
**Type Safety**: The functions work with any comparable type and ensure both arguments have the same type,
47+
catching type mismatches at compile time.
48+
49+
**Consistency**: Provides a standard way to perform these operations across all Cadence codebases.
50+
51+
## Design Proposal
52+
53+
Add two generic functions to the Cadence standard library that work with any comparable type.
54+
55+
### Function Signatures
56+
57+
```cadence
58+
/// Returns the minimum of two values
59+
///
60+
/// The arguments must be of the same comparable type.
61+
///
62+
/// Examples:
63+
/// minOf(5, 10) == 5
64+
/// minOf(10, 5) == 5
65+
/// minOf(1.5, 2.5) == 1.5
66+
/// minOf("apple", "banana") == "apple"
67+
///
68+
access(all) fun minOf<T>(_ a: T, _ b: T): T
69+
70+
/// Returns the maximum of two values
71+
///
72+
/// The arguments must be of the same comparable type.
73+
///
74+
/// Examples:
75+
/// maxOf(5, 10) == 10
76+
/// maxOf(10, 5) == 10
77+
/// maxOf(1.5, 2.5) == 2.5
78+
/// maxOf("apple", "banana") == "banana"
79+
///
80+
access(all) fun maxOf<T>(_ a: T, _ b: T): T
81+
```
82+
83+
### Type Requirements
84+
85+
The type parameter `T` must be a **comparable type**.
86+
In Cadence, comparable types are those that support comparison operators (`<`, `>`, `<=`, `>=`),
87+
e.g. all concrete number types, strings, characters, booleans, and addresses.
88+
89+
### Naming Rationale
90+
91+
The functions are named `minOf` and `maxOf` (rather than `min` and `max`) to avoid naming conflicts:
92+
- Number types already have `min` and `max` fields,
93+
which represent the minimum and maximum values of that type, e.g. `Int8.min` is the minimum value of `Int8`
94+
- Existing contracts may have defined `min` and `max` variables or functions,
95+
so using `minOf` and `maxOf` avoids potential conflicts.
96+
As of 2026-02-09, there are no global functions named `minOf` or `maxOf`, so this naming is safe.
97+
- Kotlin uses the names `minOf` and `maxOf`, see e.g. https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.comparisons/min-of.html
98+
99+
## Drawbacks
100+
101+
**Limited to Two Arguments**: The functions only accept two arguments. Finding the minimum or maximum
102+
of more values requires chaining:
103+
104+
```cadence
105+
let min = minOf(minOf(a, b), c)
106+
```
107+
108+
A future enhancement could add variadic versions that accept more than two arguments.
109+
110+
## Alternatives Considered
111+
112+
### Alternative 1: Methods
113+
114+
Add `min(_ other: T)` and `max(_ other: T)` methods to comparable types `T`:
115+
116+
```cadence
117+
a.min(b) // Returns the minimum of a and b
118+
a.max(b) // Returns the maximum of a and b
119+
```
120+
121+
**Pros:**
122+
- Intuitive method syntax
123+
- No naming conflict
124+
125+
**Cons:**
126+
- Requires many separate implementations (one per comparable type)
127+
128+
### Alternative 2: Static Methods
129+
130+
Add `minimum()` and `maximum()` methods to each comparable type:
131+
132+
```cadence
133+
Int8.minimum(5, 10)
134+
UFix64.maximum(1.5, 2.5)
135+
```
136+
137+
**Pros:**
138+
- More discoverable through type-specific documentation
139+
- No naming conflict
140+
141+
**Cons:**
142+
- More verbose
143+
- Requires many separate implementations (one per comparable type)
144+
- Users must remember type-specific methods instead of a single global function
145+
146+
## Performance Implications
147+
148+
The functions are implemented as native functions,
149+
so they will have minimal overhead compared to manual comparisons.
150+
151+
## Compatibility
152+
153+
This is a purely additive feature.
154+
155+
However, to ensure no breaking changes to existing contracts,
156+
the proposal currently assumes that existing contracts do not declare variables or functions named
157+
`minOf` or `maxOf`, which is true as of 2026-02-09.
158+
If a conflict is detected, we may need to consider alternative names,
159+
or an alternative design such as methods on comparable types.
160+
161+
## Prior Art
162+
163+
Nearly all major programming languages provide minimum/maximum functions:
164+
165+
**Python**:
166+
167+
Global functions that work with any comparable type:
168+
169+
```python
170+
min(a, b)
171+
max(a, b)
172+
```
173+
174+
**JavaScript**:
175+
176+
Functions that only work with numbers, not with strings or other comparable types:
177+
178+
```javascript
179+
Math.min(a, b)
180+
Math.max(a, b)
181+
```
182+
183+
**Rust**:
184+
185+
Methods on comparable types:
186+
187+
```rust
188+
a.min(b)
189+
a.max(b)
190+
```
191+
192+
**Swift**:
193+
194+
Global functions that work with any comparable type:
195+
196+
```swift
197+
min(a, b)
198+
max(a, b)
199+
```
200+
201+
**Kotlin**:
202+
203+
Global functions that work with any comparable type:
204+
205+
```kotlin
206+
minOf(a, b)
207+
maxOf(a, b)
208+
```
209+
210+
Cadence's design follows the Kotlin naming convention, which also distinguishes comparison functions
211+
from value range constants.
212+
213+
## Implementation
214+
215+
An implementation is available at: https://github.com/onflow/cadence/pull/4430
216+
217+
## Related Issues
218+
219+
None
220+
221+
## Questions and Discussion Topics
222+
223+
1. Should we rather use method syntax instead of global functions, or static methods on each comparable type?
224+
2. Should we add variants that accept more than two arguments in the future?
225+
3. Should we add `clamp(value, min, max)` as a related utility function?

0 commit comments

Comments
 (0)