Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Call ruby method or lambda like a proc. Calls a method with the maximum possible amount of arguments. Ruby's arity telling is too inaccurate so we just try to call the method with everything we have and if this raises an ArgumentError we examine the maximum allowed amount of arguments and pass those.
module Banana
# Provides low level support functionalities.
module Kernel
# Calls a method with the maximum possible amount of arguments.
#
# Ruby's arity telling is too inaccurate so we just try to call the method
# with everything we have and if this raises an ArgumentError we examine the
# maximum allowed amount of arguments and pass those.
#
# Dont believe me?
#
# ->(a, b = "") {}.arity
# => -2
# ->(a, *b) {}.arity
# => -2
#
# @param [Proc, Lambda, UnboundMethod] method The method object you want to call.
# This is typically an UnboundMethod but you can pass everything as long as it `respond_to?(:call)`
# @param args Arbitrary arguments which will passed to `method`
# @param [Proc] block Optional block which will be passed to `method`
def __call_method_like_proc method, *args, &block
sliced = false
method.call(*args, &block)
rescue ::ArgumentError => exception
# examine allowed amount of arguments
match = exception.message.match(/wrong number of arguments.+\(([0-9]+) for ([0-9]+)\)/)
if !sliced && match
if match[2] == "0"
args = []
elsif match[2].to_i != 0
args = args[0...match[2].to_i]
else
raise exception
end
sliced = true
retry
end
raise exception
end
module_function :__call_method_like_proc
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.