Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby: How to get the default value of optional proc arguments

Let's say I have a proc/lambda/block/method/etc like so:

2.1.2 :075 > procedure = Proc.new { |a, b=2, *c, &d| 42 }
 => #<Proc:0x000000031fcd10@(irb):75> 

I know I can find out the names of the parameters with:

2.1.2 :080 > procedure.parameters
 => [[:opt, :a], [:opt, :b], [:rest, :c], [:block, :d]]

But how do I go about getting the value that a given optional parameter would assume if it is not given?


PS: Yes. I know this has been asked/answered before here, but the previous solution requires the use of the merb gem, which is actually slightly misleading. merb itself depended on the methopara gem (unless you're on JRuby or MRI, which I am not) which itself provided the feature at the time the question was answered.

Sadly, presently, methopara appears to be abandonware. Also, it only ever supported ruby 1.9 (and not even the latest version thereof), so I'm looking for a solution that works for current ruby versions.

like image 228
mikev Avatar asked Dec 23 '14 09:12

mikev


People also ask

How do I set the default value of an argument in Ruby?

Default arguments are easy to add, you simply assign them a default value with = ("equals") in the argument list. There's no limit to the number of arguments that you can make default. Let's take a look at the different ways we can call this method: greeting # > Hello, Ruby programmer.

What is * args in Ruby?

In the code you posted, *args simply indicates that the method accepts a variable number of arguments in an array called args . It could have been called anything you want (following the Ruby naming rules, of course).

What is default Ruby?

The default values are used only when you don't pass any other arguments. This kind of parameters is useful when we have parameters that most of the time have same values. A sequence of arguments must correspond to a sequence of parameters.

How do you add an optional argument?

You can assign an optional argument using the assignment operator in a function definition or using the Python **kwargs statement. There are two types of arguments a Python function can accept: positional and optional. Optional arguments are values that do not need to be specified for a function to be called.


1 Answers

Assuming the proc / lambda was defined in a file, you can use the source_location method to find the location of that file and the line number it was defined on.

2.2.0 (main):0 > OH_MY_PROC.source_location
=> [
  [0] "sandbox/proc.rb",
  [1] 1
]

With some help from File.readlines we can make a short method that when passed a proc / lambda can spit out the source line it was defined on.

def view_def proc_lambda
  location = proc_lambda.source_location
  File.readlines(location[0])[location[1]-1]
end

In action it looks something like this

2.2.0 (main):0 > view_def OH_MY_PROC
=> "OH_MY_PROC = Proc.new { |a, b=2, *c, &d| 42 }\n"
2.2.0 (main):0 > view_def OH_MY_LAMBDA
=> "OH_MY_LAMBDA = ->(a, b=2, *c, &d) { 42 }\n"

If you want to do the same for methods it becomes a bit more involved. In that case I recommend reading this blog post from the Pragmatic Studio blog: "View Source" On Ruby Methods

like image 132
brownmike Avatar answered Oct 05 '22 23:10

brownmike