Skip to content

Instantly share code, notes, and snippets.

@2called-chaos
Created March 10, 2014 14:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 2called-chaos/9466566 to your computer and use it in GitHub Desktop.
Save 2called-chaos/9466566 to your computer and use it in GitHub Desktop.
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