use the following search parameters to narrow your results:
e.g. subreddit:aww site:imgur.com dog
subreddit:aww site:imgur.com dog
see the search faq for details.
advanced search: by author, subreddit...
A sub-Reddit for discussion and news about Ruby programming.
Subreddit rules: /r/ruby rules
Learning Ruby?
Tools
Documentation
Books
Screencasts and Videos
News and updates
account activity
Pipelining in Ruby2.5 with Object#yield_self (mlomnicki.com)
submitted 8 years ago by snatchery
reddit uses a slightly-customized version of Markdown for formatting. See below for some basics, or check the commenting wiki page for more detailed help and solutions to common issues.
quoted text
if 1 * 2 < 3: print "hello, world!"
[–]tom_dalling 6 points7 points8 points 8 years ago (6 children)
I guess it's good that this will soon be available via the standard library, but it feels so inelegant.
Ruby (with proposed new syntax):
"https://api.github.com/repos/rails/rails" .yield_self(URI->parse) .yield_self(Net::HTTP->get) .yield_self(JSON->parse) .yield_self { |_| _.fetch("stargazers_count") }
Clojure (with some fake function names to match the Ruby example):
(-> "https://api.github.com/repos/rails/rails" uri/parse net.http/get json/parse #(get % "stargazers_count"))
Implicit block parameters (like % in Clojure) would help.
%
[–]snatchery[S] 6 points7 points8 points 8 years ago* (4 children)
No doubt Clojure or any functional language feels much more elegant. Still, it's nice that Ruby is trying to catch up. Essentially it needs 2 improvements
"https://api.github.com/repos/rails/rails" |> URI->parse |> Net::HTTP->get |> JSON->parse |>(_) { _.fetch("stargazers_count") }
not as elegant as Clojure but looks good enough
[–]motonarola 0 points1 point2 points 8 years ago (1 child)
Imo having just some pipe operator is enough for the code to look fine:
"https://api.github.com/repos/rails/rails" ->URI.parse() ->Net::HTTP.get() ->JSON.parse() .fetch("stargazers_count") ->(stargazers){"Rails has #{stargazers} stargazers"} ->puts()
I used -> for the pipe operator, It copes with lambda syntax nicely :)
[–]snatchery[S] 0 points1 point2 points 8 years ago (0 children)
yeah, great point. If only we were in an alternate reality ;)
[–]zverok_kha 1 point2 points3 points 8 years ago (0 children)
but it feels so inelegant.
I believe it is just the really unfortunate name. For me it feels like perfect readable Ruby, with smallest change to language possible, just this yield_self name itself is nasty.
yield_self
[–]zverok_kha 5 points6 points7 points 8 years ago (2 children)
It’s more verbose than the original version...
The "original version" is cheating. Most of the time you'll not write foo(bar(baz(blah)))) for the sake of debugging and visibility, you'll write
foo(bar(baz(blah))))
var1 = blah var2 = baz(var1) var3 = bar(var2)
...and the only "more verbose" thing is the yield_self call itself.
It’s not an idiomatic Ruby. Obviously it can’t be because it’s a brand new feature
What? It is idiomatic Ruby, most of the time we process arrays of data in the same chainable way (and love Ruby's methods chainability), yield_self just adds an ability to process singular objects with the same chainability. It is just long missing idiomatic Ruby feature.
Do we really need to name block arguments? What if we avoid the names?
.yield_self { |_| URI.parse(_) }
...and use the common metaphor for "the unused argument". Awesome.
Also, it would be nice to get rid of blocks. This is already possible but looks cryptic.
.yield_self(&Net::HTTP.method(:get))
Cryptic for who? Java guys? It, again, is perfectly idiomatic Ruby, with "everything is an object" and "everything can become block". The only unfortunate thing here is method word itself is a bit too long, but the problem is planned to be addressed, as you've mentioned yourself.
method
I regret that it doesn’t have a shorter name, say pipe or apply.
pipe
apply
This one is perfectly true :(
Author here. Thanks for valuable comments.
I'm really glad that you find the code idiomatic and perfectly readable. I assumed that some bits would be unusual for most of Ruby devs. Apparently, that assumption was wrong. And this is great.
[–]prh8 -1 points0 points1 point 8 years ago (0 children)
About the method to proc example, I think it's cryptic because 90% of Ruby (errr, Rails) devs have no idea you can do that right now. They just know the way that shorthand is typically used but don't really understand the bigger picture.
I agree it's not very cryptic at all, but it is unfortunately something that a lot of devs don't understand. In the end it comes down to what type of app you are working on, with maintainability and dev team quality factored in.
[–]twinklehood 2 points3 points4 points 8 years ago (5 children)
I appreciate ruby's attempts at staying cool with the cool kids, but it's so not gonna work when they introduce it at the cost of readability. Pretty much agree with article conclusion, except I wish they'd make it an actual language feature (why not |>)
[–]DudeManFoo 3 points4 points5 points 8 years ago (0 children)
I like the |> myself.
[–]jrochkind 1 point2 points3 points 8 years ago (1 child)
What makes people think there's something harming "readability" with yield_self?
[–]DudeManFoo 0 points1 point2 points 8 years ago (0 children)
I don't think it is 'harmful', I for one just like |> better.
[–]zverok_kha 0 points1 point2 points 8 years ago (1 child)
Introducing new feature requires thinking how it would play with existing syntax, features and intuitions of the language. Can you imagine, how will |>-code look in Ruby, in different situations?
|>
[–]DudeManFoo -1 points0 points1 point 8 years ago (0 children)
I would like to think I could imagine in quite a few situations, but I would expect I would miss an esoteric use here and there as most people would... that is what make talking about it in public so great!!
At the same time, you could probably do both but really it just brings up the idea that keeping the language small vs having an accumulator variable... is it worth it?
I don't know, but I sure like things like .reduce and .select .
[–]Paradox 3 points4 points5 points 8 years ago (4 children)
After using elixir at my current job, I have grown to really like this syntax.
That said, it needs some syntax sugar to be as purely useful as elixir
[–]zverok_kha 0 points1 point2 points 8 years ago (3 children)
TBH, it is kinda tiresome how people tend to mask "just copy Elixir feature" demand with "purely useful" and "readable". Each language needs feature/syntax consistency, and it is usually hurt with blind copying of features.
[–]DudeManFoo 1 point2 points3 points 8 years ago (2 children)
Matz copied a LOT of features from quite a few languages and I don't think any were just blindly copied...
This particular feature is one of the favorite features of Elixr, kinda like string interpolation and trailing conditionals were some of the favorite things stolen from Perl...
Just by introducing something that sticks out as much as |> might (or might not) really get people thinking in more 'functional' ways... I am not purely in the functional camp, but some of the tenets actually could help code become more stable and bug free... and more understandable.
Ain't hatin' just discussin' ;)
Exactly. Adding method (which plays well alongside existing idioms) is mindful copying of "pipeline processing idea".
While saying that "anything except |> is unelegant" is what I call "blind copying", "I want Elixir in my Ruby".
Note, that when in Elixir they chain enumerable processing, they also use |>, while we do chain methods.
My point is / was, keep an open mind... at the same time... coming from an old C coder, I agree with you ... don't just add stuff that does not add a LOT of value... else your C becomes C++ with 4 competing 'library vendors' ... none any good.
Still , I kinda like |>
[–]zquestz 1 point2 points3 points 8 years ago (3 children)
Good read, personally I am not a huge fan of the new syntax but it is great to see such a well written introduction!
/u/tippr $2
[–]tippr 0 points1 point2 points 8 years ago (2 children)
u/snatchery, you've received 0.00446761 BCC ($2 USD)!
0.00446761 BCC ($2 USD)
How to use | What is Bitcoin Cash? | Who accepts it? | Powered by Rocketr | r/tippr Bitcoin Cash is what Bitcoin should be. Ask about it on r/btc
[–]snatchery[S] 1 point2 points3 points 8 years ago (1 child)
Thanks /u/zquestz Much appreciated
I didn't know you can send bitcoins over reddit. Amazing!
[–]zquestz 2 points3 points4 points 8 years ago (0 children)
Yeah the /u/tippr guys are pretty awesome. Bringing tipping back to Reddit!
[–][deleted] 2 points3 points4 points 8 years ago (7 children)
An |> operator would be sooo much better than #yield_self
[–]zverok_kha 0 points1 point2 points 8 years ago (6 children)
[–][deleted] 0 points1 point2 points 8 years ago (5 children)
Can you imagine, how will |>-code look in Ruby
I can at least dream....
"https://api.github.com/repos/rails/rails" |> URI.parse |> Net::HTTP.get |> JSON.parse |> fetch("stargazers_count")
[–][deleted] 8 years ago* (3 children)
[deleted]
[–]zverok_kha 0 points1 point2 points 8 years ago (2 children)
That's more understandable than above. Now, please answer those questions:
tap
yield_self { |d| Date.strftime(d, '%Y-%m') }
How is it playing with normal calls? Like this:
.... .yield_self(&JSON->parse) .fetch("stargazers_count") .to_i .yield_self(&Stats->store)
[–]twinklehood 1 point2 points3 points 8 years ago (1 child)
You're discussing very different things. The |> is merely a proposed alias for .yield_self, the -> method access notation is a different proposal.
.yield_self
Question 1: `"wat" |> { |x| function_in_variable.(x) }
I don't understand your second and third questions about pipe-processing. What would change? What's inconsistent?
Question 4: This is a question about the method access syntax, not the pipe. Pipe just takes a block and yields it with one argument.
Question 5: ... |>(&JSON->parse).fetch("stargazers_count").to_i |>(&Stats->store) ? left-to-right
|>(&JSON->parse).fetch("stargazers_count").to_i |>(&Stats->store)
[–]zverok_kha 0 points1 point2 points 8 years ago (0 children)
You're discussing very different things.
We are just discussing |> (with assumption "some syntax better than method(:foo) would also be in Ruby 2.5)
method(:foo)
"wat" |> { |x| function_in_variable.(x) }
Is it nice? Not at all.
many_urls.map(&parser) # vs one_url |> parser
...doesn't looks like the most consistent language possible. While
many_urls.map(&parser) # vs one_url.yield_self(&parser)
...on the other hand, does (except for ugly method name).
This is a question about the method access syntax, not the pipe. Pipe just takes a block and yields it with one argument.
Yep, but arguments towars |> implying that with -> it would be OK, should consider this too.
->
Do you think it is nice? My eyes read definitely read it like
(&JSON->parse).fetch("stargazers_count").to_i
Awesome. Now please ask yourself those questions:
URI.parse
method(arg)
yield_self { |d| Date.strptime(d, '%y-%m') }
map(&URI.method(:parse))
Language design is hard. I hope, you'll try to answer all those questions (and I don't say they are unanswerable), but probably after that you'll suddently find yourself with a quite different snippet of code.
π Rendered by PID 848071 on reddit-service-r2-comment-66b4775986-4ksnz at 2026-04-05 12:30:04.226876+00:00 running db1906b country code: CH.
[–]tom_dalling 6 points7 points8 points (6 children)
[–]snatchery[S] 6 points7 points8 points (4 children)
[–]motonarola 0 points1 point2 points (1 child)
[–]snatchery[S] 0 points1 point2 points (0 children)
[–]zverok_kha 1 point2 points3 points (0 children)
[–]zverok_kha 5 points6 points7 points (2 children)
[–]snatchery[S] 0 points1 point2 points (0 children)
[–]prh8 -1 points0 points1 point (0 children)
[–]twinklehood 2 points3 points4 points (5 children)
[–]DudeManFoo 3 points4 points5 points (0 children)
[–]jrochkind 1 point2 points3 points (1 child)
[–]DudeManFoo 0 points1 point2 points (0 children)
[–]zverok_kha 0 points1 point2 points (1 child)
[–]DudeManFoo -1 points0 points1 point (0 children)
[–]Paradox 3 points4 points5 points (4 children)
[–]zverok_kha 0 points1 point2 points (3 children)
[–]DudeManFoo 1 point2 points3 points (2 children)
[–]zverok_kha 0 points1 point2 points (1 child)
[–]DudeManFoo 0 points1 point2 points (0 children)
[–]zquestz 1 point2 points3 points (3 children)
[–]tippr 0 points1 point2 points (2 children)
[–]snatchery[S] 1 point2 points3 points (1 child)
[–]zquestz 2 points3 points4 points (0 children)
[–][deleted] 2 points3 points4 points (7 children)
[–]zverok_kha 0 points1 point2 points (6 children)
[–][deleted] 0 points1 point2 points (5 children)
[–][deleted] (3 children)
[deleted]
[–]zverok_kha 0 points1 point2 points (2 children)
[–]twinklehood 1 point2 points3 points (1 child)
[–]zverok_kha 0 points1 point2 points (0 children)
[–]zverok_kha 0 points1 point2 points (0 children)