From: "joel@... (Joel Drapper)" Date: 2022-06-18T17:28:13+00:00 Subject: [ruby-core:109000] [Ruby master Feature#18644] Coerce anything callable to a Proc Issue #18644 has been updated by joel@drapper.me (Joel Drapper). I really like the first option but unfortunately it makes every object respond to `to_proc` even when they don't respond to `call`. Perhaps a third option is for the & operator to try to coerce using `to_proc` and failing that, try `method(:call).to_proc` if the object responds to `call`. Alternatively there might be a way to provide a default definition for `to_proc` on only objects that respond to `call`. Here's a hacky way to do that in Ruby. ```ruby class Object def method_missing(name, ...) if name == :to_proc && respond_to?(:call) if respond_to?(:define_method) define_method(name) { method(:call).to_proc } else define_singleton_method(name) { method(:call).to_proc } end method(:call).to_proc else super end end def respond_to_missing?(name, ...) name == :to_proc && respond_to?(:call, ...) || super end end ``` ---------------------------------------- Feature #18644: Coerce anything callable to a Proc https://bugs.ruby-lang.org/issues/18644#change-98112 * Author: waiting_for_dev (Marc Busqu��) * Status: Open * Priority: Normal ---------------------------------------- Functional objects are increasingly popular in Ruby. Having objects that respond to `#call` makes them interchangeable with a `Proc`. However, when you need to perform some Proc-specific operation, like currying, you have to break the abstraction and ask for the type of object. Example: ```ruby (callable.is_a?(Proc) ? callable : callable.method(:call)).curry[value] ``` Because of https://bugs.ruby-lang.org/issues/18620, it's not possible to make them polymorphic by taking the `:call` method: ```ruby callable.method(:call).curry[value] # won't work! ``` Consequently, I propose adding a built-in Ruby way to coerce anything callable to a proc (examples in Ruby): ### Option 1: `Object#to_proc` ```ruby class Object def to_proc return method(:call).to_proc if respond_to?(:call) raise "Needs to respond to :call" end end class Proc def to_proc self end end callable.to_proc.curry[value] ``` ### Option 2. `Kernel#Proc` ```ruby class Kernel def Proc(value) if value.is_a?(::Proc) value elsif value.respond_to?(:call) value.method(:call).to_proc else raise "Needs to implement :call" end end end Proc(callable).curry[value] ``` -- https://bugs.ruby-lang.org/ Unsubscribe: