Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
205 views
in Technique[技术] by (71.8m points)

ruby - How to get argument names using reflection

I would like to do some fairly heavy-duty reflection in Ruby. I want to create a function that returns the names of the arguments of various calling functions higher up the call stack (just one higher would be enough but why stop there?). I could use Kernel.caller, go to the file and parse the argument list but that would be ugly and unreliable.

The function that I would like would work in the following way:

module A
  def method1( tuti, fruity) 
    foo
  end
  def method2(bim, bam, boom)  
    foo
  end
  def foo
    print caller_args[1].join(",") #the "1" mean one step up the call stack
  end

end

A.method1
 #prints "tuti,fruity"
A.method2
 #prints "bim, bam, boom"

I would not mind using ParseTree or some similar tool for this task but looking at Parsetree, it is not obvious how to use it for this purpose. Creating a C extension like this is another possibility but it would be nice if someone had already done it for me.

I can see that I'll probably need some kind of C extension. I suppose that means my question is what combination of C extension would work most easily. I don't think caller+ParseTree would be enough by themselves.

As far as why I would like to do this goes, rather than saying "automatic debugging", perhaps I should say that I would like to use this functionality to do automatic checking of the calling and return conditions of functions:

def add x, y 
  check_positive
  return x + y
end

Where check_positive would throw an exception if x and y weren't positive. Obviously, there would be more to it than that but hopefully this gives enough motivation.

Question&Answers:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

In Ruby 1.9.2, you can trivially get the parameter list of any Proc (and thus of course also of any Method or UnboundMethod) with Proc#parameters:

A.instance_method(:method1).parameters # => [[:req, :tuti], [:req, :fruity]]

The format is an array of pairs of symbols: type (required, optional, rest, block) and name.

For the format you want, try

A.instance_method(:method1).parameters.map(&:last).map(&:to_s)
  # => ['tuti', 'fruity']

Of course, that still doesn't give you access to the caller, though.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...