Coding 2023-03-22

Tags:
By Max Woerner Chase

Well, I'm not sick any more.

So, let's take a look at MOTR's code and imagine updating it.

Going through in order, we have the helper method not_accumulable_because, which is... Only called from not_flex_out_because? Which is only called from artifact._parametric_not_flex_out. Which is used as a validator for artifact.Condenser and artifact.BasicOutputConverter. For now, let's ignore what's going on in artifact, except insofar as this code is actually being used...

Putting all of this together, and keeping in mind that I want to relax the restrictions on multivalue labels, the final result is: one function like so:

def not_flex_out_because(self) -> typing.Iterator[str]:
    if self.input:
        yield "Unexpected use of parametric with associated inputs."
    if self.iterated_labels:
        yield (
            "The base parametric for an Output should not force iteration."
        )

I dropped the restriction on required/exclusive labels, because I think the singleton reforms handle that, as well.

The definition of expected_labels changes to return self.iterated_labels | self.exclusive_labels, and it probably needs a name change.

Next, we have providing and also_providing, which change like so:

@classmethod
def iterating_over(cls, labels: ...) -> Metadata:
    label_set = frozenset(labels)
    return cls(iterated_labels=label_set, selection_labels=label_set)

def also_iterating_over(self, label: ...) -> Metadata:
    return attr.evolve(
        self,
        iterated_labels=self.iterated_labels.union([label]),
        selection_labels=self.selection_labels.union([label]),
    )

Next, we have as_maximal, which maybe needs a name change, but I also have some simplifications planned. Something like...

class Universe(enum.Enum):
    UNIVERSE = enum.auto()

    def __and__(self, other):
        return other

    __rand__ = __and__

    def __rsub__(self, other):
        return frozenset()

    # Don't know if this one is needed.
    def __contains__(self, item):
        return True

Which would be used as the default value of multivalue_labels. So as_maximal becomes:

def as_maximal(self) -> Metadata:
    return attr.evolve(
        self,
        multivalue_labels=self.multivalue_labels & self.selection_labels,
    )

Similar changes to as_requiring:

def as_exclusive(self) -> Metadata:
    return attr.evolve(
        self,
        iterated_labels=frozenset(),
        exclusive_labels=self.expected_labels,
    )

Then we get into narrow_labels, which becomes...

def reduce_iteration_to(self, labels: _selection.Labels) -> Metadata:
    if not labels <= self.iterated_labels:
        raise ValueError
    no_longer_iterated_labels = self.iterated_labels - labels
    return attr.evolve(
        self,
        iterated_labels=labels,
        exclusive_labels=self.exclusive_labels - no_longer_iterated_labels,
    )

And I think I'll leave it there, because something is pretty suspicious about this, in a way that's making me suspect that my model is incomplete or incorrect. There's a few things going on that look suspicious:

In any case, I need to think about this a bit more, then change things if I feel the need, or just move on down through the rest of the methods and functions.

Good night.