# Suppliers and Lazy Evaluation

## Introduction

In Java, a Supplier is a functional interface introduced in Java 8 as part of the functional programming API, as explained in my previous article.

It is an interface that takes no arguments and produces a result of a specific type. Its abstract method is called get().

```java
@FunctionalInterface 
public interface Supplier<T> { 
    T get();
}
```

**Usage:**

```java
Supplier<Double> randomSupplier = () -> Math.random();
Double randomValue = randomSupplier.get();
```

But when is providing a value without taking any input useful?

## Factory methods

```java
public interface Shape {
   void draw();
}
```

```java
public class Circle implements Shape {
    @Override
    public void draw() {
        System.out.println("Drawing a circle");
    }
}

public class Rectangle implements Shape {
    @Override
    public void draw() {
        System.out.println("Drawing a rectangle");
    }
}
```

Factory pattern using Supplier:

```java
final static Map<String, Supplier<Shape>> map = new HashMap<>();
static {
    map.put("circle", () -> new Circle());  
    map.put("rectangle", () -> new Rectangle());
}
```

The whole factory class is:

```java
public class ShapeFactory {
    final static Map<String, Supplier<Shape>> map = new HashMap<>();
    static {
        map.put("circle", Circle::new);
        map.put("rectangle", Rectangle::new);
    }

    public Shape getShape(String shapeType) {
        Supplier<Shape> shape = map.get(shapeType.toLowerCase());
        if (shape != null) {
            return shape.get();
        }
        throw new IllegalArgumentException("Invalid shape type: " + shapeType.toLowerCase());
    }
}
```

The drawback of this technique is that it does not scale well if the factory method `getShape` needs to take multiple arguments to pass on to the `Shape` constructors.

## Stream API

The `generate` and `iterate` methods in the Stream API receive a Supplier as parameter:

```java
Supplier<Double> randomSupplier = () -> Math.random();
Stream.generate(randomSupplier)
    .limit(10)
    .forEach(System.out::println);
```

It can be simplified using method references:

```java
Stream.generate(Math::random)
    .limit(10)
    .forEach(System.out::println);
```

## Lazy initialization

It is a design pattern where the creation of an object or computation of a value is deferred until it is needed. This technique improves performance and reduces memory usage, because it avoids unnecessary computations.

```java
// Eager initialization
String eagerValue = "Eager Initialization";

// Lazy initialization using Supplier
Supplier<String> lazyValueSupplier = () -> "Lazy Initialization";

// Value is not created until get() is called
System.out.println("Before accessing lazy value");
System.out.println(lazyValueSupplier.get()); // Output: Lazy Initialization
```

The example is useless, but let's imagine a heavy computation task instead of a single String. For this case, it is useful to ensure the object is created only once (memoization).

Let's create a custom wrapper class for this:

```java
public class Lazy<T> {
    private final Supplier<T> supplier;
    private T value;

    public Lazy(Supplier<T> supplier) {
        this.supplier = supplier;
    }

    public T get() {
        if (value == null) {
            value = supplier.get();
        }
        return value;
    }
}
```

It is called like that:

```java
Lazy<String> lazyValue = new Lazy<>(() -> "Computed Value");

System.out.println("Before accessing lazy value");
System.out.println(lazyValue.get()); // Output: Computed Value
```

The syntax for creating a Lazy object in Java is verbose, since it's not a built-in class. In other JVM languages a variable can be declared `lazy`. For example, in Scala:

```scala
lazy val lazyValue = "Computed Value"
```

## Generating an infinite list

This is an application of lazy evaluation. It's a quite common case.

```java
 // Generate an infinite stream of random numbers
Stream<Double> infiniteStream = Stream.generate(Math::random);
// Take the first 5 elements and print them
infiniteStream.limit(5).forEach(System.out::println);
```

```java
// Generate an infinite stream of integers starting from 1
Stream<Integer> infiniteStream = Stream.iterate(1, n -> n + 1);
// Take the first 5 elements and print them
infiniteStream.limit(5).forEach(System.out::println);
```

Scala's native support for laziness makes it more idiomatic for such tasks:

```scala
val infiniteList = LazyList.continually(scala.util.Random.nextDouble())
// Take the first 5 elements and print them
println(infiniteList.take(5).toList)
```

## Lazy Evaluation in Kotlin

```kotlin
// Generate an infinite sequence of integers starting from 1
val infiniteSequence = generateSequence(1) { it + 1 }
// Take the first 5 elements and print them
println(infiniteSequence.take(5).toList())
```

In general, the `sequence` function is a builder needed for creating sequences lazily.

```kotlin
val randomNumbers = sequence {
    while (true) {
        yield(Random.nextDouble())
    }
}

// Take the first 5 random numbers and print them
println(randomNumbers.take(5).toList())
```

Custom extension functions can be defined to create infinite sequences for specific use cases. This allows Kotlin to mimic the functional Scala syntax:

```kotlin
fun Int.toInfiniteSequence(): Sequence<Int> = generateSequence(this) { it + 1 }

fun main() {
    // Create an infinite sequence starting from 10
    val infiniteSequence = 10.toInfiniteSequence()

    // Take the first 5 elements and print them
    println(infiniteSequence.take(5).toList()) 
}
```

## Summary

**Suppliers** are an important part of functional programming in Java.

They have two main use cases:

* To encapsulate the logic of value generation.
    
* To allow separating the definition of how a value is generated from when that value is needed. This technique is called **lazy evaluation** and it's more easily implemented in Scala and Kotlin.
