Coding 2022-07-15
Nothing dramatic on writing today, because I've got to do a little research.
As far as drama goes... I got to work on that bug in MOTR, and in solving it, uncovered a much bigger design issue. Let's see if I can explain it...
So, Parametric objects are wrappers around a function, and bring in associated metadata that allow the library to basically construct product iterators, but iterating over a variable twice is basically the same as iterating over it once. Now, these functions can technically produce anything, but they have affordances around producing the IO types that handle coordination between actions in the core. Basic things they try to support:
- "Act like this variable takes on this value, for this function" I didn't run into this when I was hitting bugs, but there's some subtlety here
- "Conceal iteration over a variable, unless the outer function also iterates over it" This is needed for things like "here are twelve outputs; they must all be used as inputs to the same action"
- "Prevent iterating over any variable that this function doesn't know about" This is needed to prevent multiple actions from producing the same output
If you read that last one carefully, you might be able to figure out how my initial implementation can, and just now, did go wrong...
My initial implementation said "You can iterate over variables that this function doesn't know about." But, it's actually totally valid to iterate over "extra" variables, as long as they don't take on more than one value. Now, the fields involved are just obscure enough now that I think I should take this opportunity to document them...
- provided_labels represents the variables that the wrapped function should vary with respect to
- required_labels represents the variables that something should iterate over; either this function, or something else
- handled_labels represents the variables that the function will gracefully handle iterating over
- allowed_labels represents the variables that it is acceptable for something to iterate over
- flexible is an auxiliary variable required by the user interface, and not terribly interesting for these purposes.
Relationships between these variables:
- handled_labels and allowed_labels are both supersets of provided_labels and required_labels. One of the validators responsible for maintaining this is oddly-named, and I need to investigate it.
- It's permissible to basically "copy" handled_labels into allowed_labels, to cut down on the acceptable options for iteration.
- It's permissible to "move" everything from provided_labels into required_labels (roughly speaking), to create a function that "doesn't provide" the variables that it needs something to iterate over.
- It's permissible to add information to flexible.
- It's permissible to cut down on the provided_labels, but the logic involved is somewhat elaborate.
The basic things I need to handle are:
- Instead of not allowing iteration over variables not in allowed_variables, I need to require that those labels take on only one value.
- Something similar needs to happen with the inject_registry helper function. For each key it injects, it needs to make sure that either both values are length one when the key is used in iteration, or that both values are the same when the key is used in iteration.
It's not immediately obvious to me how to do this, because the documentation is so bad right now. I'm basically going to have to do some documentation and renaming passes in order to make sense of everything. One code change I'm considering, is to create a custom container type for parameterizable values, but I'm not sure if that's necessary. Documentation first.
Well, sleep first, documentation later.
Good night.