or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

backported-collections.mdcollection-extensions.mdindex.mdjava-conversion.mdresource-management.mdstring-parsing.mdutility-features.md

collection-extensions.mddocs/

0

# Collection Extensions

1

2

Enhanced methods for existing Scala collections including safe operations, size comparisons, and functional utilities. These extensions provide Scala 2.13-style APIs on older Scala versions through implicit conversions.

3

4

## Capabilities

5

6

### Safe Min/Max Operations

7

8

Safe minimum and maximum operations that return Option instead of throwing exceptions on empty collections.

9

10

```scala { .api }

11

/**

12

* Returns the minimum element as an Option, or None if empty

13

* @param ord Ordering for elements

14

* @return Some(minimum) or None if collection is empty

15

*/

16

def minOption[B >: A](implicit ord: Ordering[B]): Option[A]

17

18

/**

19

* Returns the maximum element as an Option, or None if empty

20

* @param ord Ordering for elements

21

* @return Some(maximum) or None if collection is empty

22

*/

23

def maxOption[B >: A](implicit ord: Ordering[B]): Option[A]

24

25

/**

26

* Returns the minimum element by function as an Option

27

* @param f Function to extract comparison key

28

* @param cmp Ordering for comparison keys

29

* @return Some(minimum) or None if collection is empty

30

*/

31

def minByOption[B](f: A => B)(implicit cmp: Ordering[B]): Option[A]

32

33

/**

34

* Returns the maximum element by function as an Option

35

* @param f Function to extract comparison key

36

* @param cmp Ordering for comparison keys

37

* @return Some(maximum) or None if collection is empty

38

*/

39

def maxByOption[B](f: A => B)(implicit cmp: Ordering[B]): Option[A]

40

```

41

42

**Usage Examples:**

43

44

```scala

45

import scala.collection.compat._

46

47

val numbers = List(3, 1, 4, 1, 5)

48

val empty = List.empty[Int]

49

50

numbers.minOption // Some(1)

51

numbers.maxOption // Some(5)

52

empty.minOption // None

53

empty.maxOption // None

54

55

// Min/max by function

56

case class Person(name: String, age: Int)

57

val people = List(Person("Alice", 25), Person("Bob", 30))

58

people.minByOption(_.age) // Some(Person("Alice", 25))

59

people.maxByOption(_.age) // Some(Person("Bob", 30))

60

```

61

62

### Size Comparison Operations

63

64

Efficient size comparison methods that can short-circuit evaluation for large collections.

65

66

```scala { .api }

67

/**

68

* Compare collection size with an integer

69

* @param otherSize Size to compare against

70

* @return Negative if smaller, 0 if equal, positive if larger

71

*/

72

def sizeCompare(otherSize: Int): Int

73

74

/**

75

* Compare collection size with another collection

76

* @param that Collection to compare size against

77

* @return Negative if smaller, 0 if equal, positive if larger

78

*/

79

def sizeCompare(that: Traversable[_]): Int

80

81

/**

82

* Get size comparison operations object

83

* @return SizeCompareOps for fluent size testing

84

*/

85

def sizeIs: SizeCompareOps

86

87

class SizeCompareOps {

88

def <(size: Int): Boolean

89

def <=(size: Int): Boolean

90

def ==(size: Int): Boolean

91

def !=(size: Int): Boolean

92

def >=(size: Int): Boolean

93

def >(size: Int): Boolean

94

}

95

```

96

97

**Usage Examples:**

98

99

```scala

100

import scala.collection.compat._

101

102

val data = List(1, 2, 3, 4, 5)

103

104

// Direct size comparison

105

data.sizeCompare(3) // Positive (> 0)

106

data.sizeCompare(5) // 0 (equal)

107

data.sizeCompare(10) // Negative (< 0)

108

109

// Fluent size testing

110

if (data.sizeIs > 3) println("Large collection")

111

if (data.sizeIs <= 10) println("Manageable size")

112

113

// Efficient for lazy collections

114

val stream = Stream.from(1)

115

if (stream.sizeIs > 100) println("This won't evaluate the entire stream")

116

```

117

118

### Enhanced Functional Operations

119

120

Advanced functional operations including grouping, partitioning, and deduplication.

121

122

```scala { .api }

123

/**

124

* Remove duplicate elements based on a key function

125

* @param f Function to extract comparison key

126

* @param cbf CanBuildFrom for result collection

127

* @return Collection with duplicates removed

128

*/

129

def distinctBy[B, That](f: A => B)(implicit cbf: CanBuildFrom[Repr, A, That]): That

130

131

/**

132

* Group elements by key and transform values in one operation

133

* @param key Function to extract grouping key

134

* @param f Function to transform values

135

* @param bf CanBuildFrom for value collections

136

* @return Map of grouped and transformed values

137

*/

138

def groupMap[K, B, That](key: A => K)(f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): Map[K, That]

139

140

/**

141

* Group elements by key, transform values, and reduce to single value per group

142

* @param key Function to extract grouping key

143

* @param f Function to transform values

144

* @param reduce Function to reduce multiple values to one

145

* @return Map with single reduced value per group

146

*/

147

def groupMapReduce[K, B](key: A => K)(f: A => B)(reduce: (B, B) => B): Map[K, B]

148

149

/**

150

* Partition elements and transform them simultaneously

151

* @param f Function returning Either for partitioning and transformation

152

* @param bf1 CanBuildFrom for left partition

153

* @param bf2 CanBuildFrom for right partition

154

* @return Tuple of (left partition, right partition)

155

*/

156

def partitionMap[A1, A2, That, Repr1, Repr2](f: A => Either[A1, A2])(implicit bf1: CanBuildFrom[Repr, A1, Repr1], bf2: CanBuildFrom[Repr, A2, Repr2]): (Repr1, Repr2)

157

```

