Comments (7)
A couple of random thoughts:
- I don't think I ever needed
flatMap
on signals - whenever I use them on streams, it's legit (but I'm always looking for alternatives before doing
flatMap
s because I don't like them :) ) stream.flatMap(x => signal)
is probably always a bad idea
Gating those could be an "easy" decision?
Random idea: we could import-gate the flatMap
, but also provide another method which will do the same flatMap without requiring an import?
In akka streams they use flatMapConcat
and flatMapMerge
(and flatMap
doesn't exist) (https://doc.akka.io/docs/akka/current/stream/operators/Source-or-Flow/flatMapConcat.html, https://doc.akka.io/docs/akka/current/stream/operators/Source-or-Flow/flatMapMerge.html)
Maybe we even deprecate (and then remove) flatMaps
?
(this will probably also help prevent incorrect for-comps)
from airstream.
Aight, this is what I implemented so far:
-
flatMap
andflatten
method usages will start failing at compile time with an informative error- to help migration, for now, these errors can be replaced with a deprecation warning by importing a special implicit
- later this option will go away
- unless you manually used ConcurrentStreamStrategy, then you will need to use the new
flatMapMerge
.
- to help migration, for now, these errors can be replaced with a deprecation warning by importing a special implicit
-
new operators are
flatMapSwitch
(behaves like the oldflatMap
with no strategy provided),flatMapMerge
,flatMapCustom
(if you want to provide your own FlattenStrategy), as well as theflatten
variants of the same:flattenSwitch
,flattenMerge
,flattenCustom
.- Not a big fan of those
flatten
names tbh, going for consistency with flatMap names. I was also thinking aboutflatSwitch
andflatMerge
, but those are painfully arbitrary / non-consistent.
- Not a big fan of those
-
I also added a
flatMapTo(stream)
alias toflatMapSwitch(_ => stream)
, to clean up a popular use case. -
In Laminar:
flatMap
operator on events (e.g.onClick.flatMap(_ => stream)
will remain as it is today (no warnings or errors) because it doesn't have the same problems as observables do. It will no longer support ConcurrentStreamStrategy, because that combination never made sense anyway.flatMap
operator on events (e.g.onClick.flatMap(_ => stream)
will start using flatMapSwitch under the hood, which means no changes unless you manually provided a non-default flattenstrategy to it, in which case you will get a compiler error.- I also added a
flatMapTo(stream)
alias toflatMap(_ => stream)
, to clean up a popular use case.
from airstream.
I'm in favor of hiding it behind an import statement for exactly the reasons mentioned in the above (my) discord quote. And also because of what @raquo said:
people generally don't expect to need documentation just to use flatMap, so they don't look it up prior to use
Also, I did a quick check and went through some of my projects. For the one mentioned on discord I already noticed that 90% of the flatMaps were not needed.
I also checked two other projects. In one of them, ~~80% percent of flatMaps were wrong, in the other about ~~70%.
I also noticed that flatMaps (and of course for-comprehensions) were much less frequent than I thought. Needing an import would not affect most of the files even in the scalajs section of the projects.
Also, one of those projects is already in production and is used by quite a few people. Which highlights one of my fears: It mostly works. But you sometimes get messages from people saying something didn't work when they used it. And often, it has nothing to do with the software, like they are using a browser from 2010 or have some weird security restrictions on their network or something. But some of them might have stumbled upon a real bug in our code caused by using flatMaps where they should not be used.
For example, I have found code like this:
for {
value <- node.map(_.head.value)
spec <- node.map(_.head.spec.data)
result <- zipperFromSpec(spec) match {
case None => invalidSpec
case Some(zipper) => doStage(value, spec, zipper, open.signal, commandBus.writer)
}
} yield result
this worries me. This seems like it would work like 99% of the time but could sometimes lead to an odd glitch which makes doStage
get non-matching value
and spec
arguments.
Summary
- Did I experience unexpected
flatMap
: yes - How many of the
flatMaps
/for
used where legitimate: roughly 1/4 (meaning 3/4 were bad) - How many
.flatten
s? I only found a single.flatten
and it was legitimate. - How anoyed would I be: Not very, given a good
implicitNotFound
message. Mainly becauseflatMaps
in any form were much less frequent than I thought
from airstream.
I used flatMap
quite a bit (mostly to trigger ajax requests so it's mostly stream.flatMap(x => stream)
) and I think every time was legitimate. I did read the whole documentation before starting to use Laminar about 3 years ago.
That said, I agree this could have been a big issue if I had missed that part of the doc and could still be if someone joined my project.
I really like yurique's idea. It is more explicit, allows for smooth migration and prevents the for-comp usage.
from airstream.
Just like phfroidmont, I used flatMap
mostly for Ajax requests, so most of them were legit. The most complicated thing I did with flatMap
was something like this:
val outputListSignal = itemListSignal
.split(_.itemId) { case (_, _, itemSignal) =>
itemSignal.map(veryExpensiveFunction)
}
.distinct
.flatMap { outputSignals =>
new CombineSignalN(
JsArray.apply(outputSignals),
_.asScalaJs.toList
)
}
and I encountered diamond glitch case while coming up with that.
I do think we should rename flatMap
so users do not accidentally for-comp them.
from airstream.
To clarify what kind of comments I'm hoping for:
- Have you run into problems with Airstream's
flatMap
behaving unexpectedly, because you were expecting behaviour similar tocombineWith
? (or maybe for some other / unknown reason?) - How often do you use Airstream's
flatMap
operator, and are you using it mostly "legitimately", or mostly as a poor man'scombineWith
? (see here for clarity) - Same question but about the
flatten
operator. - How annoyed would you be if you needed to import something like
com.raquo.airstream.api.features.allowFlatMap
to be able to useflatMap
/flatten
? The compiler would give you an error telling that you need this import.
Also to clarify the proposal on a technical level:
- currently,
flatMap
method already requires an implicit param of type FlattenStrategy. - it's automatically defaulting to a switching strategy, which is a sane default (if you've read the docs, at least).
- the change would be to remove that default, and add an implicitNotFound compiler error message telling developers why they need to be careful, and how to import the default switching strategy.
- Or alternatively, we could create a second implicit param, just for implicitNotFound (like unit sinks), and leave the existing FlattenStrategy param and implicit param as-is, for better separation of concerns.
- I'll look more into specific implementation if/when there is enough agreement that we should proceed with this.
from airstream.
Good idea to rename flatMap
variations to more specific ones. Can see this being he better alternative overall.
from airstream.
Related Issues (20)
- .split operator is hard to use without Laminar
- Killing subscriptions from observers (?)
- splitByType / splitByEnum HOT 6
- Can `DerivedVar` support `map/update` semantics in addition to `map/contramap` semantics? HOT 2
- Add an AjaxStream upload progress observer
- FetchStream does not emit events if it's initialized outside of a transaction HOT 1
- [Question] Simulate DomEventStream click on page load HOT 5
- idiomatic usage of foreach for EventStream HOT 4
- Streams should emit in a shared transaction when starting HOT 2
- Vars should be splittable HOT 4
- Error: code length overflow HOT 2
- Transaction stack overflow caused by sibling transactions HOT 4
- split doesn't memoize on Signal[LazyList[A]] HOT 2
- Zooming into a Var should not require an Owner? HOT 5
- SplitChildSignal does not re-sync when restarted HOT 6
- `composeEither`: fixed-scope `flatten` without transcations HOT 4
- Add method variant of EvenStream.merge? HOT 5
- Update and get HOT 5
- add flatmap to ReactiveEventProp HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from airstream.