TE
科技回声
首页24小时热榜最新最佳问答展示工作
GitHubTwitter
首页

科技回声

基于 Next.js 构建的科技新闻平台,提供全球科技新闻和讨论内容。

GitHubTwitter

首页

首页最新最佳问答展示工作

资源链接

HackerNews API原版 HackerNewsNext.js

© 2025 科技回声. 版权所有。

Pipelining might be my favorite programming language feature

372 点作者 Mond_20 天前

70 条评论

invalidator19 天前
The author keeps calling it &quot;pipelining&quot;, but I think the right term is &quot;method chaining&quot;.<p>Compare with a simple pipeline in bash:<p><pre><code> grep needle &lt; haystack.txt | sed &#x27;s&#x2F;foo&#x2F;bar&#x2F;g&#x27; | xargs wc -l </code></pre> Each of those components executes in parallel, with the intermediate results streaming between them. You get a similar effect with coroutines.<p>Compare Ruby:<p><pre><code> data = File.readlines(&quot;haystack.txt&quot;) .map(&amp;:strip) .grep(&#x2F;needle&#x2F;) .map { |i| i.gsub(&#x27;foo&#x27;, &#x27;bar&#x27;) } .map { |i| File.readlines(i).count } </code></pre> In that case, each line is processed sequentially, with a complete array being created between each step. Nothing actually gets pipelined.<p>Despite being clean and readable, I don&#x27;t tend to do it any more, because it&#x27;s harder to debug. More often these days, I write things like this:<p><pre><code> data = File.readlines(&quot;haystack.txt&quot;) data = data.map(&amp;:strip) data = data.grep(&#x2F;needle&#x2F;) data = data.map { |i| i.gsub(&#x27;foo&#x27;, &#x27;bar&#x27;) } data = data.map { |i| File.readlines(i).count } </code></pre> It&#x27;s ugly, but you know what? I can set a breakpoint anywhere and inspect the intermediate states without having to edit the script in prod. Sometimes ugly and boring is better.
评论 #43757694 未加载
评论 #43759251 未加载
评论 #43758620 未加载
评论 #43763933 未加载
评论 #43757999 未加载
评论 #43777207 未加载
评论 #43758107 未加载
评论 #43758347 未加载
评论 #43758480 未加载
评论 #43760572 未加载
评论 #43758397 未加载
评论 #43761814 未加载
评论 #43763062 未加载
评论 #43758623 未加载
评论 #43762414 未加载
评论 #43758881 未加载
评论 #43757713 未加载
评论 #43760197 未加载
评论 #43760752 未加载
评论 #43758407 未加载
bnchrch20 天前
I&#x27;m personally someone who advocates for languages to keep their feature set small and shoot to achieve a finished feature set quickly.<p>However.<p>I would be lying if I didn&#x27;t secretly wish that all languages adopted the `|&gt;` syntax from Elixir.<p>```<p>params<p>|&gt; Map.get(&quot;user&quot;)<p>|&gt; create_user()<p>|&gt; notify_admin()<p>```
评论 #43751889 未加载
评论 #43751880 未加载
评论 #43758145 未加载
评论 #43762656 未加载
评论 #43761604 未加载
评论 #43757536 未加载
评论 #43762000 未加载
评论 #43752857 未加载
评论 #43754497 未加载
评论 #43757539 未加载
评论 #43757027 未加载
评论 #43752525 未加载
评论 #43756201 未加载
评论 #43753353 未加载
评论 #43759007 未加载
评论 #43760315 未加载
Straw19 天前
Lisp macros allow a general solution to this that doesn&#x27;t just handle chained collection operators but allows you to decide the order in which you write any chain of calls.<p>For example, we can write: (foo (bar (baz x))) as (-&gt; x baz bar foo)<p>If there are additional arguments, we can accommodate those too: (sin (* x pi) as (-&gt; x (* pi) sin)<p>Where expression so far gets inserted as the first argument to any form. If you want it inserted as the last argument, you can use -&gt;&gt; instead:<p>(filter positive? (map sin x)) as (-&gt;&gt; x (map sin) (filter positive?))<p>You can also get full control of where to place the previous expression using as-&gt;.<p>Full details at <a href="https:&#x2F;&#x2F;clojure.org&#x2F;guides&#x2F;threading_macros" rel="nofollow">https:&#x2F;&#x2F;clojure.org&#x2F;guides&#x2F;threading_macros</a>
评论 #43756727 未加载
评论 #43761008 未加载
评论 #43758146 未加载
duped19 天前
A pipeline operator is just partial application with less power. You should be able to bind any number of arguments to any places in order to create a new function and &quot;pipe&quot; its output(s) to any other number of functions.<p>One day, we&#x27;ll (re)discover that partial application is actually incredibly useful for writing programs and (non-Haskell) languages will start with it as the primitive for composing programs instead of finding out that it would be nice later, and bolting on a restricted subset of the feature.
评论 #43758922 未加载
评论 #43756644 未加载
评论 #43761777 未加载
评论 #43753625 未加载
SimonDorfman20 天前
The tidyverse folks in R have been using that for a while: <a href="https:&#x2F;&#x2F;magrittr.tidyverse.org&#x2F;reference&#x2F;pipe.html" rel="nofollow">https:&#x2F;&#x2F;magrittr.tidyverse.org&#x2F;reference&#x2F;pipe.html</a>
评论 #43751649 未加载
评论 #43751631 未加载
评论 #43756857 未加载
评论 #43751556 未加载
评论 #43762065 未加载
amai19 天前
Pipelining looks nice until you have to debug it. And exception handling is also very difficult, because that means to add forks into your pipelines. Pipelines are only good for programming the happy path.
评论 #43754677 未加载
评论 #43756802 未加载
评论 #43756601 未加载
评论 #43758844 未加载
评论 #43757213 未加载
评论 #43757470 未加载
评论 #43756620 未加载
评论 #43756548 未加载
评论 #43755377 未加载
kordlessagain20 天前
While the author claims &quot;semantics beat syntax every day of the week,&quot; the entire article focuses on syntax preferences rather than semantic differences.<p>Pipelining can become hard to debug when chains get very long. The author doesn&#x27;t address how hard it can be to identify which step in a long chain caused an error.<p>They do make fun of Python, however. But don&#x27;t say much about why they don&#x27;t like it other than showing a low-res photo of a rock with a pipe routed around it.<p>Ambiguity about what constitutes &quot;pipelining&quot; is the real issue here. The definition keeps shifting throughout the article. Is it method chaining? Operator overloading? First-class functions? The author uses examples that function very differently.
评论 #43751527 未加载
评论 #43751496 未加载
评论 #43751725 未加载
评论 #43751535 未加载
评论 #43752103 未加载
评论 #43756922 未加载
评论 #43751490 未加载
epolanski20 天前
I personally like how effect-ts allows you to write both pipelines or imperative code to express the very same things.<p>Building pipelines:<p><a href="https:&#x2F;&#x2F;effect.website&#x2F;docs&#x2F;getting-started&#x2F;building-pipelines&#x2F;" rel="nofollow">https:&#x2F;&#x2F;effect.website&#x2F;docs&#x2F;getting-started&#x2F;building-pipelin...</a><p>Using generators:<p><a href="https:&#x2F;&#x2F;effect.website&#x2F;docs&#x2F;getting-started&#x2F;using-generators&#x2F;" rel="nofollow">https:&#x2F;&#x2F;effect.website&#x2F;docs&#x2F;getting-started&#x2F;using-generators...</a><p>Having both options is great (at the beginning effect had only pipe-based pipelines), after years of writing effect I&#x27;m convinced that most of the time you&#x27;d rather write and read imperative code than pipelines which definitely have their place in code bases.<p>In fact most of the community, at large, converged at using imperative-style generators over pipelines and having onboarded many devs and having seen many long-time pipeliners converging to classical imperative control flow seems to confirm both debugging and maintenance seem easier.
vitus19 天前
I think the biggest win for pipelining in SQL is the fact that we no longer have to explain that SQL execution order has nothing to do with query order, and we no longer have to pretend that we&#x27;re mimicking natural language. (That last point stops being the case when you go beyond &quot;SELECT foo FROM table WHERE bar LIMIT 10&quot;.)<p>No longer do we have to explain that expressions are evaluated in the order of FROM -&gt; JOIN -&gt; ON -&gt; SELECT -&gt; WHERE -&gt; GROUP BY -&gt; HAVING -&gt; ORDER BY -&gt; LIMIT (and yes, I know I&#x27;m missing several other steps). We can simply just express how our data flows from one statement to the next.<p>(I&#x27;m also stating this as someone who has yet to play around with the pipelining syntax, but honestly anything is better than the status quo.)
评论 #43756954 未加载
osigurdson20 天前
C# has had &quot;Pipelining&quot; (aka Linq) for 17 years. I do miss this kind of stuff in Go a little.
评论 #43752242 未加载
评论 #43751851 未加载
singularity200120 天前
I tried to convince the julia authors to make a.b(c) synonymous to b(a,c) like in nim (for similar reasons as in the article). They didn&#x27;t like it.
评论 #43760005 未加载
评论 #43752313 未加载
0xf00ff00f20 天前
First example doesn&#x27;t look bad in C++23:<p><pre><code> auto get_ids(std::span&lt;const Widget&gt; data) { return data | filter(&amp;Widget::alive) | transform(&amp;Widget::id) | to&lt;std::vector&gt;(); }</code></pre>
评论 #43759085 未加载
评论 #43755642 未加载
评论 #43752537 未加载
cutler20 天前
Clojure has pipeline functions -&gt; and -&gt;&gt; without resorting to OO dot syntax.
评论 #43752301 未加载
okayishdefaults19 天前
Surprised that the term &quot;tacit programming&quot; wasn&#x27;t mentioned once in the article.<p>Point-free style and pipelining were meant for each other. <a href="https:&#x2F;&#x2F;en.m.wikipedia.org&#x2F;wiki&#x2F;Tacit_programming" rel="nofollow">https:&#x2F;&#x2F;en.m.wikipedia.org&#x2F;wiki&#x2F;Tacit_programming</a>
评论 #43759535 未加载
mrkeen20 天前
<p><pre><code> data.iter() .filter(|w| w.alive) .map(|w| w.id) .collect() collect(map(filter(iter(data), |w| w.alive), |w| w.id)) </code></pre> The second approach is open for extension - it allows you to write new functions on old datatypes.<p>&gt; Quick challenge for the curious Rustacean, can you explain why we cannot rewrite the above code like this, even if we import all of the symbols?<p>Probably for lack of<p>&gt; weird operators like &lt;$&gt;, &lt;*&gt;, $, or &gt;&gt;=
评论 #43751682 未加载
评论 #43752080 未加载
评论 #43756744 未加载
rocqua19 天前
The left associativity of functions really doesn&#x27;t work well with English reading left to right. I found this especially clear with the&#x27;composition opperator&#x27; of functions. Where f.g has to mean f _after_ g because you really want:<p><pre><code> f.g = f(g(x)) </code></pre> Based on this, I think a reverse polish type of notation would be a lot better. Though perhaps it is a lot nicer to think of &quot;the sine of an angle&quot; than &quot;angle sine-ed&quot;.<p>Not that it matters much, the switching costs are immense. Getting people able to teach it would be impossible, and collaboration with people taught in the other system would be horrible. I am doubtful I could make the switch, even if I wanted.
dapperdrake20 天前
Pipelining in software is covered by Richard C. Waters (1989a, 1989b). Wrangles this library to work with JavaScript. Incredibly effective. Much faster at <i>writing</i> and composing code. And this code <i>executes</i> much faster.<p><a href="https:&#x2F;&#x2F;dspace.mit.edu&#x2F;handle&#x2F;1721.1&#x2F;6035" rel="nofollow">https:&#x2F;&#x2F;dspace.mit.edu&#x2F;handle&#x2F;1721.1&#x2F;6035</a><p><a href="https:&#x2F;&#x2F;dspace.mit.edu&#x2F;handle&#x2F;1721.1&#x2F;6031" rel="nofollow">https:&#x2F;&#x2F;dspace.mit.edu&#x2F;handle&#x2F;1721.1&#x2F;6031</a><p><a href="https:&#x2F;&#x2F;dapperdrake.neocities.org&#x2F;faster-loops-javascript.html" rel="nofollow">https:&#x2F;&#x2F;dapperdrake.neocities.org&#x2F;faster-loops-javascript.ht...</a>
snthpy17 天前
Nice post and I very much agree!<p>In fact I tried to make some similar points in my CMU &quot;SQL or Death&quot; Seminar Series talk on PRQL (<a href="https:&#x2F;&#x2F;db.cs.cmu.edu&#x2F;events&#x2F;sql-death-prql-pipelined-relational-query-language&#x2F;" rel="nofollow">https:&#x2F;&#x2F;db.cs.cmu.edu&#x2F;events&#x2F;sql-death-prql-pipelined-relati...</a>) in that I would love to see PRQL (or something like it) become a universal DSL for data pipelines. Ideally this wouldn&#x27;t even have to go through some query engine and could just do some (byte)codegen for your target language.<p>P.S. Since you mentioned the Google Pipe Syntax HYTRADBOI 2025 talk, I just want to throw out that I also have a 10 min version for the impatient: <a href="https:&#x2F;&#x2F;www.hytradboi.com&#x2F;2025&#x2F;deafce13-67ac-40fd-ac4b-175d53318a78-prql-a-modern-pipelined-sql-replacement" rel="nofollow">https:&#x2F;&#x2F;www.hytradboi.com&#x2F;2025&#x2F;deafce13-67ac-40fd-ac4b-175d5...</a> That&#x27;s just a PRQL overview though. The Universal Data Pipeline DSL ideas and comparison to LINQ, F#, ... are only in the CMU talk. I also go a bit into imperative vs declarative and point out that since &quot;pipelining&quot; is just function composition it should really be &quot;functional&quot; rather than imperative or declarative (which also came up in this thread).
andyferris19 天前
Pipelining is great! Though sometimes you want to put the value in the first argument of a function, or a different location, or else call a method... it can be nice to simply refer to the value directly with `_` or `%` or `$` or something.<p>In fact, I always thought it would be a good idea for all statement blocks (in any given programming language) to allow an implicit reference to the value of the previous statement. The pipeline operation would essentially be the existing semicolons (in a C-like language) and there would be a new symbol or keyword used to represent the previous value.<p>For example, the MATLAB REPL allows for referring to the previous value as `ans` and the Julia REPL has inherited the same functionality. You can copy-paste this into the Julia REPL today:<p><pre><code> [1, 2, 3]; map(x -&gt; x * 2, ans); @show ans; filter(x -&gt; x &gt; 2, ans); @show ans; sum(ans) </code></pre> You can&#x27;t use this in Julia outside the REPL, and I don&#x27;t think `ans` is a particularly good keyword for this, but I honestly think the concept is good enough. The same thing in JavaScript using `$` as an example:<p><pre><code> { [1 ,2, 3]; $.map(x =&gt; x * 2); (console.log($), $); $.filter(x =&gt; x &gt; 2); (console.log($), $); $.reduce((acc, next) =&gt; acc + next, 0) } </code></pre> I feel it would work best with expression-based languages having blocks that return their final value (like Rust) since you can do all sorts of nesting and so-on.
评论 #43759521 未加载
davemp19 天前
Computer scientists continue to pick terrible names. Pipelining is already an overloaded concept that implies some type of operation level parallelism. Picking names like this does everyone in the field a disservice. Calling it something like “composition chain” would be much clearer with respect to existing literature in the field. Maybe I’m being nitpicky, but sometimes it feels like the tower of babel parable talking to folks who use different ecosystems.
huyegn19 天前
I liked the pipelining syntax so much from pyspark and linq that I ended up implementing my own mini linq-like library for python to use in local development. It&#x27;s mainly used in quick data processing scripts that I run locally. The syntax just makes everything much nicer to work with.<p><a href="https:&#x2F;&#x2F;datapad.readthedocs.io&#x2F;en&#x2F;latest&#x2F;quickstart.html#overview" rel="nofollow">https:&#x2F;&#x2F;datapad.readthedocs.io&#x2F;en&#x2F;latest&#x2F;quickstart.html#ove...</a>
评论 #43756610 未加载
weinzierl19 天前
I suffer from (what I call) bracket claustrophobia. Whenever brackets get nested too deep I makes me uncomfortable. But I fully realize that there are people who are the complete opposite. Lisp programmers are apparently as claustrophil as cats and spelunkers.
评论 #43753718 未加载
RHSeeger20 天前
I feel like, at least in some cases, the article is going out of its way to make the &quot;undesired&quot; look worse than it needs to be. Compairing<p><pre><code> fn get_ids(data: Vec&lt;Widget&gt;) -&gt; Vec&lt;Id&gt; { collect(map(filter(map(iter(data), |w| w.toWingding()), |w| w.alive), |w| w.id)) } </code></pre> to<p><pre><code> fn get_ids(data: Vec&lt;Widget&gt;) -&gt; Vec&lt;Id&gt; { data.iter() .map(|w| w.toWingding()) .filter(|w| w.alive) .map(|w| w.id) .collect() } </code></pre> The first one would read more easily (and, since it called out, diff better)<p><pre><code> fn get_ids(data: Vec&lt;Widget&gt;) -&gt; Vec&lt;Id&gt; { collect( map( filter( map(iter(data), |w| w.toWingding()), |w| w.alive), |w| w.id)) } </code></pre> Admittedly, the chaining is still better. But a fair number of the article&#x27;s complaints are about the lack of newlines being used; not about chaining itself.
评论 #43752870 未加载
评论 #43753436 未加载
评论 #43752913 未加载
bjourne19 天前
In concatenative languages with an implicit stack (Factor) that expression would read:<p><pre><code> iter [ alive? ] filter [ id&gt;&gt; ] map collect </code></pre> The beauty of this is that everything can be evaluated strictly left-to-right. Every single symbol. &quot;Pipelines&quot; in other languages are never fully left-to-right evaluated. For example, &quot;.filter(|w| w.alive)&quot; in the author&#x27;s example requires one to switch from postfix to infix evaluation to evaluate the filter application.<p>The major advantage is that handling multiple streams is natural. Suppose you want to compute the dot product of two files where each line contains a float:<p><pre><code> fileA fileB [ lines [ str&gt;float ] map ] bi@ [ mul ] 2map 0 [ + ] reduce</code></pre>
评论 #43761967 未加载
relaxing19 天前
These articles never explain what’s wrong with calling each function separately and storing each return value in an intermediate variable.<p>Being able to inspect the results of each step right at the point you’ve written it is pretty convenient. It’s readable. And the compiler will optimize it out.
flakiness19 天前
After seeing LangChain abusing the &quot;|&quot; operator overload for pipeline-like DSL, I followed the suite at work and I loved it. It&#x27;s especially good when you use it in a notebook environment where you literally build the pipeline incrementally through repl.
hliyan20 天前
I always wondered how programming would be if we hadn&#x27;t designed the assignment operator to be consistent with mathematics, and instead had it go LHS -&gt; RHS, i.e. you perform the operation and <i>then</i> decide its destination, much like Unix pipes.
评论 #43752057 未加载
评论 #43752746 未加载
评论 #43755008 未加载
EnPissant19 天前
I don&#x27;t know. I find this:<p><pre><code> fn get_ids(data: Vec&lt;Widget&gt;) -&gt; Vec&lt;Id&gt; { let mut result = Vec::new(); for widget in &amp;data { if widget.alive { result.push(widget.id); } } result } </code></pre> more readable than this:<p><pre><code> fn get_ids(data: Vec&lt;Widget&gt;) -&gt; Vec&lt;Id&gt; { data.iter() .filter(|w| w.alive) .map(|w| w.id) .collect() } </code></pre> and I also dislike Rust requiring you to write &quot;mut&quot; for function mutable values. It&#x27;s mostly just busywork and dogma.
评论 #43759541 未加载
otsukare19 天前
I wish more languages would aim for infix functions (like Haskell and Kotlin), rather than specifically the pipe operator.
neuroelectron19 天前
I really like the website layout. I&#x27;m guessing that they&#x27;re optimizing for Kindle or other e-paper readers.
评论 #43756690 未加载
layer819 天前
The one thing that I don’t like about pipelining (whether using a pipe operator or method chaining), is that assigning the result to a variable goes in the wrong direction, so to speak. There should be an equivalent of the shell’s `&gt;` for piping into a variable as the final step. Of course, if the variable is being declared at the same time, whatever the concrete syntax is would still require some getting used to, being “backwards” compared to regular assignment&#x2F;initialization.
评论 #43762162 未加载
评论 #43754735 未加载
1899-12-3020 天前
You can somewhat achieve a pipelined like system in sql by breaking down your steps into multiple CTEs. YMMV on the performance though.
评论 #43752168 未加载
immibis19 天前
We had this - it was called variables. You could do:<p>x = iter(data);<p>y = filter(x, w=&gt;w.isAlive);<p>z = map(y, w=&gt;w.id);<p>return collect(z);<p>It doesn&#x27;t need new syntax, but to implement this with the existing syntax you do have to figure out what the intermediate objects are, but you also have that problem with &quot;pipelining&quot; unless it compiles the whole chain into a single thing a la Linq.
shae20 天前
If Python object methods returned `self` by default instead of `None` you could do this in Python too!<p>This is my biggest complaint about Python.
评论 #43751464 未加载
wavemode19 天前
&gt; At this point you might wonder if Haskell has some sort of pipelining operator, and yes, it turns out that one was added in 2014! That’s pretty late considering that Haskell exists since 1990.<p>The tone of this (and the entire Haskell section of the article, tbh) is rather strange. Operators aren&#x27;t special syntax and they aren&#x27;t &quot;added&quot; to the language. Operators are just functions that by default use infix position. (In fact, any function can be called in infix position. And operators can be called in prefix position.)<p>The commit in question added &amp; to the prelude. But if you wanted &amp; (or any other character) to represent pipelining you have always been able to define that yourself.<p>Some people find this horrifying, which is a perfectly valid opinion (though in practice, when working in Haskell it isn&#x27;t much of a big deal if you aren&#x27;t foolish with it). But at least get the facts correct.
mexicocitinluez20 天前
LINQ is easily one of C#&#x27;s best features.
评论 #43755231 未加载
pxc19 天前
Maybe it&#x27;s because I love the Unix shell environment so much, but I also really love this style. I try to make good use of it in every language I write code in, and I think it helps make my control flow very simple. With lots of pipelines, and few conditionals or loops, everything becomes very easy to follow.
jmyeet19 天前
Hack (Facebook&#x27;s PHP fork) has this feature. It&#x27;s called pipes [1]:<p><pre><code> $x = vec[2,1,3] |&gt; Vec\map($$, $a ==&gt; $a * $a) &#x2F;&#x2F; $$ with value vec[2,1,3] |&gt; Vec\sort($$); &#x2F;&#x2F; $$ with value vec[4,1,9] </code></pre> It is a nice feature. I do worry about error reporting with any feature that combines multiple statements into a single statement, which is essentially what this does. In Java, there was always an issue with NullPointerExceptiosn being thrown and if you chain several things together you&#x27;re never sure which one was null.<p>[1]: <a href="https:&#x2F;&#x2F;docs.hhvm.com&#x2F;hack&#x2F;expressions-and-operators&#x2F;pipe" rel="nofollow">https:&#x2F;&#x2F;docs.hhvm.com&#x2F;hack&#x2F;expressions-and-operators&#x2F;pipe</a>
评论 #43757848 未加载
rokob19 天前
I learned the term for this as a fluent interface. Pipelining is in my mind something quite different.
raggi19 天前
&gt; (This is not real Rust code. Quick challenge for the curious Rustacean, can you explain why we cannot rewrite the above code like this, even if we import all of the symbols?)<p>Um, you can:<p><pre><code> #![feature(import_trait_associated_functions)] use Iterator::{collect, map, filter}; fn get_ids2(data: Vec&lt;usize&gt;) -&gt; Vec&lt;usize&gt; { collect(map(filter(&lt;[_]&gt;::iter(&amp;data), |v| ...), |v| ...)) } </code></pre> and you can because it&#x27;s lazy, which is also the same reason you can write it the other way.. in rust. I think the author was getting at an ownership trap, but that trap is avoided the same way for both arrangements, the call order is the same in both arrangements. If the calls were actually a pipeline (if collect didn&#x27;t exist and didn&#x27;t need to be called) then other considerations show up.
评论 #43759561 未加载
jiggawatts19 天前
PowerShell has the best pipeline capability of any language I have ever seen.<p>For comparison, UNIX pipes support only trivial byte streams from output to input.<p>PowerShell allows typed object streams where the properties of the object are automatically wired up to named parameters of the commands on the pipeline.<p>Outputs at any stage can not only be wired directly to the next stage but also captured into named variables for use <i>later</i> in the pipeline.<p>Every command in the pipeline also gets begin&#x2F;end&#x2F;cancel handlers automatically invoked so you can set up accumulators, authentication, or whatever.<p>UNIX scripting advocates don’t know what they’re missing out on…
评论 #43768624 未加载
评论 #43759271 未加载
TrianguloY20 天前
Kotlin sort of have it with let (and run)<p><pre><code> a().let{ b(it) }.let{ c(it) }</code></pre>
评论 #43754034 未加载
_heimdall19 天前
Is pipelining the right term here? I&#x27;ve always used the term &quot;transducer&quot; to describe this kind of process, I picked it up from an episode of FunFunFunction if I&#x27;m not mistaken.
评论 #43759543 未加载
评论 #43759031 未加载
zelphirkalt20 天前
To one up this: Of course it is even better, if your language allows you to implement proper pipelining with implicit argument passing by yourself. Then the standard language does not need to provide it and assign meaning to some symbols for pipelining. You can decide for yourself what symbols are used and what you find intuitive.<p>Pipelining can guide one to write a bit cleaner code, viewing steps of computation as such, and not as modifications of global state. It forces one to make each step return a result, write proper functions. I like proper pipelining a lot.
评论 #43751609 未加载
chewbacha20 天前
Is this pipelining or the builder pattern?
评论 #43751814 未加载
评论 #43753701 未加载
评论 #43752089 未加载
taeric19 天前
A thing I really like about pipelines in shell scripts, is all of the buffering and threading implied by them. Semantically, you can see what command is producing output, and what command is consuming it. With some idea of how the CPU will be split by them.<p>This is far different than the pattern described in the article, though. Small shame they have come to have the same name. I can see how both work with the metaphor; such that I can&#x27;t really complain. The &quot;pass a single parameter&quot; along is far less attractive to me, though.
stuaxo19 天前
It&#x27;s part of why JQuery was so great, and the Django ORM.
true_blue19 天前
That new Rhombus language that was featured here recently has an interesting feature where you can use `_` in a function call to act as a &quot;placeholder&quot; for an argument. Essentially it&#x27;s an easy way to partially apply a function. This works very well with piping because it allows you to pipe into any argument of a function (including optional arguments iirc) rather than just the first like many pipe implementations have. It seems really cool!
评论 #43754301 未加载
dpc_0123419 天前
I think there&#x27;s a language syntax to be invented that would make everything suffix&#x2F;pipeline-based. Stack based languages are kind of there, but I don&#x27;t think exactly the same thing.<p>BTW. For people complaining about debug-ability of it: <a href="https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;iter&#x2F;trait.Iterator.html#method.inspect" rel="nofollow">https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;iter&#x2F;trait.Iterator.html#metho...</a> etc.
评论 #43762194 未加载
XorNot19 天前
Every example of why this is meant to be good is contrived.<p>You have a create_user function that doesn&#x27;t error? Has no branches based on type of error?<p>We&#x27;re having arguments over the best way break these over multiple lines?<p>Like.. why not just store intermediate results in variables? Where our branch logic can just be written inline? And then the flow of data can be very simply determined by reading top to bottom?
amelius20 天前
Am I the only one who thinks yuck?<p>Instead of writing: a().b().c().d(), it&#x27;s much nicer to write: d(c(b(a()))), or perhaps (d ∘ c ∘ b ∘ a)().
评论 #43751849 未加载
评论 #43753248 未加载
评论 #43751913 未加载
评论 #43752300 未加载
评论 #43755214 未加载
评论 #43758014 未加载
评论 #43752264 未加载
kissgyorgy19 天前
In Nix, you can do something like this:<p><pre><code> gitRef = with lib; pipe .git&#x2F;HEAD [ readFile trim (splitString &quot;:&quot;) last trim (ref: .&#x2F;git&#x2F;${ref}) readFile trim ]; </code></pre> Super clean and cool!
middayc19 天前
Ryelang has a little different take on this ... op-words and pipe-words: <a href="https:&#x2F;&#x2F;ryelang.org&#x2F;meet_rye&#x2F;specifics&#x2F;opwords&#x2F;" rel="nofollow">https:&#x2F;&#x2F;ryelang.org&#x2F;meet_rye&#x2F;specifics&#x2F;opwords&#x2F;</a>
jesse__19 天前
I&#x27;ve always wondered why more languages don&#x27;t do this. It just makes sense
bcoates19 天前
Why is the SQL syntax so unnecessarily convoluted? SQL is already an operator language, just an overly constrained one due to historical baggage. If you&#x27;re going to allow new syntax at all, you can just do<p><pre><code> from customer left join orders on c_custkey = o_custkey and o_comment not like &#x27;%unusual%&#x27; group by c_custkey alias count(o_orderkey) as count_of_orders group by count_of_orders alias count(*) as count_of_customers order by count_of_customers desc select count_of_customers, count_of_orders; </code></pre> I&#x27;m using &#x27;alias&#x27; here as a strawman keyword for what the slide deck calls a free-standing &#x27;as&#x27; operator because you can&#x27;t reuse that keyword, it makes the grammar a mess.<p>The aliases aren&#x27;t really necessary, you could just write the last line as &#x27;select count(count(*)) ncust, count(*) nord&#x27; if you aren&#x27;t afraid of nested aggregations, and if you are you&#x27;ll never understand window functions, soo...<p>The |&gt; syntax adds visual noise without expressive power, and the novelty &#x27;aggregate&#x27;&#x2F;&#x27;call&#x27; operators are weird special-case syntax for something that isn&#x27;t that complex in the first place.<p>The implicit projection is unnecessary too, for the same reason any decent SQL linter will flag an ambiguous &#x27;select *&#x27;
评论 #43758237 未加载
moralestapia18 天前
(Un)surprisingly, the author ignores this is almost already a thing in JS. What a terrible oversight.<p>Anyway, JS wins again, give it a try if you haven&#x27;t, it&#x27;s one of the best languages out there.
评论 #43762929 未加载
drchickensalad20 天前
I miss F#
评论 #43754109 未加载
kuon20 天前
That&#x27;s also why I enjoy elixir a lot.<p>The |&gt; operator is really cool.
ZYbCRq22HbJ2y719 天前
Its nice sugar, but pretty much any modern widely used language supports &quot;pipelining&quot;, just not of the SML flavor.
bluSCALE419 天前
Same. The sad part is that pipelining seems to be something AI is really good at so I&#x27;m finding myself writing less of it.
jongjong19 天前
Pipelining is great. Currying is horrible. Though currying superficially looks similar to pipelining.<p>One difference is that currying returns an incomplete result (another function) which must be called again at a later time. On the other hand, pipelining usually returns raw values. Currying returns functions until the last step. The main philosophical failure of currying is that it treats logic&#x2F;functions as if they were state which should be passed around. This is bad. Components should be responsible for their own state and should just talk to each other to pass plain information. State moves, logic doesn&#x27;t move. A module shouldn&#x27;t have awareness of what tools&#x2F;logic other modules need to do their jobs. This completely breaks the separation of concerns principle.<p>When you call a plumber to fix your drain, do you need to provide them with a toolbox? Do you even need to know what&#x27;s inside their toolbox? The plumber knows what tools they need. You just show them what the problem is. Passing functions to another module is like giving a plumber a toolbox which you put together by guessing what tools they might need. You&#x27;re not a plumber, why should you decide what tools the plumber needs?<p>Currying encourages spaghetti code which is difficult to follow when functions are passed between different modules to complete the currying. In practice, if one can design code which gathers all the info it needs before calling the function once; this leads to much cleaner and much more readable code.
Weryj19 天前
LINQ was my gateway drug into functional programming, Pipelining is so beautiful.
jaymbo20 天前
This is why I love Scala so much
评论 #43751555 未加载
评论 #43751543 未加载
joeevans100019 天前
Clojure threading, of course.
wslh20 天前
I also like a syntax that includes pipelining parallelization, for example:<p>A<p>.B<p>.C<p><pre><code> || D || E</code></pre>
评论 #43756144 未加载
tantalor20 天前
&gt; allows you to omit a single argument from your parameter list, by instead passing the previous value<p>I have no idea what this is trying to say, or what it has to do with the rest of the article.
评论 #43752498 未加载
guerrilla19 天前
This is just super basic functional programming. Seems like we&#x27;re taking the long way around...
评论 #43753527 未加载
HackerThemAll18 天前
I like how they are unaware of neat F# pipelines or else how they deliberately &quot;forgot&quot; to mention them.
tpoacher19 天前
pipelines are great IF you can easily debug them as easily as temp variable assignments<p>... looking at you R and tidyverse hell.
blindseer20 天前
This article is great, and really distills why the ergonomics of Rust is so great and why languages like Julia are so awful in practice.
评论 #43754254 未加载