Coding 2023-01-09

Tags:
By Max Woerner Chase

All right. I got some work done on one project today, let's sketch stuff out for MOTR.

My idea for generalizing artifact.Output is to have a helper class that looks something like

@attrs.frozen
class Converter(Generic[T]):
    label: Label[T] | None
    names: Parametric[Sequence[str]] = attrs.field(
        default=no_parameters(()),
        validator=RejectBecause(parametric_not_flex_out),
    )

    def convert(self, parametric: Parametric[Input[T]]) -> PCM[...]:
        # Things get a little problematic here.
        # This needs some way to either use a provided converter callable
        # OR to use the Implicit converter.
        # I think the steps there are to move the "logic" of Implicit to
        # the top level, and write overrides for this method.
        # Anyway, once that's done, porting over the main logic from
        # artifact.Output is a cinch.
        # One thing that I realize I should do first is, check how aligned
        # the different implementations of the Artifact protocol end up
        # looking.
        # I may want to look into reducing the degree of runtime
        # polymorphism somehow, although there are some hurdles there.
        # Like the fact that there are three separate implementations on
        # both sides of the interface boundary.

    # Anyway...

    @attrs.frozen
    class AdditionalOutput(Generic[T_contra, T_co]):
        map: Callable[[T_contra], T_co]
        converter: Converter[T_co]

        def convert(
            self, parametric: Parametric[Input[T_contra]]
        ) -> PCM[...]:
            # Map types over the parametric, then pass it to the converter.

    # This raises the question of whether the artifact.Output should derive
    # all of its outputs from the basal combined value, or if it should
    # apply a map to that value, and then additional maps on top of the
    # first.
    # I'm thinking about this, and not coming up with anything compelling,
    # so I think the tiebreaker is ease of implementation, which would mean
    # merging those classes into one and constraining T_contra when using
    # them with artifact.Output

    # ...

    # One possibility is to allow nesting AdditionalOutputs inside each
    # other.
    # This would allow quite a bit of flexibility, while also simplifying
    # the implementation of Output...

I think I should keep on thinking about this. Before I make any changes one way or the other, I should switch topics to the coverage topic, and work on marking up all of the code that I decided to change.

This entry is finished a bit earlier than most of the recent ones, so let's just call it there and let me wind down properly for a change.

Good night.