158

159

**Usage Examples:**

160

161

```scala

162

import scala.collection.compat._

163

164

val people = List("Alice", "Bob", "Alice", "Charlie", "Bob")

165

166

// Remove duplicates by function

167

people.distinctBy(_.length) // List("Alice", "Bob")

168

169

// Group and map in one operation

170

val words = List("apple", "apricot", "banana", "blueberry")

171

words.groupMap(_.head.toUpper)(_.length)

172

// Map('A' -> List(5, 7), 'B' -> List(6, 9))

173

174

// Group, map and reduce

175

words.groupMapReduce(_.head.toUpper)(_.length)(_ + _)

176

// Map('A' -> 12, 'B' -> 15)

177

178

// Partition and map simultaneously

179

val numbers = List(1, 2, 3, 4, 5)

180

numbers.partitionMap(n => if (n % 2 == 0) Left(n * 2) else Right(n.toString))

181

// (List(4, 8), List("1", "3", "5"))

182

```

183

184

### Side Effect Operations

185

186

Operations that apply side effects while preserving the original collection structure.

187

188

```scala { .api }

189

/**

190

* Apply a side effect to each element and return the original collection

191

* @param f Side effect function

192

* @param bf CanBuildFrom for result collection

193

* @return Original collection unchanged

194

*/

195

def tapEach[U](f: A => U)(implicit bf: CanBuildFrom[Repr, A, Repr]): Repr

196

```

197

198

**Usage Examples:**

199

200

```scala

201

import scala.collection.compat._

202

203

val numbers = List(1, 2, 3, 4, 5)

204

205

// Apply side effect (logging) while preserving the collection

206

val result = numbers

207

.tapEach(n => println(s"Processing: $n"))

208

.map(_ * 2)

209

.tapEach(n => println(s"Result: $n"))

210

211

// Useful for debugging pipelines

212

val processed = data

213

.filter(predicate)

214

.tapEach(item => logger.debug(s"After filter: $item"))

215

.map(transform)

216

.tapEach(item => logger.debug(s"After transform: $item"))

217

```

218

219

### Map-Specific Extensions

220

221

Special extension methods for Map collections including atomic updates and entry iteration.

222

223

```scala { .api }

224

/**

225

* Apply function to each key-value pair (more efficient than foreach on tuples)

226

* @param f Function to apply to each key-value pair

227

*/

228

def foreachEntry[U](f: (K, V) => U): Unit

229

230

/**

231

* Update map with remapping function (immutable maps)

232

* @param key Key to update

233

* @param remappingFunction Function that receives current value and returns new value

234

* @return New map with updated value

235

*/

236

def updatedWith[V1 >: V](key: K)(remappingFunction: (Option[V]) => Option[V1]): Map[K, V1]

237

238

/**

239

* Update map with remapping function (mutable maps)

240

* @param key Key to update

241

* @param remappingFunction Function that receives current value and returns new value

242

* @return Previous value if any

243

*/

244

def updateWith(key: K)(remappingFunction: (Option[V]) => Option[V]): Option[V]

245

```

246

247

**Usage Examples:**

248

249

```scala

250

import scala.collection.compat._

251

252

val scores = Map("Alice" -> 85, "Bob" -> 92, "Charlie" -> 78)

253

254

// Efficient entry iteration

255

scores.foreachEntry { (name, score) =>

256

println(s"$name scored $score")

257

}

258

259

// Atomic map updates

260

val updated = scores.updatedWith("Alice") {

261

case Some(score) => Some(score + 10) // Bonus points

262

case None => Some(50) // Default score

263

}

264

265

// For mutable maps

266

val mutableScores = scala.collection.mutable.Map("Alice" -> 85)

267

val previousScore = mutableScores.updateWith("Alice")(_.map(_ + 5))

268

```

269

270

### Iterator Extensions

271

272

Enhanced iterator operations including safe element access and concatenation.

273

274

```scala { .api }

275

/**

276

* Safe next element access

277

* @return Some(next element) or None if iterator is empty

278

*/

279

def nextOption(): Option[A]

280

281

/**

282

* Check if iterator elements are the same as collection elements

283

* @param that Collection to compare against

284

* @return true if all elements are equal in order

285

*/

286

def sameElements[B >: A](that: TraversableOnce[B]): Boolean

287

288

/**

289

* Concatenate iterator with another collection

290

* @param that Collection to concatenate

291

* @return Combined traversable

292

*/

293

def concat[B >: A](that: TraversableOnce[B]): TraversableOnce[B]

294

```

295

296

**Usage Examples:**

297

298

```scala

299

import scala.collection.compat._

300

301

val iter = List(1, 2, 3).iterator

302

303

// Safe element access

304

while (iter.nextOption.isDefined) {

305

// Process elements safely

306

}

307

308

// Element comparison

309

val iter1 = List(1, 2, 3).iterator

310

val list2 = List(1, 2, 3)

311

iter1.sameElements(list2) // true

312

313

// Iterator concatenation

314

val combined = List(1, 2).iterator.concat(List(3, 4))

315

```