|
| 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