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

utility-features.mddocs/

0

# Utility Features

1

2

Additional utilities including chaining operations, annotations for cross-compilation, enhanced regex functionality, and other helper features that improve code quality and cross-version compatibility.

3

4

## Capabilities

5

6

### Chaining Operations

7

8

Fluent interface methods that enable method chaining and functional programming patterns on any type.

9

10

```scala { .api }

11

/**

12

* Trait providing chaining syntax for all types

13

*/

14

trait ChainingSyntax {

15

/**

16

* Add chaining methods to any type

17

* @param a Value to add chaining methods to

18

* @return ChainingOps instance with chaining methods

19

*/

20

implicit final def scalaUtilChainingOps[A](a: A): ChainingOps[A]

21

}

22

23

/**

24

* Import target for chaining operations

25

*/

26

object chaining extends ChainingSyntax

27

28

/**

29

* Value class providing chaining methods

30

* @param self The wrapped value

31

*/

32

final class ChainingOps[A](self: A) extends AnyVal {

33

/**

34

* Apply side effect function and return original value

35

* Useful for debugging, logging, or other side effects in method chains

36

* @param f Side effect function

37

* @return Original value unchanged

38

*/

39

def tap[U](f: A => U): A

40

41

/**

42

* Transform value by applying function (alias for function application)

43

* Useful for applying transformations in a fluent style

44

* @param f Transformation function

45

* @return Transformed value

46

*/

47

def pipe[B](f: A => B): B

48

}

49

```

50

51

**Usage Examples:**

52

53

```scala

54

import scala.util.chaining._

55

56

// Basic tap usage for side effects

57

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

58

.filter(_ % 2 == 0)

59

.tap(filtered => println(s"After filter: $filtered"))

60

.map(_ * 2)

61

.tap(mapped => println(s"After map: $mapped"))

62

63

// Pipe for transformations

64

val processed = "hello world"

65

.pipe(_.split(" "))

66

.pipe(_.map(_.capitalize))

67

.pipe(_.mkString("-"))

68

// Result: "Hello-World"

69

70

// Debugging chains with tap

71

val calculation = 42

72

.tap(x => println(s"Starting with: $x"))

73

.pipe(_ * 2)

74

.tap(x => println(s"After doubling: $x"))

75

.pipe(_ + 10)

76

.tap(x => println(s"After adding 10: $x"))

77

// Result: 94

78

79

// Complex data processing pipeline

80

case class User(name: String, age: Int, email: String)

81

82

val users = List(

83

User("Alice", 25, "alice@example.com"),

84

User("Bob", 17, "bob@example.com"),

85

User("Charlie", 30, "charlie@example.com")

86

)

87

88

val processedUsers = users

89

.filter(_.age >= 18)

90

.tap(adults => println(s"Found ${adults.length} adult users"))

91

.sortBy(_.age)

92

.pipe(_.take(10)) // Top 10 by age

93

.map(user => user.copy(email = user.email.toLowerCase))

94

.tap(final => println(s"Final result: ${final.length} users"))

95

```

96

97

### Cross-Compilation Annotations

98

99

Annotations that facilitate cross-compilation between different Scala versions by suppressing warnings and marking unused code.

100

101

```scala { .api }

102

/**

103

* Local warning suppression annotation

104

* On Scala 2.13+: Suppresses compiler warnings locally

105

* On Scala 2.11: No functionality, but enables cross-compilation

106

* @param value Warning category to suppress (optional)

107

*/

108

class nowarn(value: String = "") extends scala.annotation.ClassfileAnnotation

109

110

/**

111

* Mark parameters or definitions as unused to suppress warnings

112

* Extends deprecated to suppress unused warnings across Scala versions

113

*/

114

final class unused extends deprecated("unused", "unused")

115

```

116

117

**Usage Examples:**

118

119

