title: Why do some RxJS 6 operators take predicates and projections / selectors?
body: <p>This is a question about the design of RxJS 6. Consider two operators as examples.</p>
  <ol>
  <li><p><a href="https://rxjs-dev.firebaseapp.com/api/index/function/combineLatest" rel="nofollow noreferrer"><code>combineLatest</code></a> takes as an optional parameter a <em>projection</em> or <em>selector</em> (called by different names in different areas of the documentation), i.e. a function that maps from the values of the input observables to a type that will be the value type of the returned observable.</p>
  <p>Presumably, <code>combineLatest([as, bs], f)</code> is the same as <code>combineLatest([as, bs]).pipe(map(f))</code>.</p>
  </li>
  <li><p><a href="https://rxjs-dev.firebaseapp.com/api/operators/last" rel="nofollow noreferrer"><code>last</code></a> takes as an (optional) parameter a <em>predicate</em> that can be used to filter values from the source observable.</p>
  <p>Presumably, <code>source.pipe(last(p))</code> is the same as <code>source.pipe(filter(p), last())</code>. ^1</p>
  </li>
  </ol>
  <p>Given these equivalencies, why take additional selectors and projections at all? What is the benefit of violating the single responsibility principle in this way?</p>
  <p>^1: Or nearly so; <code>last</code> passes the source observable to the predicate, but <code>filter</code> does not. Most predicates will not need that parameter, and the few who do can use some pipe gymnastics:</p>
  <pre><code>source.pipe(src =&gt; {
    const p2 = (value, index) =&gt; p(value, index, src)
    return filter(p2)(src)
  })
  </code></pre>