or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

collections.mdconcurrent.mdcontrol-types.mdcore-types.mdfunctional-interfaces.mdindex.md

functional-interfaces.mddocs/

0

# Functional Interfaces

1

2

Extended function interfaces with composition, memoization, and exception handling capabilities that enhance Java's standard functional interfaces.

3

4

## Capabilities

5

6

### Function Interfaces

7

8

Extended function interfaces from arity 0 to 8 with additional methods for composition, memoization, and currying.

9

10

```java { .api }

11

/**

12

* Supplier function (0 arguments)

13

*/

14

@FunctionalInterface

15

interface Function0<R> extends Supplier<R> {

16

// Factory methods

17

static <R> Function0<R> of(Function0<R> function);

18

static <R> Function0<R> constant(R value); // Function that always returns value

19

20

// Execution

21

R apply(); // Execute the function

22

23

// Memoization

24

Function0<R> memoized(); // Cache result after first call

25

boolean isMemoized(); // Check if this function is memoized

26

27

// Composition

28

default <V> Function0<V> andThen(Function<? super R, ? extends V> after);

29

30

// Lifting

31

static <R> Function1<Integer, R> lift(Function0<R> function); // Lift to Function1 ignoring argument

32

}

33

34

/**

35

* Single argument function

36

*/

37

@FunctionalInterface

38

interface Function1<T1, R> extends Function<T1, R> {

39

// Factory methods

40

static <T1, R> Function1<T1, R> of(Function1<T1, R> function);

41

static <T1, R> Function1<T1, R> identity(); // Function returning its argument

42

static <T1, R> Function1<T1, R> constant(R value); // Function ignoring argument, returning value

43

44

// Execution

45

R apply(T1 t1); // Apply function to argument

46

47

// Memoization

48

Function1<T1, R> memoized(); // Cache results by argument

49

boolean isMemoized();

50

51

// Composition

52

default <V> Function1<T1, V> andThen(Function<? super R, ? extends V> after);

53

default <V> Function1<V, R> compose(Function<? super V, ? extends T1> before);

54

55

// Currying (for compatibility - Function1 is already curried)

56

Function1<T1, R> curried();

57

58

// Partial application

59

Function0<R> apply(T1 t1); // Partially apply argument, return Function0

60

61

// Lifting operations

62

static <T1, R> Function1<Option<T1>, Option<R>> lift(Function1<T1, R> function);

63

static <T1, R> Function1<Try<T1>, Try<R>> liftTry(Function1<T1, R> function);

64

}

65

66

/**

67

* Two argument function (BiFunction)

68

*/

69

@FunctionalInterface

70

interface Function2<T1, T2, R> extends BiFunction<T1, T2, R> {

71

// Factory methods

72

static <T1, T2, R> Function2<T1, T2, R> of(Function2<T1, T2, R> function);

73

static <T1, T2, R> Function2<T1, T2, R> constant(R value);

74

75

// Execution

76

R apply(T1 t1, T2 t2); // Apply function to arguments

77

78

// Memoization

79

Function2<T1, T2, R> memoized(); // Cache results by argument tuple

80

boolean isMemoized();

81

82

// Composition

83

default <V> Function2<T1, T2, V> andThen(Function<? super R, ? extends V> after);

84

85

// Currying

86

Function1<T1, Function1<T2, R>> curried(); // Convert to curried form

87

88

// Partial application

89

Function1<T2, R> apply(T1 t1); // Apply first argument

90

Function0<R> apply(T1 t1, T2 t2); // Apply both arguments

91

92

// Argument manipulation

93

Function2<T2, T1, R> reversed(); // Swap argument order

94

95

// Lifting operations

96

static <T1, T2, R> Function2<Option<T1>, Option<T2>, Option<R>> lift(Function2<T1, T2, R> function);

97

}

98

99

/**

100

* Three argument function

101

*/

102

@FunctionalInterface

103

interface Function3<T1, T2, T3, R> {

104

// Factory methods

105

static <T1, T2, T3, R> Function3<T1, T2, T3, R> of(Function3<T1, T2, T3, R> function);

106

static <T1, T2, T3, R> Function3<T1, T2, T3, R> constant(R value);

107

108

// Execution

109

R apply(T1 t1, T2 t2, T3 t3); // Apply function to arguments

110

111

// Memoization

112

Function3<T1, T2, T3, R> memoized();

113

boolean isMemoized();

114

115

// Composition

116

default <V> Function3<T1, T2, T3, V> andThen(Function<? super R, ? extends V> after);

117

118

// Currying

119

Function1<T1, Function1<T2, Function1<T3, R>>> curried(); // Convert to curried form

120

121

// Partial application

122

Function2<T2, T3, R> apply(T1 t1); // Apply first argument

123

Function1<T3, R> apply(T1 t1, T2 t2); // Apply first two arguments

124

Function0<R> apply(T1 t1, T2 t2, T3 t3); // Apply all arguments

125

}

126

127

// ... continues similarly for Function4 through Function8 with appropriate arities

128

```