```scala

120

import scala.annotation.unused

121

122

// Suppress specific warnings

123

@nowarn("cat=deprecation")

124

def useDeprecatedApi(): Unit = {

125

// Use deprecated API without warnings

126

legacyLibrary.deprecatedMethod()

127

}

128

129

// Suppress all warnings in a scope

130

@nowarn

131

def experimentalCode(): Unit = {

132

// Experimental code with potential warnings

133

val x = unsafeOperation()

134

riskyTransformation(x)

135

}

136

137

// Mark unused parameters

138

def processData(data: List[String], @unused debugMode: Boolean): List[String] = {

139

// debugMode parameter is unused but kept for API compatibility

140

data.filter(_.nonEmpty).map(_.trim)

141

}

142

143

// Mark unused variables in pattern matching

144

def handleResponse(response: Either[Error, Success]): String = response match {

145

case Left(@unused error) => "Error occurred" // error details unused

146

case Right(success) => s"Success: ${success.message}"

147

}

148

149

// Mark unused imports (useful for cross-compilation)

150

import scala.collection.compat._ // @unused - needed for 2.11/2.12 but not 2.13

151

152

// Cross-version compatibility pattern

153

class CrossVersionService {

154

@nowarn("cat=unused")

155

private val compatImport = {

156

// Import needed for older Scala versions but unused in newer ones

157

import scala.collection.compat._

158

()

159

}

160

161

def processCollection[A](items: List[A]): Option[A] = {

162

items.maxOption // Available through compat import on older versions

163

}

164

}

165

```

166

167

### Enhanced Regex Operations

168

169

Additional regex functionality providing more intuitive matching operations.

170

171

```scala { .api }

172

/**

173

* Extension methods for Regex

174

* @param regex The regex to extend

175

*/

176

implicit class RegexOps(regex: Regex) {

177

/**

178

* Test if regex matches entire character sequence with anchoring

179

* More intuitive than findFirstIn for full string matching

180

* @param source Character sequence to test

181

* @return true if regex matches the entire sequence

182

*/

183

def matches(source: CharSequence): Boolean

184

}

185

```

186

187

**Usage Examples:**

188

189

```scala

190

import scala.util.matching.Regex

191

import scala.util.matching.compat._

192

193

val emailPattern = """[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}""".r

194

val phonePattern = """\d{3}-\d{3}-\d{4}""".r

195

196

// Full string matching

197

emailPattern.matches("user@example.com") // true

198

emailPattern.matches("not-an-email") // false

199

emailPattern.matches("user@example.com!") // false (extra character)

200

201

phonePattern.matches("555-123-4567") // true

202

phonePattern.matches("555-123-456") // false (too short)

203

204

// Validation functions

205

def isValidEmail(email: String): Boolean = {

206

emailPattern.matches(email)

207

}

208

209

def isValidPhoneNumber(phone: String): Boolean = {

210

phonePattern.matches(phone)

211

}

212

213

// Form validation

214

case class ContactForm(email: String, phone: String) {

215

def validate(): List[String] = {

216

val errors = List.newBuilder[String]

217

218

if (!emailPattern.matches(email)) {

219

errors += "Invalid email format"

220

}

221

222

if (!phonePattern.matches(phone)) {

223

errors += "Invalid phone number format"

224

}

225

226

errors.result()

227

}

228

}

229

230

// Pattern matching with validation

231

def processUserInput(input: String): String = input match {

232

case emailPattern.matches(_) if emailPattern.matches(input) => "Valid email"

233

case phonePattern.matches(_) if phonePattern.matches(input) => "Valid phone"

234

case _ => "Invalid format"

235

}

236

```

237

238

### Random Number Extensions

239

240

Enhanced random number generation with support for long ranges.

241

242

```scala { .api }

243

/**

244

* Extension methods for scala.util.Random

245

* @param self Random instance to extend

246

*/

247

final class RandomExtensions(self: Random) {

248

/**

249

* Generate random long in range [0, n)

250

* Extends Random to support long ranges beyond Int.MaxValue

251

* @param n Upper bound (exclusive)

252

* @return Random long between 0 (inclusive) and n (exclusive)

253

*/

254

def nextLong(n: Long): Long

255

}

256

```

257

258

**Usage Examples:**

259

260

