Description
I'd like something like the following to work:
DefineMap.extend({
name: "string"
nameChangeCount: {
default: 0,
reduce: {
"name": (last, nameEvent)=> last + 1;
}
}
})
Essentially, the reducer would specify events to bind to and a corresponding function that gets the last value, event emitted and returns the new value. Here's how fullName
could be built without a getter
(and #434 merged) :
DefineMap.extend({
first: "string",
last: "string",
nameParts: {
default: [],
reduce: {
"first": ( [first, last], {newValue} ) => [newValue, last],
"last": ( [first, last], {newValue} ) => [first, newValue],
}
},
fullName: {
default: "",
reduce: {
nameParts: (last, {newValue} )=> newValue.join(" ")
}
}
})
Notes / Questions
-
The functions should be called with the last value and all arguments used to dispatch the event. This makes it possible to have a funciton like
(last, event, newValue, oldValue) => {}
. -
Should "deep" values be supported? For example
reduce: { "task.length": ()=>{} }
. -
How should the set values be treated? Perhaps a reserved name?
fullName: { default: "", reduce: { $lastSet: (last, newValue) => newValue, nameParts: (last, {newValue} )=> newValue.join(" ") } }
-
Could a
get
be used as a "final" stage and avoid intermediate steps?DefineMap.extend({ first: "string", last: "string", fullName: { default: [], reduce: { "first": ( [first, last], {newValue} ) => [newValue, last], "last": ( [first, last], {newValue} ) => [first, newValue], }, get: (reducedValue) => reducedValue.join(" ") } })
-
Can these "reducers" be shared and tested somehow? Or would we need
can-reducer
for this?
How to build this
We can add a reducer observable that would work like:
new ReducerObservable({
"first": ( [first, last], {newValue} ) => [newValue, last],
"last": ( [first, last], {newValue} ) => [first, newValue],
}, this, 0 )
This can be mixed in similar to how ResolverObservable
is here:
Line 455 in 10d9068
ReducerObservable
would be a constructor function very similar in API to ResolverObservable
, with the right symbols:
Reducer.prototype = {
[getValue]()
[setValue]()
[onValue]()
[offValue]()
}