129

130

**Usage Examples:**

131

132

```java

133

import io.vavr.Function1;

134

import io.vavr.Function2;

135

import io.vavr.Function3;

136

137

// Creating functions

138

Function1<String, Integer> length = String::length;

139

Function2<Integer, Integer, Integer> add = Integer::sum;

140

Function3<Integer, Integer, Integer, Integer> add3 = (a, b, c) -> a + b + c;

141

142

// Function composition

143

Function1<String, String> toUpper = String::toUpperCase;

144

Function1<String, Integer> upperLength = length.compose(toUpper);

145

Function1<String, String> describe = length.andThen(len -> "Length: " + len);

146

147

// Memoization (caching results)

148

Function1<Integer, Integer> expensive = n -> {

149

System.out.println("Computing for " + n);

150

return n * n;

151

};

152

Function1<Integer, Integer> cached = expensive.memoized();

153

154

cached.apply(5); // Prints "Computing for 5", returns 25

155

cached.apply(5); // Returns 25 without printing (cached)

156

157

// Currying

158

Function2<Integer, Integer, Integer> multiply = (a, b) -> a * b;

159

Function1<Integer, Function1<Integer, Integer>> curried = multiply.curried();

160

Function1<Integer, Integer> multiplyBy5 = curried.apply(5);

161

Integer result = multiplyBy5.apply(10); // 50

162

163

// Partial application

164

Function3<String, String, String, String> concat3 = (a, b, c) -> a + b + c;

165

Function2<String, String, String> prefixed = concat3.apply("Hello ");

166

Function1<String, String> greeting = prefixed.apply("World");

167

String message = greeting.apply("!"); // "Hello World!"

168

169

// Lifting functions to work with containers

170

Function1<String, Integer> safeLength = Function1.lift(String::length);

171

Option<String> maybeName = Option.of("John");

172

Option<Integer> maybeLength = safeLength.apply(maybeName); // Some(4)

173

174

// Working with Try

175

Function1<String, Integer> parseToInt = Integer::parseInt;

176

Function1<Try<String>, Try<Integer>> safeParse = Function1.liftTry(parseToInt);

177

Try<String> input = Try.of(() -> "123");

178

Try<Integer> parsed = safeParse.apply(input); // Success(123)

179

```

180

181

### Checked Function Interfaces

182

183

Function interfaces that can throw checked exceptions, providing functional programming with exception handling.

184

185

```java { .api }

186

/**

187

* Supplier that may throw checked exceptions

188

*/

189

@FunctionalInterface

190

interface CheckedFunction0<R> {

191

// Execution

192

R apply() throws Throwable; // Execute function, may throw

193

194

// Conversion to regular functions

195

default Function0<Try<R>> unchecked(); // Convert to Function0 returning Try

196

default Function0<R> recover(Function<? super Throwable, ? extends R> recover);

197

198

// Lifting

199

static <R> CheckedFunction0<R> of(CheckedFunction0<R> function);

200

static <R> CheckedFunction0<R> constant(R value); // Function returning constant value

201

202

// Memoization

203

CheckedFunction0<R> memoized();

204

}

205

206

/**

207

* Single argument function that may throw checked exceptions

208

*/

209

@FunctionalInterface

210

interface CheckedFunction1<T1, R> {

211

// Execution

212

R apply(T1 t1) throws Throwable; // Apply function, may throw

213

214

// Conversion to regular functions

215

default Function1<T1, Try<R>> unchecked(); // Convert to Function1 returning Try

216

default Function1<T1, R> recover(Function<? super Throwable, ? extends R> recover);

217

218

// Lifting

219

static <T1, R> CheckedFunction1<T1, R> of(CheckedFunction1<T1, R> function);

220

static <T1, R> CheckedFunction1<T1, R> identity();

221

static <T1, R> CheckedFunction1<T1, R> constant(R value);

222

223

// Composition (with exception handling)

224

default <V> CheckedFunction1<T1, V> andThen(CheckedFunction1<? super R, ? extends V> after);

225

default <V> CheckedFunction1<V, R> compose(CheckedFunction1<? super V, ? extends T1> before);

226

227

// Memoization

228

CheckedFunction1<T1, R> memoized();

229

}

230

231

/**

232

* Two argument function that may throw checked exceptions

233

*/

234

@FunctionalInterface

235

interface CheckedFunction2<T1, T2, R> {

236

// Execution

237

R apply(T1 t1, T2 t2) throws Throwable; // Apply function, may throw

238

239

// Conversion to regular functions

240

default Function2<T1, T2, Try<R>> unchecked(); // Convert to Function2 returning Try

241

default Function2<T1, T2, R> recover(Function<? super Throwable, ? extends R> recover);

242

243

// Lifting and factory methods

244

static <T1, T2, R> CheckedFunction2<T1, T2, R> of(CheckedFunction2<T1, T2, R> function);

245

static <T1, T2, R> CheckedFunction2<T1, T2, R> constant(R value);

246

247

// Composition

248

default <V> CheckedFunction2<T1, T2, V> andThen(CheckedFunction1<? super R, ? extends V> after);

249

250

// Currying

251

CheckedFunction1<T1, CheckedFunction1<T2, R>> curried();

252

253

// Partial application

254

CheckedFunction1<T2, R> apply(T1 t1);

255

256

// Memoization

257

CheckedFunction2<T1, T2, R> memoized();

258

}

259

260

// ... continues for CheckedFunction3 through CheckedFunction8

261

```

262

263

**Usage Examples:**

264

265

```java

266

import io.vavr.CheckedFunction1;

267

import io.vavr.CheckedFunction2;

268

import io.vavr.control.Try;

269

270

// Checked functions for operations that may throw

271

CheckedFunction1<String, Integer> parseInteger = Integer::parseInt;

272

CheckedFunction1<String, String> readFile = fileName -> Files.readString(Paths.get(fileName));

273

CheckedFunction2<String, String, Void> writeFile = (fileName, content) -> {

274

Files.writeString(Paths.get(fileName), content);

275

return null;

276

};

277

278

// Converting to safe functions

279

Function1<String, Try<Integer>> safeParse = parseInteger.unchecked();

280

Try<Integer> result1 = safeParse.apply("123"); // Success(123)

281

Try<Integer> result2 = safeParse.apply("abc"); // Failure(NumberFormatException)

282

283

// Using recover for error handling

284

Function1<String, Integer> parseWithDefault = parseInteger.recover(ex -> -1);

285

Integer parsed1 = parseWithDefault.apply("123"); // 123

286

Integer parsed2 = parseWithDefault.apply("abc"); // -1

287

288

// Composition with checked functions

289

CheckedFunction1<String, String> processFile = readFile

290

.andThen(content -> content.toUpperCase())

291

.andThen(upper -> upper.replace("OLD", "NEW"));

292

293

Try<String> processed = processFile.unchecked().apply("input.txt");

294

295

// Memoized checked functions

296

CheckedFunction1<String, String> expensiveOperation = input -> {

297

Thread.sleep(1000); // Simulate expensive operation

298

return "Processed: " + input;

299

};

300

CheckedFunction1<String, String> memoized = expensiveOperation.memoized();

301

302

// First call - slow

303

Try<String> result3 = memoized.unchecked().apply("test");

304

// Second call - fast (cached)

305

Try<String> result4 = memoized.unchecked().apply("test");

306

```

