4 ms·
This is quite elegant! Direct link to the source of OP's pipe function and recursive type definitions: https://github.com/MathisBullinger/froebel/blob/main/pip
by btown 4y ago
This is quite elegant!
Direct link to the source of OP's pipe function and recursive type definitions: https://github.com/MathisBullinger/froebel/blob/main/pipe.ts#L4 https://github.com/MathisBullinger/froebel/blob/main/pipe.ts...
On a related note, I've been frustrated by the slow progress on https://github.com/tc39/proposal-pipeline-operator https://github.com/tc39/proposal-pipeline-operator - specifically the thread in https://github.com/tc39/proposal-pipeline-operator/issues/91 https://github.com/tc39/proposal-pipeline-operator/issues/91 which has 668 comments over 4+ years and shows no meaningful sign of consensus.
The TC39 group is (justifiably) very concerned about backwards and future compatibility, and Typescript has a policy of not introducing syntax that is in scope for Javascript itself until the syntax has formally reached a stable state (see: https://github.com/Microsoft/TypeScript/issues/2103#issuecomment-182195915 https://github.com/Microsoft/TypeScript/issues/2103#issuecom...) - so we're far from having a pure operator for this.
But `pipe((n: number) => n.toString(), (a: string) => a+' ')(3)` is as clean as I've ever seen it get.
And to use it in an ad-hoc way for left-to-right readability (and for code that will be maintained by those who think curry is just a tasty dish), it's trivial to implement an applyPipe on top:
applyPipe('foo', strip, title, (s: string) => `${s}: bar`)
OP - it would be great to have that, or something named slightly better, out of the box!
- ledauphin 4y agoin the Python library `returns`, `applyPipe` is called `flow`, and I agree that it's a very handy utility to have on top of a pipe.
- upzylon 4y agoThanks for linking the code, I meant to link to the pipe section of the README but obviously botched that and can't change it now :) I was really exited about the pipe proposal and actively followed the discussion like 4 years ago. But with every passing year of no progress my excitement is slowly dying. An `applyPipe` function is an interesting idea. My only concern with it is that the first function in the pipe could have more (or less) than one argument. And in that case how would you know where the arguments stop and the functions begin? Maybe the first parameter should be an array of the arguments. Or applyPipe could be of the form applyPipe(1, 2)(add, square, whatever). What do you think? If there is interest in this I'll add it.
- btown 4y agoIf I'm reaching for this form, I'm likely thinking about a pipeline of unary functions, and the TC39 proposal seems to take the same approach. Plus, doesn't every other function in the pipeline need to be unary after the first? As a half-baked thought, perhaps callPipe would take exactly one non-function argument to start the pipeline (which would appeal to most use cases), and applyPipe could take an array of args, mimicking the call/apply duality in native JS?
- upzylon 4y agoYes, every function except the first one needs to have exactly one argument. Others have also said that `pipe` is not an ideal name for the function. So perhaps renaming it to `compose` and have `pipe` be of the form `pipe(arg, funA, funB, ...)` (like you suggested for `applyPipe`) might be the solution. Will need to think about it a bit more.
- anderskaseorg 4y agoNote ‘compose’ conventionally connotes a right-to-left order, so that (f ∘ g ∘ h)(x) = f(g(h(x))).
- dan-robertson 4y agoIs there an implementation where ‘then’ is added to Object.prototype as: function(f, ...preargs) { return f(...preargs, this) } And then you can use it to pipeline sync and async things together? It’s still kinda bad and seems pretty crazy though. Some obvious issues are: - the preargs thing presumably doesn’t work for promises so you’d need to use bind. - there’s no great way to specify ‘the function which is property foo of the object being operated on’ to e.g. map an array that is in a promise you can’t write .then(.map, …). But I think this is also a problem with other pipe implementations.
- AprilArcus 4y agoI think `Object.prototype.then` would break every source file that uses `typeof o?.then === 'function'` as a check for PromiseLike behavior.
- deleted 4y ago[deleted]
- dclowd9901 4y agoTrying to understand this: is the lambda symbol defined somewhere globally? How can they just use it Willy nilly as a generic Stand-in for a spread parameter type?
- upzylon 4y agoIt's just an identifier like any other defined in types.ts: https://github.com/MathisBullinger/froebel/blob/main/types.ts#L1 https://github.com/MathisBullinger/froebel/blob/main/types.t... It's defined as type λ<TA extends any[] = any[], TR = any> = (...args: TA) => TR; meaning λ is just any function and λ<[number], string> would be the type of a function that takes a number as its only argument and returns a string.
- dclowd9901 4y agoOk that’s what I thought, thanks!
- WorldMaker 4y agoJS (and TS thereby) allows arbitrary unicode in identifiers (variable names, class names, [TS] type names). The lambda symbol is just acting as the name of a type parameter instead of something more ASCII usual like `T` or `F`. There's a lot of interesting discussions around it as some math libraries like to use math symbols and greek letters and sometimes even emoji as variable/class names in JS and other developers have a gut reaction that they do not like it.
- upzylon 4y agoapplyPipe is added now: https://github.com/MathisBullinger/froebel#applypipe https://github.com/MathisBullinger/froebel#applypipe It's included in version 0.21.0