```scala

261

import scala.util.Random

262

import scala.collection.compat._

263

264

val random = new Random()

265

266

// Generate random longs in large ranges

267

val bigRandomId = random.nextLong(1000000000000L) // 0 to 1 trillion

268

val timestampOffset = random.nextLong(86400000L) // 0 to 24 hours in milliseconds

269

270

// Generate random data for testing

271

def generateTestData(count: Int): List[TestRecord] = {

272

(1 to count).map { _ =>

273

TestRecord(

274

id = random.nextLong(Long.MaxValue),

275

timestamp = System.currentTimeMillis() + random.nextLong(86400000L),

276

value = random.nextDouble()

277

)

278

}.toList

279

}

280

281

// Random sampling from large datasets

282

def sampleLargeDataset[A](data: Vector[A], sampleSize: Int): List[A] = {

283

val indices = (1 to sampleSize).map(_ => random.nextLong(data.length.toLong).toInt).toSet

284

indices.map(data(_)).toList

285

}

286

```

287

288

### Factory and Collection Extensions

289

290

Additional factory methods and collection utilities for enhanced collection creation patterns.

291

292

```scala { .api }

293

/**

294

* Extension methods for Array companion object

295

* @param fact Array companion object

296

*/

297

class ArrayExtensions(fact: Array.type) {

298

/**

299

* Create array from collection

300

* @param source Source collection

301

* @param elemTag ClassTag for element type

302

* @return New array containing elements from source

303

*/

304

def from[A: ClassTag](source: TraversableOnce[A]): Array[A]

305

}

306

307

/**

308

* Extension methods for SortedMap companion object

309

* @param fact SortedMap companion object

310

*/

311

class ImmutableSortedMapExtensions(fact: immutable.SortedMap.type) {

312

/**

313

* Create SortedMap from collection of pairs

314

* @param source Source collection of key-value pairs

315

* @param ordering Ordering for keys

316

* @return New SortedMap containing pairs from source

317

*/

318

def from[K: Ordering, V](source: TraversableOnce[(K, V)]): immutable.SortedMap[K, V]

319

}

320

321

/**

322

* Extension methods for Option companion object

323

* @param fact Option companion object

324

*/

325

class OptionCompanionExtensionMethods(fact: Option.type) {

326

/**

327

* Create Option based on condition

328

* @param cond Condition to test

329

* @param a Value to wrap if condition is true (call-by-name)

330

* @return Some(a) if cond is true, None otherwise

331

*/

332

def when[A](cond: Boolean)(a: => A): Option[A]

333

334

/**

335

* Create Option based on negated condition

336

* @param cond Condition to test

337

* @param a Value to wrap if condition is false (call-by-name)

338

* @return Some(a) if cond is false, None otherwise

339

*/

340

def unless[A](cond: Boolean)(a: => A): Option[A]

341

}

342

```

343

344

**Usage Examples:**

345

346

```scala

347

import scala.collection.compat._

348

349

// Array creation from collections

350

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

351

val array = Array.from(list)

352

353

val stringArray = Array.from("hello".toCharArray.map(_.toString))

354

355

// SortedMap creation

356

val pairs = List("c" -> 3, "a" -> 1, "b" -> 2)

357

val sortedMap = immutable.SortedMap.from(pairs)

358

// Result: SortedMap("a" -> 1, "b" -> 2, "c" -> 3)

359

360

// Conditional Option creation

361

val userAge = 25

362

val drinkingAge = Option.when(userAge >= 21)(userAge) // Some(25)

363

val invalidAge = Option.when(userAge < 0)(userAge) // None

364

365

val message = Option.unless(userAge < 18)("Welcome, adult user!")

366

367

// Complex conditional logic

368

def processUser(user: User): Option[ProcessedUser] = {

369

Option.when(user.isActive && user.email.nonEmpty) {

370

ProcessedUser(

371

id = user.id,

372

name = user.name.trim,

373

email = user.email.toLowerCase,

374

lastLogin = user.lastLogin.getOrElse(Instant.now())

375

)

376

}

377

}

378

379

// Configuration-based instantiation

380

def createService(config: Config): Option[DatabaseService] = {

381

Option.when(config.databaseEnabled) {

382

new DatabaseService(

383

url = config.databaseUrl,

384

username = config.databaseUser,

385

password = config.databasePassword

386

)

387

}

388

}

389

```

390

391

### Size and Sorting Extensions

392

393

