> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dairy.foundation/llms.txt
> Use this file to discover all available pages before exploring further.

# Lambda

`Lambda` and `StatefulLambda` are the primary way to write commands in
Mercurial.

These classes are immutable command builders, that allow you to compose a
command programmatically, and are easy to read and use.

`StatefulLambda` is the same as `Lambda`, but has additional state stored in it,
that gets passed to each of its methods to manipulate.

Both `Lambda` and `StatefulLambda` start with sensible defaults:

* no requirements
* an empty init method
* an empty execute method
* instantly finishes
* an empty end method
* is interruptible
* allowed to be scheduled in OpModeState.ACTIVE only (start and loop)

Then, you can apply the builder methods to compose a new command, by adding to
or replacing components of the current command.

# Construction

Both `Lambda` and `StatefulLambda` are easy to construct:

<CodeGroup>
  ```java Java theme={null}
  Lambda lambda = new Lamdba("command-name");
  StatefulLambda<RefCell<String>> statefulLambda = new StatefulLambda<>("command-name", new RefCell<>("state"));
  ```

  ```kt Kotlin theme={null}
  val lambda = Lamdba("command-name")
  val statefulLambda = StatefulLambda("command-name", RefCell("state"))
  ```
</CodeGroup>

Our `StatefulLambda` will have a `RefCell` with a `String` in it as its state.
Go read the `RefCell` documentation in Util for how it works. We need a cell or
similar in order to obtain interior mutability for a simpler piece of data like
a `String`, but you could use a more complex class you've written yourself.

# Building

There are easy methods to set parts of a Command:

<CodeGroup>
  ```java Java theme={null}
  lambda
  	.setInit(() -> {
  		// do w/e
  	})
  	.setExecute(() -> {
  		// do w/e
  	})
  	.setEnd(interrupted -> {
  		// do w/e
  	})
  	.setFinish(() -> {
  		// compute and return if the command is finished
  		return true;
  	})
  	// both variants are available
  	.setInterruptible(true)
  	.setInterruptible(() -> true)
  	// we'll used Mercurial as an example requirement
  	// but it would be strange to use
  	// you could also pass a Set of objects instead of varargs
  	.setRequirements(Mercurial.INSTANCE /*, varargs requirements*/)
  	// you could also pass a Set of OpModeStates instead of varargs
  	.setRunStates(OpModeState.INIT, OpModeState.ACTIVE);

  statefulLambda
  	// stateful lambda adds equivalent methods that also get state as a parameter
  	.setExecute(stateRef -> {
  		stateRef.accept("new state");
  	})
  	.setEnd((interrupted, stateRef) -> {
  		if (interrupted) stateRef.accept("interrupted");
  		else stateRef.accept("not interrupted");
  	});
  ```

  ```kt Kotlin theme={null}
  lambda
  	.setInit {
  		// do w/e
  	}
  	.setExecute {
  		// do w/e
  	}
  	.setEnd { interrupted ->
  		// do w/e
  	}
  	.setFinish {
  		// compute and return if the command is finished
  		true
  	}
  	// both variants are available
  	.setInterruptible(true)
  	.setInterruptible { true }
  	// we'll used Mercurial as an example requirement
  	// but it would be strange to use
  	// you could also pass a Set of objects instead of varargs
  	.setRequirements(Mercurial, /*varargs requirements*/)
  	// you could also pass a Set of OpModeStates instead of varargs
  	.setRunStates(Wrapper.OpModeState.INIT, Wrapper.OpModeState.ACTIVE)

  statefulLambda
  	// stateful lambda adds equivalent methods that also get state as a parameter
  	.setExecute { stateRef ->
  		stateRef.accept("new state");
  	}
  	.setEnd { interrupted, stateRef ->
  		if (interrupted) stateRef.accept("interrupted");
  		else stateRef.accept("not interrupted");
  	}
  ```
</CodeGroup>

Or add to the pre-existing ones, we'll demonstrate some of the add methods, but
there are equivalents for all the set methods.

<CodeGroup>
  ```java Java theme={null}
  lambda
  	.addInit(() -> {
  		// this will run the init already set
  		// then this code
  	})
  	.addFinish(finished -> {
  		// addFinished gives you the computed finished state of the command thus far
  		// and allows you to then determine if it should still finish
  		return finished;
  	})
  	.addInterruptible(interruptible -> {
  		// addInterruptible does the same
  		return interruptible;
  	});

  statefulLambda
  	// statefulLambda has all the same methods, plus you can get the state
  	.addInterruptible((interruptible, state) -> {
  		return interruptible && state.get().equals("interruptible");
  	});
  ```

  ```kt Kotlin theme={null}
  lambda
  	.addInit {
  		// this will run the init already set
  		// then this code
  	}
  	.addFinish { finished ->
  		// addFinished gives you the computed finished state of the command thus far
  		// and allows you to then determine if it should still finish
  		finished
  	}
  	.addInterruptible { interruptible ->
  		// addInterruptible does the same
  		interruptible
  	}

  statefulLambda
  	// statefulLambda has all the same methods, plus you can get the state
  	.addInterruptible { interruptible, state ->
  		interruptible && state.get() == "interruptible"
  	}
  ```
</CodeGroup>

Remember, each of these methods are non-mutating. This means than when you call
them, you get back a new, different command. In the case of statefulLambda, they
still share the same state reference, but other than that they are totally
different.

This is a common theme across Dairy, and its not hard to deal with, but you must
keep it in mind.

Finally, any command can be converted into a `Lambda` or `StatefulLambda`
command.

<CodeGroup>
  ```java Java theme={null}
  Lambda converted = Lambda.from(new Sequential())
  	.addEnd(interrupted -> {
  		System.out.println("sequence ending, interrupted: " + interrupted + "!");
  	});

  StatefulLambda<RefCell<Integer>> statefulConverted = StatefulLambda.from(new Sequential(), new RefCell<>(0))
  	.addEnd((interrupted, stateRef) -> {
  		// increment state
  		stateRef.accept(stateRef.get() + 1);
  		System.out.println("sequence ending for the " + stateRef.get() + " time, interrupted: " + interrupted + "!");
  	});
  ```

  ```kt Kotlin theme={null}
  val converted: Lambda = Lambda.from(Sequential())
  	.addEnd {
  		println("sequence ending!")
  	}

  val statefulConverted: StatefulLambda<RefCell<Int>> = StatefulLambda.from(Sequential(), RefCell(0))
  	.addEnd { interrupted, stateRef ->
  		// increment state
  		stateRef.accept(stateRef.get() + 1)
  		println("sequence ending for the ${stateRef.get()} time, interrupted: $interrupted!")
  	}
  ```
</CodeGroup>

This process is safe for `Lambda.from(Command)`, it does not create a new object
if the argument is already a `Lambda` or a `StatefulLambda`.

But `StatefulLamba.from(Command, STATE)` does not have this safety.

`Lambda` and `StatefulLambda` are clearly nice and easy ways to compose
commands! They are the recommended tool for writing commands in Mercurial.
