From: "joel@... (Joel Drapper) via ruby-core" Date: 2023-02-10T14:08:05+00:00 Subject: [ruby-core:112333] [Ruby master Feature#19432] Introduce a wrapping operator (&) to Proc Issue #19432 has been reported by joel@drapper.me (Joel Drapper). ---------------------------------------- Feature #19432: Introduce a wrapping operator (&) to Proc https://bugs.ruby-lang.org/issues/19432 * Author: joel@drapper.me (Joel Drapper) * Status: Open * Priority: Normal ---------------------------------------- I don't know if this concept exists under another name, or whether there���s a technical term for it. I often find myself wanting to wrap a proc in another proc. Here's a snippet from a recent example where a visitor class renders a TipTap AST. Given a `text` node, we want to output the text by calling the `text` method with the value. But if the text has `marks`, we want to iterate through each mark, wrapping the output for each mark. It's possible to do this using the `>>=` operator if each proc explicitly returns another proc. ```ruby when "text" result = -> { -> { text node["text"] } } node["marks"]&.each do |mark| case mark["type"] when "bold" result >>= -> (r) { -> { strong { r.call } } } when "italic" result >>= -> (r) { -> { em { r.call } } } end end result.call.call end ``` This is quite difficult to follow and the `result.call.call` feels wrong. I think the concept of wrapping one proc in another proc would make for a great addition to `Proc` itself. I prototyped this using the `&` operator. ```ruby class Proc def &(other) -> { other.call(self) } end end ``` With this definition, we can call `&` on the original proc with our other proc to return a new proc that calls the other proc with the original proc as an argument. It also works with `&=`, so the above code can be refactored to this: ```ruby when "text" result = -> { text node["text"] } node["marks"]&.each do |mark| case mark["type"] when "bold" result &= -> (r) { strong { r.call } } when "italic" result &= -> (r) { em { r.call } } end end result.call end ``` -- https://bugs.ruby-lang.org/ ______________________________________________ ruby-core mailing list -- ruby-core@ml.ruby-lang.org To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-core.ml.ruby-lang.org/