Enhanced operations for size checking and sorting on various collection types.

394

395

```scala { .api }

396

/**

397

* Extension methods for Sorted collections

398

* @param fact Sorted collection instance

399

*/

400

class SortedExtensionMethods[K, T <: Sorted[K, T]](fact: Sorted[K, T]) {

401

/**

402

* Elements from key onwards

403

* @param from Starting key (inclusive)

404

* @return Collection containing elements from key onwards

405

*/

406

def rangeFrom(from: K): T

407

408

/**

409

* Elements up to key

410

* @param to Ending key (inclusive)

411

* @return Collection containing elements up to key

412

*/

413

def rangeTo(to: K): T

414

415

/**

416

* Elements up to but not including key

417

* @param until Ending key (exclusive)

418

* @return Collection containing elements before key

419

*/

420

def rangeUntil(until: K): T

421

}

422

423

/**

424

* Extension methods for SortedMap instances

425

* @param self SortedMap to extend

426

*/

427

class SortedMapExtensionMethods[K, V](self: collection.SortedMap[K, V]) {

428

/**

429

* First entry after given key

430

* @param key Key to search after

431

* @return Some((key, value)) of first entry after key, None if not found

432

*/

433

def minAfter(key: K): Option[(K, V)]

434

435

/**

436

* Last entry before given key

437

* @param key Key to search before

438

* @return Some((key, value)) of last entry before key, None if not found

439

*/

440

def maxBefore(key: K): Option[(K, V)]

441

}

442

443

/**

444

* Extension methods for SortedSet instances

445

* @param self SortedSet to extend

446

*/

447

class SortedSetExtensionMethods[A](self: collection.SortedSet[A]) {

448

/**

449

* First element after given key

450

* @param key Key to search after

451

* @return Some(element) of first element after key, None if not found

452

*/

453

def minAfter(key: A): Option[A]

454

455

/**

456

* Last element before given key

457

* @param key Key to search before

458

* @return Some(element) of last element before key, None if not found

459

*/

460

def maxBefore(key: A): Option[A]

461

}

462

```

463

464

**Usage Examples:**

465

466

```scala

467

import scala.collection.compat._

468

import scala.collection.{SortedMap, SortedSet}

469

470

// Sorted collection range operations

471

val sortedNumbers = SortedSet(1, 3, 5, 7, 9, 11, 13, 15)

472

473

val fromFive = sortedNumbers.rangeFrom(5) // SortedSet(5, 7, 9, 11, 13, 15)

474

val upToTen = sortedNumbers.rangeTo(10) // SortedSet(1, 3, 5, 7, 9)

475

val beforeTen = sortedNumbers.rangeUntil(10) // SortedSet(1, 3, 5, 7, 9)

476

477

// SortedMap neighbor searches

478

val scores = SortedMap("Alice" -> 95, "Bob" -> 87, "Charlie" -> 92, "Diana" -> 98)

479

480

val nextAfterBob = scores.minAfter("Bob") // Some(("Charlie", 92))

481

val prevBeforeCharlie = scores.maxBefore("Charlie") // Some(("Bob", 87))

482

483

// SortedSet neighbor searches

484

val timestamps = SortedSet(100L, 200L, 300L, 400L, 500L)

485

486

val nextAfter250 = timestamps.minAfter(250L) // Some(300L)

487

val prevBefore350 = timestamps.maxBefore(350L) // Some(300L)

488

489

// Range-based querying

490

def findScoresInRange(scores: SortedMap[String, Int],

491

minScore: Int,

492

maxScore: Int): Map[String, Int] = {

493

scores.filter { case (_, score) => score >= minScore && score <= maxScore }

494

}

495

496

// Time-based operations

497

case class Event(timestamp: Long, data: String)

498

499

def findEventsAfter(events: SortedSet[Event], afterTime: Long): Option[Event] = {

500

implicit val eventOrdering: Ordering[Event] = Ordering.by(_.timestamp)

501

val dummyEvent = Event(afterTime, "")

502

events.minAfter(dummyEvent)

503

}

504

```

505

506

These utility features provide essential cross-compilation support, enhanced debugging capabilities, and improved collection operations that make Scala code more maintainable and functional across different versions.