8 ms·
The JavaScript Pipeline Operator
- theLotusGambit 8y agoInteresting. This proposal would for the first time allow any javascript to be written in just 5 characters: []+|> Down from the 6 that jsfuck requires: []+!()
- sAbakumoff 8y agorxjs is already available and allows to perform chained transformations by using wide variety of methods.
- yanis_t 8y agoGood point. I've heard about it but never could quite understand if it's useful enough. Can you share some public repos where it's being used?
- sAbakumoff 8y agothe official web-site is pretty informative and has a ton of samples..https://rxjs-dev.firebaseapp.com/api https://rxjs-dev.firebaseapp.com/api - take a look at operators section for example. as for public repos - nowadays any modern front-end app that is built with Angular is using rxjs - it's de factor standard for data processing in angular world.
- yanis_t 8y agoThanks sir. Will take a look
- jbob2000 8y agoI've been converting our eCommerce site to using it. It's OK. Way too complicated for the average developer, it's full of jargon that is not usually present in JS/web development. The use cases they have on their site do not reflect how it is actually used, I spent a lot of time wondering how to translate their examples of clicks and timers into my problems of API calls and route changes. The more I think about how I use it, the more I realize I'm using it to clean up the leaky abstractions from our backend. If our backend was better, promises would meet my needs fully - get the data, stick it in the views. But no. I have to do all these bullshit transformations and call multiple APIs because apparently Java Spring apps are EXTREMELY DIFFICULT to develop...
- WorldMaker 8y agorxjs encourages a pipe() function approach as mentioned in other threads. It would still benefit from a pipe operator replacing that function, as the operator version would be easier to type (in Typescript and Flow) and to some of us aesthetically cleaner. The pipe operator that this article is hoping gets adopted is just a generic version of the rxjs pipe() function.
- icholy 8y agoES6 was needed, but I think js should hit the breaks for new language features for a while.
- ergothus 8y agoI wont agree or disagree yet, but why?
- icholy 8y agoBecause it's easy to add features, but impossible to take them away.
- yanis_t 8y agoI tend to agree with you. The thing is that most people would agree but at the time everyone wants different features. Me personally I even think we could be better without classes and all that "pretend you're writing Java" nonsense
- shados 8y ago> I even think we could be better without classes Absolutely. Classes are also a big part of why there's still a lot of bikeshedding for some new features (class properties, decorators, private fields, etc). Classes are familiar to most developers these days, but they're an absurdly complicated construct. The current implementation in javascript is "maximally minimal", in that the TC39 pushed the minimum they could that was still kind of sortoff useful to get the wheel rolling...but it's still not good enough. They'll need several more updates before they're truly useful. And even when that's all there, they still won't offer much that wasn't already doable, arguably better if less familiar. At the end of the day, ES6 classes were designed back in the days where OOP was getting big in JavaScript. It took so long to release that by the time they were, the field had changed a lot.
- coltonv 8y agoI see this idea that adding classes to JS was a bad thing a lot, but even though I don't ever use classes in my codebase, I don't know why it would make sense to remove them before adding new features, or to stall new features because they exist and I don't like them. In my opinion, we should be moving forward with features that make functional paradigms easier, such as the pipeline operator, regardless of the fact that JS has object oriented features. There's no reason to stall new features just because different people want different features, at this moment we're pleasing no one with the slow release cycle.
- Scarbutt 8y agoHe was whining about lodash but still used it till the end. His lodash and pipeline operator version looked more noisy than the lodash only version.
- nabla9 8y ago>The difference is in how we read it. With pipeline operator data flows from left to the right, and thus making it much more comprehensible without the need to introduce extra variables. Why you need operator? Can't it be done with a function? pipe(64,Math.sqrt)
- weliketocode 8y agoYour example falls apart when making multiple function calls.
- nabla9 8y agoPlease explain.
- Spivak 8y ago64 |> Math.sqrt becomes pipe(64, Math.sqrt) 64 |> Math.sqrt |> Math.sin becomes pipe(pipe(64, Math.sqrt), Math.sin) Assuming pipe was smart and took varags we can make this better. 64 |> Math.sqrt |> Math.sin becomes pipe(64, Math.sqrt, Math.sin)
- Leszek 8y agoI guess you could make pipe variadic: function pipe(val, ...funcs) { for (let f of funcs) val = f(val); } EDIT: seems like I got ninja'd by an edit :)
- nabla9 8y agoJavaScript argument list evaluation is from left to right, right? pipe(64,Math.sqrt,Math.sin) and pipe(pipe(64, Math.sqrt), Math.sin) are equivalent.
- Spivak 8y agoIf you just define a simple function pipe(val, func) => func(val) then they wouldn't be equivalent but you absolutely could define pipe so they would be.
- furgooswft13 8y agoBeen using this in LiveScript for awhile (ls also provides it in the opposite direction <| ). Very useful for chaining functions in a logical order and without unnecessary () nesting. Absolutely needs to be paired with partial application though for multiple argument functions.
- yanis_t 8y agoYeah, partial application is also a stage 1 proposal now. But for now I guess you could also do with auto-curring functions (https://ramdajs.com/ https://ramdajs.com/ or something like that)
- Prefinem 8y agoPiping is relatively easy to write a function for. Here [0] is a package that I wrote that has a few trivial functions (including pipe) for things such as this. 0: https://www.npmjs.com/package/afpf https://www.npmjs.com/package/afpf
- rudolph9 8y agoYou could just use ramda https://ramdajs.com/docs/#pipe https://ramdajs.com/docs/#pipe Not quite as seamless and it would be nice to have |> but ultimatles introduces a lot of complexity. The only good reason I could see is if there is a performance benefit a JavaScript JIT could take advantage of by having the |> operator?
- yanis_t 8y agoHonestly, I don't think so. More likely this will be just a syntactical sugar.
- WorldMaker 8y agoPerformance benefits likely depend on which side of the partial application / currying coin the operator ends up landing on. Some of the partial application proposals would potentially reduce the needs for currying in the language, which would reduce the needs for a lot of variable closures in some libraries. The biggest potential benefit is to typing (in Typescript or Flow), which potentially can provide potentially much better or at least much simpler typing and type inferencing with an operator versus many of the alternatives (such as variadic pipe() functions).
- AdieuToLogic 8y agoFWIW, several language communities call this "the Thrush combinator"[0]. Armed with that term, searching the web for background/info/theory on this topic will be easier. 0 - https://debasishg.blogspot.com/2009/09/thrush-combinator-in-scala.html https://debasishg.blogspot.com/2009/09/thrush-combinator-in-...
- yanis_t 8y agoThanks! Sounds a bit too scientific to my ear but good to know
- AdieuToLogic 8y agoIt is what it is, and what it is in JavaScript is this: Object.prototype.pipeTo = function (functor) { return functor (this); }; function inc (input) { return input + 1; } // this will write out "2" to the console log new Number (1).pipeTo (inc).pipeTo (console.log); HTH
- mbostock 8y agoYou don’t need lodash or a new operator for the example provided: departments .flatMap(d => d.employees) .map(e => e.salary) .reduce((p, v) => Math.max(p, v), 0) That said, the pipe operator is nice because it allows similar chaining patterns on subjects that are not arrays, as shown in the proposal’s README: https://github.com/tc39/proposal-pipeline-operator/blob/master/README.md#introduction https://github.com/tc39/proposal-pipeline-operator/blob/mast...
- yanis_t 8y agoGood point. Is flatMap already supported by browsers or is it a proposal?
- fgheorghe 8y agohttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flatMap#Browser_compatibility https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe... Is one of many results google returns on the topic.
- mullsork 8y agoStill a proposal and experimental, stage 3.
- porphyrogene 8y agoBoth flat[1] and flatMap[2] are unsupported in Edge, IE and Node. 1. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flat#Browser_compatibility https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe... 2. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flatMap#Browser_compatibility https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
- savanaly 8y agoRealistically, there's always a few functions I want to call on my data that aren't part of the prototype of the thing I'm transforming. And then this pipe operator is called for.
- phillipcarter 8y agoIf you want to see how the operator "feels" in practice, I recommend trying out F#[0] or Elixir[1]. Hint: it's pretty great! [0]: https://www.microsoft.com/net/languages/fsharp https://www.microsoft.com/net/languages/fsharp [1]: https://elixir-lang.org/ https://elixir-lang.org/
- gedy 8y ago> "Expressions Math.sqrt(64) and 64 |> Math.sqrt are equivalent. The difference is in how we read it. With pipeline operator data flows from left to the right, and thus making it much more comprehensible" Ugh, no, that's a very subjective statement, 64 |> Math.sqrt is not "much more comprehensible" assuming especially for beginners.
- williamdclt 8y agoI agree that this example isn't convincing, I also prefer the "vanilla" Math.sqrt(64). It's more convincing (IMO) when chaining calls, eg: Math.sqrt(Math.ceil(Math.sin(64))) VS. 64 |> Math.sin |> Math.ceil |> Math.sqrt
- mercer 8y agoI used to feel that way until I got comfortable with Elixir and its pipe operator. I think without prior knowledge the latter, which is interpreted left-to-right, is more intuitive: "take some data, do x, do y, do z"
- tracker1 8y agoMy only real criticism, is it would be nice if it supported generators/promises as an alternative to for-await syntax.
- WorldMaker 8y agoIxJS [1] already has pipeable functions for working with AsyncIterable (the underlying interface for the proposed for-await-of syntax). [1] https://github.com/ReactiveX/IxJS https://github.com/ReactiveX/IxJS