xstream icon indicating copy to clipboard operation
xstream copied to clipboard

mapTo + flatten might need lazy evaluation

Open staltz opened this issue 8 years ago • 4 comments

There are cases where mapTo(innerStream) is simply not the same as map(() => innerStream) because the former does lazy evaluation of the innerStream expression, which may involve the creation of a new stream, eg if innerStream expression was source.compose(dropUntil(second)).

Here's an example:

 function notBetween(first, second) {
   return source => xs.merge(
     source.endWhen(first),
-    first.mapTo(source.compose(dropUntil(second))).flatten()
+    first.map(() => source.compose(dropUntil(second))).flatten()
   )
 }

The map works but not the mapTo.

This bug/behavior is not a top priority, but something we should be aware of, in case someone else trips over this.

It may also be related to the asynchronous stop when switching the inner stream in the flatten.

staltz avatar May 14 '16 20:05 staltz

I think that this is solved now since mapTo(x) is really just a call to map(() => x)

TylorS avatar Sep 25 '16 07:09 TylorS

Not really, because x is eagerly evaluated in mapTo(x) but lazily evaluated in map(() => x). This issue is marked bug but I think it's rather unsolvable. What we could do is forbid passing a stream to mapTo, so we always pass streams in map, for lazy evaluation.

staltz avatar Sep 25 '16 08:09 staltz

But they are the same now, no? https://github.com/staltz/xstream/blob/master/src/core.ts#L1699

TylorS avatar Sep 25 '16 16:09 TylorS

Not really, because

function multiply(x) {
  return x * Math.random();
}

is different to

const multiply = makeMultiplyFunction(Math.random());

given

function makeMultiplyFunction(c) {
  return function multiply(x) {
    return x * c;
  } 
}

staltz avatar Sep 25 '16 16:09 staltz