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

"Computed" values using combinator #3

Closed
aksonov opened this issue May 17, 2016 · 8 comments
Closed

"Computed" values using combinator #3

aksonov opened this issue May 17, 2016 · 8 comments

Comments

@aksonov
Copy link

aksonov commented May 17, 2016

Computer value concept looks very interesting, but it looks strange why it is put into 'react' package? I thought pure model should not depend from any 'view' stack, right?

@polytypic
Copy link
Member

polytypic commented May 17, 2016

If you are referring to the Kefir based K or the Bacon based B combinator, then those are specifically designed for computing stuff to be embedded into VDOM. For more general uses one should use combinators from Kefir or Bacon.

@aksonov
Copy link
Author

aksonov commented May 17, 2016

Thanks! So i could use Atoms and do computed 'atoms' using Kefir's combinators. It is a little bit unclear from calmm documentation ;)
Also it would be great to implement 'facade' API so developer could switch Kefir/Backon/etc and it will not affect Calmm code...

@aksonov
Copy link
Author

aksonov commented May 17, 2016

"Observable frameworks such as Bacon and Kefir provide a large number of combinators for observables. While most of those combinators have uses in conjunction with Calmm, we are frequently only interested in combining, with some function, a bunch of properties, possibly contained in some data structure, into a new property that is kept up-to-date with respect to the latest values of the original properties. We also do a lot of this. Everywhere. That is one of the two main reasons why we have defined a generalized combinator for that use case. Let's just import the Kefir based version of the combinator from the kefir.react.html library:" -

it is nothing there about VDOM. So if i want "combining, with some function, a bunch of properties, possibly contained in some data structure, into a new property" and use generalized combinator, i have to use 'react'-based library, right?

@polytypic
Copy link
Member

The atoms provided by kefir.atom / bacon.atom are observables or more specifically properties of Kefir / Bacon. So, you can use ordinary Kefir / Bacon combinators with those. For example, using kefir.atom and kefir you could use combine:

import Atom from "kefir.atom"
import * as Kefir from "kefir"

const x = Atom(1)
const y = Atom(2)

const x_plus_y = Kefir.combine([x, y], (x, y) => x + y)

So, you don't have to use kefir.react.html or bacon.react.html to combine atoms as properties.

The K and B combinators are tailor made for VDOM embedding and I would not recommend them as such for use outside of UI controls. In particular, the K combinator is optimized to return a constant in case none of the given arguments contains observables. It works nicely when embedding into VDOM, but would likely be error prone when used in other contexts.

One could certainly create versions of K and B more suitable for use in other contexts.

Also, when doing IO it is more common to need to use streams rather than properties.

@aksonov
Copy link
Author

aksonov commented May 17, 2016

Thanks! So let me repeat my question from gitter and #2 to implement side effects - is it correct from FPR point of view for simple xmpp auth to create Atom 'user credentials' with username/ password and make 'connected' as computed value (using map) for credentials Atom (i.e. credentials.map(x=>xmppConnect())? That connected stream will contain xmpp connection obj, etc.

@polytypic
Copy link
Member

I'm not familiar with the particulars of xmpp.

If the credentials (username and password) is something that a user can directly edit through the UI then it is not typical to just directly attempt to connect after each change. It is more typical to have a separate connect -button and make it so that, when it is clicked, connection is attempted with the credentials.

For other kinds of side-effects, say you are displaying the results of an editable query, you may find it appropriate to start query directly after changes to the query parameter atom(s). It is then typical to use flatMapLatest. Something like this:

const query_results =
  combined_parameters_skipping_duplicates
  .debounce( some_appropriate_debounce_period_in_ms )
  .flatMapLatest( params => does_query_and_returns_a_stream( params ) )

Where combined_parameters_skipping_duplicates is an expression that combines atoms (and possibly other kinds of properties) to form an observable for the query parameters. The function does_query_and_returns_a_stream is a function that creates a stream that performs the query (e.g. might perform a HTTP request). The query_results stream could then be used to compute properties for the UI.

This is a really simplified take on this subject. More generally, this is a question of how to do IO with an event stream library like Kefir or Bacon and not really specific to Calmm.

@aksonov
Copy link
Author

aksonov commented May 17, 2016

Thank you so much.

@aksonov
Copy link
Author

aksonov commented May 17, 2016

"It is more typical to have a separate connect -button and make it so that, when it is clicked, connection is attempted with the credentials." - so what is best way to pass data into stream? Also i will want to do disconnect when user clicks 'logout' button. I can't find something similar to Events within FPR...

@aksonov aksonov reopened this May 17, 2016
@aksonov aksonov closed this as completed May 17, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants