Ruby code

Can someone explain this part of the Ruby code:

def add_spec_path_to(args) # :nodoc: args << {} unless Hash === args.last args.last[:spec_path] ||= caller(0)[2] end 

I saw the << operator used for concatenation strings or as a bitwise operator in other languages, but can anyone explain this in this context. Does this somehow add an empty lamda to the args, or am I completely wrong?

I also see that it is used as follows:

 before_parts(*args) << block 

Is a Hash Keyword Keyword?

I'm also not sure what the ||= operator says.

I am equally in the dark regarding what caller(0)[2] .

+5
ruby
Mar 04 '09 at 7:50
source share
3 answers

|| = is a common Ruby idiom: it only assigns a value if it is not already set. The effect is the same as the type code

 if some_variable == nil some_variable = some_value end 

or

 some_variable= some_value unless some_variable 

=== when not redefined, two objects are compared for identification. In the case of Hash === args.last , Hash (which is an object of type Class) checks to see if it matches the class of the last element of the args array. The code uses the obvious fact that the implementation of the class # === forces us to check the class of the compared object.

This does not work the other way around, for example:

 a = [{}] Hash === a.last #=> true a.last === Hash #=> false 

Returned arguments to the method can be provided as hash contents without the need to provide {}

So you can do this:

 def hello(arg1, arg2, arg3) puts [arg1.class, arg2.class, arg3.class].join(',') end hello 1,2,3 #=> Fixnum,Fixnum,Fixnum hello :a, "b", :c => 1, :d => 99 #=> Symbol,String,Hash 

It is often used to provide optional variable-length parameters for a function.

Are you sure that you have exactly rewritten the source code, by the way? To get an array of arguments, you usually add * to the argument, as declared, otherwise the arguments must be entered as an array, which is more likely to defeat the object.

 def add_spec_path_to(*args) # now args is an array args << {} unless Hash === args.last # if trailing arguments cannot be # interpreted as a Hash, add an empty # Hash here so that following code will # not fail args.last[:spec_path] ||= caller(0)[2] # Set the spec_path option if it not # already set end 

EDIT: Extending further in the * args argument, try the following:

 def x(*args) puts args.join(',') puts args.map{|a| a.class }.join(',') end x 1,2,:a=>5,:b=>6 1,2,a5b6 Fixnum,Fixnum,Hash 

... using * args causes args to be presented to the method as an array. If I do not use * like this, for example:

 def y(args) puts args.join(',') puts args.map{|a| a.class }.join(',') end 

... then args must be an array before I call the method, or I get "ArgumentError: wrong number of arguments" for anything but one. Therefore, it should look like this:

 y [1,2,{:c=>3,:d=>4}] 

... with a Hash explicitly created using {}. And it is ugly.

All of the above were tested using MRI 1.8.6, btw.

+11
Mar 04 '09 at 9:30
source share

I assume args is an Array .

Hash is the name of the class - the first line pushes the empty hash {} on args if the last element of args already Hash (the === operator for class tests is an object of a particular class).

The ||= operator is similar to the += operator: it is more or less equivalent:

 args.last[:spec_path] = args.last[:spec_path] || caller(0)[2] 

So, it will install args.last[:spec_path] if and only if it is not currently installed.

The caller method returns information about the calling method.

+14
Mar 04 '09 at 7:57
source share

In short:

 def add_spec_path_to(args) # :nodoc: ... # Append an empty hash to args UNLESS the last arg is a hash.. in which case do nothing args << {} unless Hash === args.last # so we need a hash. If it is not there, make an empty one and put it there. ... #if args.last[:spec_path] equals nil or false, set it to caller(0)[2]... #so inside that hash from the first part, if :spec_path is not there, create it by using caller(0)[2]. args.last[:spec_path] ||= caller(0)[2] ... end 
+1
02 Sep 2018-11-11T00:
source share



All Articles