Live data from Hacker News

Pipelining might be my favorite programming language feature

herecomesthemoon.net

271–280 of 360 posts

Re: Pipelining might be my favorite programming language feature

#271
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() ```

> I would be lying if I didn't secretly wish that all languages adopted the `|>` syntax from Elixir. This is usually the Thrush combinator[0], exists in other languages as well, and can be informally defined as: f(g(x)) = g(x) |> f 0 - https://leanpub.com/combinators/read#leanpub-auto-the-thrush

Not quite. Note that the Elixir pipe puts the left hand of the pipe as the first argument in the right-hand function. E.g.

    x |> f(y) = f(x, y)
As a result, the Elixir variant cannot be defined as a well-typed function, but must be a macro.

Re: Pipelining might be my favorite programming language feature

#272

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. 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 statemen…

In the Node and Python interpreters you'd use _, in browser JS consoles (and PHP shells like Psysh/Tinker) you'd use $_, in Picolisp @ (or @@ or @@@ for previous computations).

I think most interactive programming shells has an equivalent.

Re: Pipelining might be my favorite programming language feature

#273

Surprised that the term "tacit programming" wasn't mentioned once in the article. Point-free style and pipelining were meant for each other. https://en.m.wikipedia.org/wiki/Tacit_programming

Point free was technically mentioned once, but more as a "I'd rather not get into this in great detail right now." thing. It's really cool, though.

Re: Pipelining might be my favorite programming language feature

#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.

Re: Pipelining might be my favorite programming language feature

#275

Is pipelining the right term here? I've always used the term "transducer" to describe this kind of process, I picked it up from an episode of FunFunFunction if I'm not mistaken.

There's like 5 terms for this in different programming languages. I think 'pipelining' is the best universal word. 'Method chaining' just isn't correct, nor is 'builder pattern', and 'transducer' or 'thrush combinator' is obviously a nonstarter for most people.

Re: Pipelining might be my favorite programming language feature

#276

Earlier quoted context omitted.

If you add in a call to “.lazy“ it won’t create all the intermediate arrays. There since at least 2.7. https://ruby-doc.org/core-2.7.0/Enumerator/Lazy.html

Ultimately it will depend on the functions being chained. If they can work with one part of the result, or a subset of parts, then they might not block, otherwise they will still need to get a complete result and the lazy cannot help.

Not much different from having a `sort` in shell pipeline I guess?

Re: Pipelining might be my favorite programming language feature

#277
post #64
post #57

Earlier quoted context omitted.

I feel like a sufficiently good debugger should allow you to place a breakpoint at any of the lines here, and it should break exactly at that specific line. fn get_ids(data: Vec ) -> Vec { data.iter() .filter(|w| w.alive) .map(|w| w.id) .collect() } It sounds to me like you're asking for linebreaks. Chaining doesn't seem to be the issue here.

I'm only familiar with C++, Python, and SQL. Neither GDB nor PDB helps here, and I've never heard of a SQL debugger that will break apart expressions and let you view intermediate query results.

You can use EXPLAIN and similar keywords to see the execution plans in common SQL database engines. In practice you don't really care about the actual intermediate data so it doesn't show it, usually it's enough to learn whether indices are used at every step.

But you could in many cases easily infer from the execution plan what a query would look like and fetch an intermediate set separately.

Re: Pipelining might be my favorite programming language feature

#278
post #195

> (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?) Um, you can: #![feature(import_trait_associated_functions)] use Iterator::{collect, map, filter}; fn get_ids2(data: Vec ) -> Vec { collect(map(filter( ::iter(&data), |v| ...), |v| ...)) } and you can because it's lazy, which is also the same r…

Guilty as charged, I did not know about the `import_trait_associated_functions` feature at the time. I might add a note to the article to clarify this.

Re: Pipelining might be my favorite programming language feature

#279

Earlier quoted context omitted.

Pipelining is just syntactic sugar for nested function calls. If you need to handle an unhappy path in a way that isn’t optimal for nested function calls then you shouldn’t be nesting your function calls. Pipelining doesn’t magically make things easier nor harder in that regard. But if a particular sequence of function calls do suit nesting, then pipelining makes the code much more readable because you’re not mixing…

I think they are talking about nested loops, not nested function calls.

Nested loops isn’t pipelining. Some of the examples make heavy use of lambda so they do have nested loops happening as well but in those examples the pipelining logic is still the nesting of the lambda functions.

Crudely put, in C-like languages, pipelining is just as way of turning

  fn(fn(fn()))
Where the first function call is in the inner, right-most, parentheses,

into this:

  fn | fn | fn
…which can be easily read sequentially from left-to-right.
Post reply on HN