Coding 2023-04-05

Tags:
By Max Woerner Chase

Okay, the magma is written, and I'll verify that it's "actually correct in general" later, hopefully after I've nailed down some requirements for it.

Let's start working on the next parametric overhaul.

The first half of this has several parts:

It's probably worth calling the decorator just "parametric". The type should be called, um... FakeValue, or something. Something that hopefully makes it really clear that it shouldn't work for most purposes. And the property, just value, maybe?

I don't know if I want to put these ideas into the actual module yet, but let's see what I can do in code blocks here.

# Eventually, these will be replaced with "attrs.frozen"
@attr.dataclass(frozen=True)
class FakeValue(typing.Generic[T_co]):
    parametric: Parametric[T_co]

...
class Parametric(typing.Generic[T_co]):
    ...
    @property
    def value(self) -> T_co:
        return typing.cast(T_co, FakeValue(self))

def parametric(function):
    signature = inspect.signature(function)
    instantiators = {}
    metadata = Metadata()
    for param in signature.parameters.values():
        default = param.default
        if not isinstance(default, FakeValue):
            raise ValueError
        metadata = metadata.combine(default.metadata)
        instantiators[param.name] = default.instantiator

    def instantiate(box, selectors):
        # I'm pretty sure Python is too strict to allow this, but eh.
        kwargs = {name: (yield from instantiator(box, selectors)) for name, instantiator in instantiators.values()}
        return function(**kwargs)

    return Parametric(instantiate, metadata)

I hope this basically works, disregarding the syntactic gunk that I'll have to work around. I'm going to wrap things up for now, and think about it.

Good night.