Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add: Allow for functions as actions #105

Closed
dxinteractive opened this issue Sep 25, 2018 · 5 comments
Closed

Add: Allow for functions as actions #105

dxinteractive opened this issue Sep 25, 2018 · 5 comments

Comments

@dxinteractive
Copy link
Collaborator

This is necessary for proper safe update andmodifyChange functions, and may end up simplifying the reducer a bunch.
Previously kind of hard to make in a way that could still have replayable actions on different data sets.

  • Add a new action type called func.
  • As Parcels are branched, keep track of modifys that happen. Concat those functions and their keypaths and pass into child parcels. Send this array of modifiers in each action.
  • When a func action is sent, the reducer can start from its own source of parcelData, and it can run nested data through the array of modifiers where necessary to end up with the same data that the action-ing parcel has at the time it send its action. This means the func function can then be called with that data, and the result can be applied to the locationed indicated by the func actions keypath as per normal.

What about modifyChange?

Needs more thought, but I think these can be done in essentially the same way. The order of action could be:

  • Origin action
    • Data is now just that action applied to the data that origin had, which may not be like the real parcelData at all
  • Modify change action
    • Changes the data to be the correct shape

Should these be separate actions, or somehow appended to origin actions so you can never get in that weird middle state of unrepresentative data?

@dxinteractive
Copy link
Collaborator Author

dxinteractive commented Sep 27, 2018

Rewrite updateIn to compose functions together like:

parcel
    .modify(a => a)
    .modifyChange(b => b)
    .get('abc')
    .modify(x => x)
    .modifyChange(y => y)
    .get('def')
    .modify(j => j)
    .modifyChange(k => k)
    .set('!!!');


pipe(
    a => a,
    update('abc', pipe(
        x => x,
        update('def', pipe(
            j => j,
            set,
            k => k
        )),
        y => y
    )),
    b => b
)

// or more like

let keyPathModifiers = [...];
let action = (data) => ...;

composeWith(
    ...kpm.map(aa => (next) => pipe(
        ...aa.pre,
        update(AA.key, next),
        ...aa.post
    )),
    action 
)

@dxinteractive
Copy link
Collaborator Author

({pre, post}) => (fn) => pipe(pre, fn, post)

@dxinteractive
Copy link
Collaborator Author

Lets not do this if possible. It makes it much harder to serialise change requests (important if these are to be saved in local storage or something), and most use cases I can think of right now would be taken care of by an IndexedParcel.arrange() method.

@dxinteractive
Copy link
Collaborator Author

This actually has many advantages than previously thought. It removes the need for modifyChange changes to be as small as possible. Without functions as actions, all changes need to be small because if other data is bundled up in a change request by mistake, that data will overwrite base data whether its intended or not, making rebasing way less effective. With functions as actions, the rebased parcel data can be passed through each actions "changeFunction", which includes all modifyValue calls, get calls, the action at hand, th recursion back from all the gets, and the modifyChange calls in between.

This means Actions will have to contain the modifyValue and modifyChange calls used by each change. This is fine, but Actions are also required to be serialisable so they can be cached. Which means those modify functions also must be serialisable. Serialising functions is possible, but they necessarily lose their scope. So it's almost certain that there'll have to be a rule that all modify functions + Parcel.update function will have to be pure functions that dont rely on scope, and don't trigger side effects.

Also an IndexedParcel.arrange() function necessarily relies on knowing the input value to operate on (what would ['#a','#b'] > ['#b','#a'] do if it were suddenly given ['#x','#y','#p'] to operate on!? It cant know), so the statement above that says IndexedParcel.arrange() would take care of this is nonsensical.

@dxinteractive
Copy link
Collaborator Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant