[ruby-core:112741] [Ruby master Feature#19484] Calling `binding` on a C-level proc raises an `ArgumentError`

Issue #19484 has been reported by joel@drapper.me (Joel Drapper). ---------------------------------------- Feature #19484: Calling `binding` on a C-level proc raises an `ArgumentError` https://bugs.ruby-lang.org/issues/19484 * Author: joel@drapper.me (Joel Drapper) * Status: Open * Priority: Normal ---------------------------------------- Calling `binding` on a C-level proc (from `&:symbol`) raises an `ArgumentError`, "Can't create Binding from C level Proc" but there is no way to tell if a given proc is a C-level proc before calling `binding` on it. It’s possible to rescue this error, but rescuing an exception is slow. Given that a C-level proc doesn't have a binding, would it make more sense to respond to `binding` with `nil` rather than raise an error? That would allow us to, for example, look up the receiver and fall back to self, e.g. `block.binding&.receiver || self`. Alternatively, it would be useful to be able to check whether a given proc is a C-Level proc using something like this. ```ruby case block when CProc block.call(self) else block.call end ``` An example use case is an interface that takes a hash of conditions and tokens. If the condition is valid, we do something with the token. Otherwise, we ignore it. ```ruby some_interface(-> { true } => "foo", -> { false } => "bar" ) ``` With literal Procs, it makes sense to call them and check their truthiness. ```ruby def some_interface(**conditional_tokens) conditional_tokens.each do |condition, token| do_something_with(token) if condition.call end end ``` When given C-Level procs, it makes sense to call them with `self` to evaluate the corresponding method. ```ruby some_interface(&:foo? => "foo", &:bar? => "bar" ) ``` ```ruby def foo? = true def bar? = false def some_interface(**conditional_tokens) conditional_tokens.each do |condition, token| case condition when CProc do_something_with(token) if condition.call(self) else do_something_with(token) if condition.call end end end ``` -- https://bugs.ruby-lang.org/

Issue #19484 has been updated by Eregon (Benoit Daloze). `block.binding` is not meant to be fast anyway. So is there a real performance problem caused by that? `nil` would cause the error to happen later and probably be less clear for the user. Note that "C-level proc" is not a good classification, similar restrictions apply to methods defined in any language but Ruby (e.g. Java for TruffleRuby). ---------------------------------------- Feature #19484: Calling `binding` on a C-level proc raises an `ArgumentError` https://bugs.ruby-lang.org/issues/19484#change-102237 * Author: joel@drapper.me (Joel Drapper) * Status: Open * Priority: Normal ---------------------------------------- Calling `binding` on a C-level proc (from `&:symbol`) raises an `ArgumentError`, "Can't create Binding from C level Proc" but there is no way to tell if a given proc is a C-level proc before calling `binding` on it. It’s possible to rescue this error, but rescuing an exception is slow. Given that a C-level proc doesn't have a binding, would it make more sense to respond to `binding` with `nil` rather than raise an error? That would allow us to, for example, look up the receiver and fall back to self, e.g. `block.binding&.receiver || self`. Alternatively, it would be useful to be able to check whether a given proc is a C-Level proc using something like this. ```ruby case block when CProc block.call(self) else block.call end ``` -- https://bugs.ruby-lang.org/
participants (2)
-
Eregon (Benoit Daloze)
-
joel@drapper.me (Joel Drapper)