Live data from Hacker News

Pipelining might be my favorite programming language feature

herecomesthemoon.net

281–290 of 360 posts

Re: Pipelining might be my favorite programming language feature

#281

Earlier quoted context omitted.

It also has barely seen any activity in years. It is going nowhere. The TC39 committee is utterly dysfunctional and anti-progress, and will not let any this or any other new syntax into JavaScript. Records and tuples has just been killed, despite being cited in surveys as a major missing feature[1]. Pattern matching is stuck in stage 1 and hasn't been presented since 2022. Ditto for type annotations and a million oth…

Records and Tuples weren't stopped because of tc39, but rather the engine developers. Read the notes.

It was also replaced with the Composite proposal, which is similar but not exactly the same.

Re: Pipelining might be my favorite programming language feature

#282
post #194

Earlier quoted context omitted.

I hate to be that guy , but I believe the `|>` syntax started with F# before Elixir picked it up. (No disagreements with your post, just want to give credit where it's due. I'm also a big fan of the syntax)

I turn older then f#, it’s been an ML language thing for a while but not sure where it first appeared

It seems like it originated in the Isabelle proof assistant ML dialect in the mid 90s https://web.archive.org/web/20190217164203/https://blogs.msd...

Re: Pipelining might be my favorite programming language feature

#283
post #274

I don't know. I find this: fn get_ids(data: Vec ) -> Vec { let mut result = Vec::new(); for widget in &data { if widget.alive { result.push(widget.id); } } result } more readable than this: fn get_ids(data: Vec ) -> Vec { data.iter() .filter(|w| w.alive) .map(|w| w.id) .collect() } and I also dislike Rust requiring you to write "mut" for function mutable values. It's mostly just busywork and dogma.

Yeah, I really wanted to avoid a discussion over functional vs. imperative programming, so I just... didn't talk about the imperative style at all, and just said so in the first section. I think the imperative style isn't as readable (of course I would), but that's absolutely a discussion for another day, and I get why people prefer it.

I think it’s important to point out what the imperative version would look like because I think the fundamental reason that the method chaining approach is more readable is because it more closely resembles imperative code. When reading it, you start with a vector and then you mutate it in various ways before returning it. I understand that’s not how it’s implemented under the hood, but I don’t think it really matters.

Re: Pipelining might be my favorite programming language feature

#284
post #267

The author keeps calling it "pipelining", but I think the right term is "method chaining". Compare with a simple pipeline in bash: grep needle Each of those components executes in parallel, with the intermediate results streaming between them. You get a similar effect with coroutines. Compare Ruby: data = File.readlines("haystack.txt") .map(&:strip) .grep(/needle/) .map { |i| i.gsub('foo', 'bar') } .map { |i| File.re…

I don’t find your “seasoned developer” version ugly at all. It just looks more mature and relaxed. It also has the benefits that you can actually do error handling and have space to add comments. Maybe people don’t like it because of the repetition of “data =“ but in fact you could use descriptive new variable names making the code even more readable (auto documenting). I’ve always felt method chaining to look “cramp…

I have a lot of code like this. The reason I prefer pipelines now is the mental overhead of understanding the intermediate step variables.

Something like

  lines = File.readlines("haystack.txt")
  stripped_lines = lines.map(&:strip)
  needle_lines = stripped_lines.grep(/needle/)
  transformed_lines = needle_lines.map { |line| line.gsub('foo', 'bar') }
  line_counts = transformed_lines.map { |file_path| File.readlines(file_path).count }
is a hell to read and understand later imo. You have to read a lot of intermediate variables that do not matter in anything else in the code after you set it up, but you do not know in advance necessarily which matter and which don't unless you read and understand all of it. Also, it pollutes your workspace with too much stuff, so while this makes it easier to debug, it makes it also harder to read some time after. Moreover becomes even more crumpy if you need to repeat code. You probably need to define a function block then, which moves the crumpiness there.

What I do now is starting defining the transformation in each step as a pure function, and chain them after once everything works, plus enclosing it into an error handler so that I depend on breakpoint debugging less.

There is certainly a trade off, but as a codebase grows larger and deals with more cases where the same code needs to be applied, the benefits of a concise yet expressive notation shows.

Re: Pipelining might be my favorite programming language feature

#285
post #267

The author keeps calling it "pipelining", but I think the right term is "method chaining". Compare with a simple pipeline in bash: grep needle Each of those components executes in parallel, with the intermediate results streaming between them. You get a similar effect with coroutines. Compare Ruby: data = File.readlines("haystack.txt") .map(&:strip) .grep(/needle/) .map { |i| i.gsub('foo', 'bar') } .map { |i| File.re…

I don’t find your “seasoned developer” version ugly at all. It just looks more mature and relaxed. It also has the benefits that you can actually do error handling and have space to add comments. Maybe people don’t like it because of the repetition of “data =“ but in fact you could use descriptive new variable names making the code even more readable (auto documenting). I’ve always felt method chaining to look “cramp…

Code in this "named-pipeline" style is already self-documenting: using the same variable name makes it clear that we are dealing with a pipeline/chain. Using more descriptive names for the intermediate steps hides this, making each line more readable (and even then you're likely to end up with `dataStripped = data.map(&:strip)`) at the cost of making the block as a whole less readable.

Re: Pipelining might be my favorite programming language feature

#286
post #24

I'm personally someone who advocates for languages to keep their feature set small and shoot to achieve a finished feature set quickly. However. I would be lying if I didn't secretly wish that all languages adopted the `|>` syntax from Elixir. ``` params |> Map.get("user") |> create_user() |> notify_admin() ```

The pipe operator relies on the first argument being the subject of the operation. A lot of languages have the arguments in a different order, and OO languages sometimes use function chaining to get a similar result.

You could make use of `flip` from Haskell.

    flip :: (x -> y -> z) -> (y -> x -> x)
    flip f = \y -> \x -> f x y

    x |> (flip f)(y)    -- f(x, y)

Re: Pipelining might be my favorite programming language feature

#287

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't like it.

I don't like it either, because it promotes method `b` to the global namespace. There may be many such `b` methods on different, unrelated types. I think that the latter should be prefixed with the typename or module name.

   a.b(c) == AType.b(a, c)   (or AType::b(a, c) , C++ style)

Re: Pipelining might be my favorite programming language feature

#288

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't like it.

I don't like it either, because it promotes method `b` to the global namespace. There may be many such `b` methods on different, unrelated types. I think that the latter should be prefixed with the typename or module name. a.b(c) == AType.b(a, c) (or AType::b(a, c) , C++ style)

It's the other way around: in Julia b are functions which are globally visible by default and I just suggested to optionally hide them or find them via the object a.

Re: Pipelining might be my favorite programming language feature

#289

The author keeps calling it "pipelining", but I think the right term is "method chaining". Compare with a simple pipeline in bash: grep needle Each of those components executes in parallel, with the intermediate results streaming between them. You get a similar effect with coroutines. Compare Ruby: data = File.readlines("haystack.txt") .map(&:strip) .grep(/needle/) .map { |i| i.gsub('foo', 'bar') } .map { |i| File.re…

[deleted]

Re: Pipelining might be my favorite programming language feature

#290
post #24

I'm personally someone who advocates for languages to keep their feature set small and shoot to achieve a finished feature set quickly. However. I would be lying if I didn't secretly wish that all languages adopted the `|>` syntax from Elixir. ``` params |> Map.get("user") |> create_user() |> notify_admin() ```

Elixir itself adopted this operator from F#
Post reply on HN