Allow actions to not specify intermediate result
Take the following:
@action(reads=['input_var'], writes=['output_var'])
def simple_action(state: State) -> tuple[dict, State]:
output_var = _compute(state["input_var"])
result = {"output_var" : output_var}
return result, state.update(**result)
# or
return result, state.append(**result)
This is just a lot of boiler plate -- you have to:
- Compute the result
- Store it in a variable
- return it
- Apply a state update using it
Note most people will probably write it like this:
@action(reads=['input_var'], writes=['output_var', 'output_var_list'])
def simple_action(state: State) -> tuple[dict, State]:
output_var = _compute(state["input_var"])
return {"output_var" : output_var}, state.update(output_var=output_var).append(output_var_list=output_var)
Which is correct, but kind of strange. This is due to the oddity of the "single-step" action. That said, if we want these as simple python functions, then we don't really need the result. Just inspecting the state delta will do it... In fact, when we have the layering, we can think of the state delta as the result.
So, what if we just didn't have intermediate results for certain simple state updates:
@action(reads=['input_var'], writes=['output_var'])
def simple_action(state: State) -> State:
output_var = _compute(state['input_var'])
return state.update(output_var=output_var).append(output_var_list=output_var)
We would determine which we use either based on the annotation or the return type, nd the user would do this knowing that they wouldn't have access to intermediate results in the UI...
Alternatively, we could have them only use the result, and we auto-update the state...
@action(
reads=['input_var'],
writes=[
update(output_var='output_var'),
append(output_var_list='output_var')
]
)
def simple_action(state: State) -> dict:
return {"output_var" : _compute(state['input_var'])}
Having update as a separate function is just one approach, could have increment and append, or have the default be update
More ideas (in this case I'm adding output_var_list to illustrate append
@action(reads=['input_var'], writes=[update('output_var'), append('output_var_list')])
@action(reads=['input_var'], writes=['output_var', append('output_var_list')]
@action(reads=['input_var'], updates=['output_var'], appends=['output_var_list'])
@action(
reads=['input_var'],
writes=['output_var', 'output_var_list'],
update=lambda result: state.update(output_var=result['output_var']).append(output_var_list=result['output_var'])
)
We have decided to do this, just for function-based actions
This is complete