Live data from Hacker News

Pipelining might be my favorite programming language feature

herecomesthemoon.net

211–220 of 360 posts

Re: Pipelining might be my favorite programming language feature

#211
post #85
post #42

I always wondered how programming would be if we hadn't designed the assignment operator to be consistent with mathematics, and instead had it go LHS -> RHS, i.e. you perform the operation and then decide its destination, much like Unix pipes.

TI-BASIC is like this with its store operator →. I always liked it. 10→A A+10→C

It also has an = operator, which saves the whole expression. It re-evaluates it then every time it was used.

Re: Pipelining might be my favorite programming language feature

#212
Hack (Facebook's PHP fork) has this feature. It's called pipes [1]:

    $x = vec[2,1,3]
      |> Vec\map($$, $a ==> $a * $a) // $$ with value vec[2,1,3]
      |> Vec\sort($$); // $$ with value vec[4,1,9]
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're never sure which one was null.

[1]: https://docs.hhvm.com/hack/expressions-and-operators/pipe

Re: Pipelining might be my favorite programming language feature

#213
post #85

Earlier quoted context omitted.

TI-BASIC is like this with its store operator →. I always liked it. 10→A A+10→C

It also has an = operator, which saves the whole expression. It re-evaluates it then every time it was used.

Yep, CAS right in the BASIC on the 89 and up is a truly magical experience

Re: Pipelining might be my favorite programming language feature

#214
post #212

Hack (Facebook's PHP fork) has this feature. It's called pipes [1]: $x = vec[2,1,3] |> Vec\map($$, $a ==> $a * $a) // $$ with value vec[2,1,3] |> Vec\sort($$); // $$ with value vec[4,1,9] 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 be…

Wait. Isn't that already solved in Java? Optional, Mono, Flux, etc.

I remember being able to deal with object streams with it quite comfortably.

Re: Pipelining might be my favorite programming language feature

#215
post #212

Hack (Facebook's PHP fork) has this feature. It's called pipes [1]: $x = vec[2,1,3] |> Vec\map($$, $a ==> $a * $a) // $$ with value vec[2,1,3] |> Vec\sort($$); // $$ with value vec[4,1,9] 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 be…

Wait. Isn't that already solved in Java? Optional, Mono, Flux, etc. I remember being able to deal with object streams with it quite comfortably.

Any function that can return an object in Java can return a null. Nullability not being part of the type system I think is a design fail.

Re: Pipelining might be my favorite programming language feature

#216
post #170
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 wish there were a variation that can destructure more ergonomically. Instead of: ``` fetch_data() |> (fn {:ok, val, _meta} -> val :error -> "default value" end).() |> String.upcase() ``` Something like this: ``` fetch_data() |>? {:ok, val, _meta} -> val |>? :error -> "default value" |> String.upcase() ```

  fetch_data()
  |> case do
      {:ok, val, _meta} -> val
      :error -> "default value"
  end
You have the extra "case do...end" block but it's pretty close?

This is for sequential conditions. If you have nested conditions, check out a where block instead. https://dev.to/martinthenth/using-elixirs-with-statement-5e3...

Re: Pipelining might be my favorite programming language feature

#217
post #215

Earlier quoted context omitted.

Wait. Isn't that already solved in Java? Optional, Mono, Flux, etc. I remember being able to deal with object streams with it quite comfortably.

Any function that can return an object in Java can return a null. Nullability not being part of the type system I think is a design fail.

Yeah, so the null checks become annoying if you use only language fundamentals.

Java has a culture of having a layer above fundamentals.

We're past all that already. I am discussing the ergonomics of their null checking APIs, particularly in the context of pipelining (or streaming, in the Java world).

I find them quite comfortable.

Re: Pipelining might be my favorite programming language feature

#218

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…

Syntactic sugar can sometimes fool us into thinking the underlying process is more efficient or streamlined. As a new programmer, I probably would have assumed that "storing" `data` at each step would be more expensive.

It absolutely becomes very inefficient, though the threshold data set size varies according to context. Most languages don't have lightweight coroutines as an alternative (but see Lua!), so the convenient alternatives have larger fixed cost. Plus cache locality means cache utilization might be helpful, or even better, as opposed to switching back-and-for every data element, though coroutine-based approaches can also use buffering strategies, which not coincidentally is how pipes work.

But, yes, naive call chaining like that is sometimes a significant performance problem in the real world. For example, in the land of JavaScript. One of the more egregious examples I've personally seen was a Bash script that used Bash arrays rather than pipelines, though in that case it had to do with the loss of concurrency, not data churn.

Re: Pipelining might be my favorite programming language feature

#219

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…

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

Re: Pipelining might be my favorite programming language feature

#220
post #31

Am I the only one who thinks yuck? Instead of writing: a().b().c().d(), it's much nicer to write: d(c(b(a()))), or perhaps (d ∘ c ∘ b ∘ a)().

Add a couple more arguments to each function and you'll get that first variant is a lot nicer:

    a(axe).b(baz, bog).c(cid).d(dot)
vs

    d(c(b(a(axe), baz, bog), cid), dot)
Post reply on HN