Feature #22474
closedKernel#using (or BasicObject#using)
Description
Currently there is Module#using. The scope where using is effective is the lexical scope of the module eval block (blocks for module keyword, Module::new, module_eval, and module_exec). However, since any block is a lexical scope, why not allow using in any block? Example:
module R
refine(Enumerable) { def f = 1 }
end
proc { using R; [].f }.() # => 1
[].f # => ! NoMethodError
Note that we can already achieve a similar effect in pure Ruby: it is possible to define a function while_using.
module Kernel
private def while_using mod, binding, code
old = Thread.current[:using_mod]
Thread.current[:using_mod] = mod
args = binding.local_variables.map { binding.local_variable_get _1 }
result = TOPLEVEL_BINDING.eval(<<~RUBY).bind_call binding.receiver, *args
Module.new do
using Thread.current[:using_mod]
def run #{binding.local_variables.join ', '}
#{code}
end
end.instance_method :run
RUBY
Thread.current[:using_mod] = old
result
end
end
module R
refine(Enumerable) { def f = 1 }
end
class C
def g x
@y = 1
while_using R, binding, 'x + @y + [].f'
end
end
C.new.g 1 # => 3
Updated by alanwu (Alan Wu) about 14 hours ago
- Is duplicate of Feature #22097: Add Proc#with_refinements added
Updated by alanwu (Alan Wu) about 14 hours ago
ยท Edited
- Status changed from Open to Feedback
However, since any block is a lexical scope, why not allow using in any block?
Seems to be already addressed by #22097.
Updated by UlyssesZhan (Ulysses Zhan) about 13 hours ago
alanwu (Alan Wu) wrote in #note-2:
Seems to be already addressed by #22097.
I see. My quick issue search did not dig it up. I would say using R; something is much easier than -> { something }.refined(R).(), and we can have both features. However Proc#refined should be good enough for the former use case.