Skip to content

Preview Ruby 4.1 is a preview. It can change before the final release. Switch to Ruby 4.0 →

instance method · added in Ruby 4.1

Proc#refined

prc.refined(*modules) → a_proc

Returns a new Proc that behaves like the receiver but with the refinements activated by the given modules in effect inside its body. The receiver is left unchanged.

Example
module StringRefinement
  refine String do
    def shout = upcase + "!"
  end
end

original = ->(s) { s.shout }
refined_proc = original.refined(StringRefinement)
refined_proc.call("hi")  #=> "HI!"
original.call("hi")      #=> NoMethodError

If no modules are given, returns the receiver. Otherwise, only Procs created from a Ruby block are supported; calling this on a Proc backed by a C function, a Symbol, or a method raises ArgumentError.

When calls of this method are chained, all the given modules are activated in the order they are given, so refinements activated by a later call take precedence.

The refinement set of the returned Proc is fixed when it is created: calling using inside its body raises RuntimeError.

The refinements are in effect throughout the body, including nested blocks and methods defined with def inside it. As with a def inside a using scope, such a method keeps the refinements even when it is called later:

Example
refined_proc = ->(s) {
  -> { s.shout }.call          # nested block: "HI!"
}.refined(StringRefinement)

refined_proc = -> {
  obj = Object.new
  def obj.shout_hi = "hi".shout  # the method sees the refinement
  obj.shout_hi                   #=> "HI!"
}.refined(StringRefinement)

Running the returned Proc requires a copy of the instruction sequence of the block and of all of its nested blocks, so that the copy can resolve methods through the refinements without affecting the original Proc. The copy is made when the Proc is first called, and is cached and reused for the same block and the same modules, whether they were given in one call or in a chain of calls; a Proc that is never called is never copied. Applying refinements therefore increases memory use roughly in proportion to the size of the block, once the Proc runs.

Ruby version changes

  1. 4.1
    • Proc#refined is added. It returns a new Proc that behaves like the receiver but with the refinements activated by the given modules in effect inside its body, without affecting the original Proc. [Feature #22097]