307

308

### Predicate and Consumer Interfaces

309

310

Enhanced predicate and consumer interfaces with exception handling and composition.

311

312

```java { .api }

313

/**

314

* Predicate that may throw checked exceptions

315

*/

316

@FunctionalInterface

317

interface CheckedPredicate<T> {

318

// Execution

319

boolean test(T t) throws Throwable; // Test predicate, may throw

320

321

// Conversion to regular predicates

322

default Predicate<T> unchecked(); // Convert to Predicate catching exceptions

323

324

// Logical operations

325

default CheckedPredicate<T> and(CheckedPredicate<? super T> other);

326

default CheckedPredicate<T> or(CheckedPredicate<? super T> other);

327

default CheckedPredicate<T> negate();

328

329

// Factory methods

330

static <T> CheckedPredicate<T> of(CheckedPredicate<T> predicate);

331

}

332

333

/**

334

* Consumer that may throw checked exceptions

335

*/

336

@FunctionalInterface

337

interface CheckedConsumer<T> {

338

// Execution

339

void accept(T t) throws Throwable; // Consume value, may throw

340

341

// Conversion to regular consumer

342

default Consumer<T> unchecked(); // Convert to Consumer catching exceptions

343

344

// Chaining

345

default CheckedConsumer<T> andThen(CheckedConsumer<? super T> after);

346

347

// Factory methods

348

static <T> CheckedConsumer<T> of(CheckedConsumer<T> consumer);

349

}

350

351

/**

352

* Runnable that may throw checked exceptions

353

*/

354

@FunctionalInterface

355

interface CheckedRunnable {

356

// Execution

357

void run() throws Throwable; // Run operation, may throw

358

359

// Conversion to regular Runnable

360

default Runnable unchecked(); // Convert to Runnable catching exceptions

361

362

// Factory methods

363

static CheckedRunnable of(CheckedRunnable runnable);

364

}

365

```

366

367

**Usage Examples:**

368

369

```java

370

import io.vavr.CheckedPredicate;

371

import io.vavr.CheckedConsumer;

372

import io.vavr.CheckedRunnable;

373

374

// Checked predicates

375

CheckedPredicate<String> isValidFile = fileName -> Files.exists(Paths.get(fileName));

376

CheckedPredicate<String> isReadable = fileName -> Files.isReadable(Paths.get(fileName));

377

378

// Combining predicates

379

CheckedPredicate<String> canRead = isValidFile.and(isReadable);

380

Predicate<String> safeCanRead = canRead.unchecked(); // Won't throw, returns false on exception

381

382

// Using in streams

383

List<String> validFiles = fileNames.filter(safeCanRead);

384

385

// Checked consumers

386

CheckedConsumer<String> writeToLog = message -> {

387

Files.write(Paths.get("app.log"), (message + "\n").getBytes(),

388

StandardOpenOption.CREATE, StandardOpenOption.APPEND);

389

};

390

391

CheckedConsumer<String> sendEmail = message -> emailService.send(message);

392

393

// Chaining consumers

394

CheckedConsumer<String> logAndEmail = writeToLog.andThen(sendEmail);

395

Consumer<String> safeProcess = logAndEmail.unchecked();

396

397

// Using with collections

398

messages.forEach(safeProcess);

399

400

// Checked runnable

401

CheckedRunnable startup = () -> {

402

initializeDatabase();

403

loadConfiguration();

404

startServices();

405

};

406

407

// Convert to safe runnable

408

Runnable safeStartup = startup.unchecked();

409

new Thread(safeStartup).start();

410

```

