Created
May 15, 2015 11:24
-
-
Save koppen/bbe92e5a0b41ffa232e0 to your computer and use it in GitHub Desktop.
Find methods that return a value given a receiver and arguments
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
wanted = if ARGV.any? | |
[ | |
ARGV.map { |argument| eval(argument) } | |
] | |
else | |
# 1: The receiver | |
# 2: Expected result | |
# 3+: Arguments | |
[ | |
[1, 2, 1], | |
[2, 4, 2], | |
] | |
end | |
def find_methods(wanted) | |
def result(receiver, method_name, arguments) | |
if arguments.any? | |
receiver.send(method_name, *arguments) | |
else | |
receiver.send(method_name) | |
end | |
rescue ArgumentError => e | |
false | |
rescue LocalJumpError => e | |
false # This methods needs a block | |
rescue NameError, RuntimeError, TypeError => e | |
false # Shit happens | |
end | |
def match?(method_name, receiver, arguments, wanted_result) | |
begin | |
receiver = receiver.dup if receiver.respond_to?(:dup) | |
rescue TypeError | |
# Some objects, like Fixnum, respond_to :dup, but can't actually be duped | |
end | |
result(receiver, method_name, arguments) == wanted_result | |
end | |
def methods_matching_result(receiver, arguments, wanted_result) | |
methods_with_arity(receiver, arguments.size).select { |method_name| | |
match?(method_name, receiver, arguments, wanted_result) | |
} | |
end | |
def methods_with_arity(receiver, number_of_arguments) | |
receiver.methods.select do |method_name| | |
arity = receiver.method(method_name).arity | |
if arity == -1 | |
# This is a method written in C, taking a variable number of methods, | |
# and we can't know the exact number | |
else | |
arity == number_of_arguments || arity == -1 - number_of_arguments | |
end | |
end | |
end | |
wanted.map do |w| | |
w = w.dup | |
receiver = w.shift | |
wanted_result = w.shift | |
arguments = w | |
methods_matching_result(receiver, arguments, wanted_result).map { |method_name| | |
call = "#{receiver.inspect}.#{method_name}" | |
arglist = if arguments.any? | |
"(#{arguments.map(&:inspect).join(',')})" | |
else | |
"" | |
end | |
"#{call}#{arglist} #=> #{wanted_result.inspect}" | |
} | |
end | |
end | |
puts find_methods(wanted) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$ ./find_method.rb "foo" "FOO" | |
"foo".upcase #=> "FOO" | |
"foo".swapcase #=> "FOO" | |
"foo".upcase! #=> "FOO" | |
"foo".swapcase! #=> "FOO" | |
$ ./find_method.rb 1 2 | |
1.succ #=> 2 | |
1.next #=> 2 | |
$ ./find_method.rb 1 2 2 | |
1.*(2) #=> 2 | |
1.lcm(2) #=> 2 | |
$ ./find_method.rb \[1,2\] \[2,1\] | |
[1, 2].reverse #=> [2, 1] | |
[1, 2].reverse! #=> [2, 1] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment