Closed dmitriz closed 7 years ago
I should add, because stream is passed in place of function update
, I find this a bit difficult to unravel:
const increase = () => update(model => {
model.value = model.value + 1;
return model;
Here we are passing the anonymous function to the update
stream? The way I understand the flyd
api, is that you can pass directly the value:
update(model.value + 1)
Would it do the same? Any reason to pass the function instead?
Right now the anonymous function is mutating the model
object passed to it as argument, so it is not pure. Is it intentional?
Hi @dmitriz
Please accept my apologies for the delay in responding! This was not on purpose. I did not get any notification from github and so was not aware that you had opened this issue. I have gotten notifications in the past, so was counting on them instead of manually monitoring the issues tab.
You are correct, views are not aware that they are given streams as callback functions. This is on purpose, so that views are not coupled to implementation details.
As you said, flyd
happens to have an api where a stream can be called as a function. But, if you replaced flyd
with another stream library, you would only have to make one change at the top-level code:
const updateStream = someOtherStreamLibrary.createStream();
// let's say you need to call updateStream.emit(val) to emit a value.
const update = val => updateStream.emit(val);
// now you can pass update to views as before.
The rest of the code works without any changes. That is the benefit of not tying view code to stream implementation details.
I'm not sure about the term lifting -- I've heard of it, but am not an expert on its meaning -- but nothing special happens when passing update
when we pass it to views. It is a function. As I showed above, you could wrap the stream library emit
call to be able to pass update
such that views can call update(val)
. If that is called lifting, then yes :) But with flyd
it is already a function so it is passed as-is.
Now, about what is passed to update
: yes, you can pass a value. But in Meiosis, the value itself is actually a function. update
is a stream of functions, as explained in the first bullet in https://github.com/foxdonut/meiosis/wiki/The-Fundamental-Setup#the-meiosis-setup
update is a stream of model updates: that is, a stream of functions that get the current model and return the updated model.
Passing a function that updates the model, instead of passing a value, is very powerful:
scan
. If the workings of scan
are not clear, please review the previous segment: https://github.com/foxdonut/meiosis/wiki/Quick-Intro-to-Streams Finally, as you said, the anonymous function in the example is mutating the model. Indeed, it is not pure. This is intentional to demonstrate that you can use plain object mutation if you wish. Immutability is not a requirement. But it is certainly possible to use immutable models (Object.assign, Ramda, partial.lenses, Immutable.js, and so on). The choice is yours.
I hope that is helpful!
Thank you for looking at Meiosis! Let me know if I can be of further help.
Hi @foxdonut ,
Many thanks for your answers!
I love your work here and it was one of my inspirations for
the un
project
It seems to have many goals similar to Meiosis. Would be great to know your opinion about it.
Sorry for being short here, I'll be happy to answer in more details once I am sure my answers will reach you :)
Thank you @dmitriz for your kind words!
Hi @foxdonut
Just wanted to mention, we have some related discussion on some more general composition strategies with models decoupled from the views:
https://github.com/uzujs/uzu/issues/6#issuecomment-304519136
Would be curious to hear your opinion on it.
Love the introduction here https://github.com/foxdonut/meiosis/wiki/The-Fundamental-Setup but found this confusing:
When
view
is called, it is passed the update stream instead of function:The only reason it works here is because of the
flyd
api treating streams as functions. But you need to know this in order to write the view correctly, and it would not work when you replaceflyd
by another stream library with different api. E.g. ifupdate(val)
were replaced byupdate.emit(val)
, then theview
must be aware of it.What seem conceptually happen here is some sort of lifting where the
update
was previously defined for functions, but when called, is actually lifted to stream values.