411

412

### Partial Functions

413

414

Functions that are not defined for all possible inputs, providing pattern matching and domain restriction capabilities.

415

416

```java { .api }

417

/**

418

* Function that is not defined for all inputs

419

*/

420

interface PartialFunction<T, R> extends Function1<T, R> {

421

// Factory methods

422

static <T, R> PartialFunction<T, R> of(Predicate<? super T> isDefinedAt,

423

Function<? super T, ? extends R> apply);

424

425

// Domain checking

426

boolean isDefinedAt(T value); // Check if function is defined for value

427

428

// Safe application

429

Option<R> lift(T value); // Apply if defined, return None otherwise

430

431

// Execution (throws if not defined)

432

R apply(T value); // Apply function, throws if not defined at value

433

434

// Composition

435

default <V> PartialFunction<T, V> andThen(Function<? super R, ? extends V> after);

436

default <V> PartialFunction<V, R> compose(PartialFunction<? super V, ? extends T> before);

437

438

// Combination with other partial functions

439

default PartialFunction<T, R> orElse(PartialFunction<? super T, ? extends R> that);

440

441

// Lifting to total function

442

default Function1<T, Option<R>> lift(); // Convert to total function returning Option

443

444

// Pattern matching support

445

static <T, R> PartialFunction<T, R> caseOf(Predicate<? super T> condition,

446

Function<? super T, ? extends R> function);

447

}

448

```

449

450

**Usage Examples:**

451

452

```java

453

import io.vavr.PartialFunction;

454

import io.vavr.control.Option;

455

456

// Creating partial functions

457

PartialFunction<Integer, String> evenToString = PartialFunction.of(

458

n -> n % 2 == 0, // Defined only for even numbers

459

n -> "Even: " + n // Function to apply

460

);

461

462

PartialFunction<Integer, String> oddToString = PartialFunction.of(

463

n -> n % 2 == 1, // Defined only for odd numbers

464

n -> "Odd: " + n // Function to apply

465

);

466

467

// Checking if defined

468

boolean defined = evenToString.isDefinedAt(4); // true

469

boolean notDefined = evenToString.isDefinedAt(3); // false

470

471

// Safe application

472

Option<String> result1 = evenToString.lift(4); // Some("Even: 4")

473

Option<String> result2 = evenToString.lift(3); // None

474

475

// Combining partial functions

476

PartialFunction<Integer, String> numberToString = evenToString.orElse(oddToString);

477

478

// Now defined for all integers

479

String result3 = numberToString.apply(4); // "Even: 4"

480

String result4 = numberToString.apply(3); // "Odd: 3"

481

482

// Pattern matching style

483

PartialFunction<Object, String> classifier = PartialFunction

484

.caseOf(String.class::isInstance, obj -> "String: " + obj)

485

.orElse(PartialFunction.caseOf(Integer.class::isInstance, obj -> "Integer: " + obj))

486

.orElse(PartialFunction.caseOf(o -> true, obj -> "Other: " + obj.getClass().getSimpleName()));

487

488

String classification1 = classifier.apply("hello"); // "String: hello"

489

String classification2 = classifier.apply(42); // "Integer: 42"

490

String classification3 = classifier.apply(3.14); // "Other: Double"

491

492

// Converting to total function

493

Function1<Integer, Option<String>> totalFunction = evenToString.lift();

494

Option<String> maybeResult = totalFunction.apply(5); // None

495

496

// Using in collection processing

497

List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6);

498

List<String> evenStrings = numbers

499

.map(evenToString.lift()) // Apply partial function safely

500

.filter(Option::isDefined) // Keep only defined results

501

.map(Option::get); // Extract values

502

// Result: ["Even: 2", "Even: 4", "Even: 6"]

503

```