More EC Recombination; redsigning for pipelines! Episode 69 of Unhindered by Coding
Channel: Unhindered by Coding!
Date: 2023-01-30

The bulk of this session was working on a major redesign of the the recombinator system, following esitsu@Twitch's vision as laid out over in Discord. I think this design is really interesting, but doesn't necessarily come naturally to me, so I've struggled in places. In a perfect world I'd be able to work up to this in a more incremental fashion, but we're really doing a pretty wholesale rewrite at this point. I think I'm getting my head around #esitsu's design and the implementation is making sense, although TBH I'm still not convinced it's the design I would have come up with.

This is a tough episode to summarize, i.e., it's hard to effectively compress these two hours into a few hundred words. There wasn't a simple set of "achievements" to list, nor particular technologies or libraries to discuss, as it was almost entirely a design discussion, and the beginnings of implementing that design.

The key idea in #esitsu's design is the idea of a very general `Operator` trait:

```rust
trait Operator(Input, P) {
 type Output;

 fn apply(&self, input: Input, p: &P, rng: &mut ThreadRng) -- Self::Output;
}
```

Then pretty much _everything_ (selectors, mutators, recombinators) implement that trait, using the `apply` method to perform the operator's action (e.g., mutating a genome).

One thing in #esitsu's design that I don't fully grok is he has both `Mutate` type and `Mutator` traits, where a `Mutate` (typically) holds something that implements the `Mutator` trait. His goal is is to be able to build pipelines that look something like:

```rust
let child_genome = select(Best)
 .and(select(Lexicase))
 .then_recombine(UniformXo)
 .then_mutate(OneOverLength);
```

Then (I think):
- `Best` and `Lexicase` would be `Select` structs that implement `Selector`
- `UniformXo` would be a `Recombine` struct that implements `Recombinator`, and 
- `OneOverLength` would be a `Mutate` struct that implements `Mutator`
I don't fully get, though, why we would need, e.g., both `Mutate` and `Mutator`.

I made the "mistake" again of trying to attach lots of type constraints on my traits, when it's definitely more flexible if you wait and apply them when you _`impl`_ those traits instead. Luckily #esitsu was there to help guide me.

#esitsu also had a blanket implementation of `Compose` for _all_ types:

```rust
impl(T) Compose for T {}
```

This is really interesting, and something I need to think about some more. Does this in some way "pollute" the namespace by attaching `then_mutate` and `and_select` to _every_ type, whether they want them or not? Presumably we could define them differently for some types as needed, but it still seems a pretty broad brush. I chatted with #esitsu about this on Discord, and they pointed out that the compiler won't generate the `Compose` code for any type _unless it's actually used_, so that's nice. I still feel a _little_ odd about this, but it clearly does make things a lot easier to have everything just automagically pick up the blanket implementation. This is another example of something I would have never thought to do, and I'm not sure how I would have incrementally built up to it.

There was a lot of discussion about the `Mutator` trait and whether things like `mutate()` should take a `&Genome` or a `&mut Genome` argument. I was leaning towards `&Genome`, but #esitsu proposed `&mut Genome`. That struck me as "wrong" at first because I was worried about inadvertently modifying some individual's genome, which we can't do with `&Genome`. #esitsu was trying to avoid making a lot of copies of genomes, though, with the idea that `select` would return an _owned copy_ of the genome which could then be mutated freely by subsequent operators. I still have mixed feelings about that, TBH, but we'll roll with it for a bit.

================

In the first few months of 2023 (at least to mid-March) I'm streaming at https://twitch.tv/NicMcPhee four times a week:

* Tuesday: 10am-noon CST
* Wednesday: 7-9pm CST
* Saturday: 2-4pm CST
* Sunday: 10am-noon CST

The Tuesday and Sunday slots will be focusing on building the EC system in Rust and on the ice-repos webapp. The Wednesday and Saturday slots will be going through the Advent of Code 2022 puzzles/exercises.

Thanks for watching!