Making sense out of ruby's dynamic method calls
Case 1:
def n
puts "inside n"
end
def m(&m2)
m2.call
end
m(&method(:n))
m() {puts "hello"}
>> inside n
>> hello
Case 2:
def m()
yield
end
m(&method(:n))
m() {puts "hello"}
>> inside n
>> hello
Case 3:
def m(&m2)
m2.call
yield
p m2.class
end
m(&method(:n))
m() {puts "hello"}
>> inside n
>> inside n
>> Proc
>> hello
>> hello
>> Proc
Case 4: (Adding checking before calling)
def m(&m2)
m2.call unless m2.nil?
end
def m
yield if block_given?
end
Case 5:
p = Proc.new(&method(:n))
p.call
m(&p)
>> inside n #p.call
>> inside n #m(&p)
Case 6:
p = Proc.new() {puts 'hello'}
p.call
m(&p)
>> hello #p.call
>> hello #m(&p)
Case 7:
p = method(:n).to_proc
m(&p)
>> inside n
Conclusions and Summary
- The decision of using yield or call in a method does not affect how the method is invoked. It can be given a block or a &Proc, or a &Method.
- If yield is used, then block_given? is used for checking.
- If call is used, then nil? is used for checking.
- For a method m, a parameter of the form &m2 can only appear at the end of the parameter list (therefore, at most once). This parameter corresponds to a block, or a &Proc, or a &Method.
- A method symbol (or a function pointer) can be created using "method(:)" (note the usage of ':' to obtain a symbol).
- A procedure can be created using "Proc.new(&x)" where x is a Method or a Proc. A procedure can also be created using Proc.new() {...} via a block.
def n
puts "inside n"
end
def m(&m2)
m2.call
end
m(&method(:n))
m() {puts "hello"}
>> inside n
>> hello
Case 2:
def m()
yield
end
m(&method(:n))
m() {puts "hello"}
>> inside n
>> hello
Case 3:
def m(&m2)
m2.call
yield
p m2.class
end
m(&method(:n))
m() {puts "hello"}
>> inside n
>> inside n
>> Proc
>> hello
>> hello
>> Proc
Case 4: (Adding checking before calling)
def m(&m2)
m2.call unless m2.nil?
end
def m
yield if block_given?
end
Case 5:
p = Proc.new(&method(:n))
p.call
m(&p)
>> inside n #p.call
>> inside n #m(&p)
Case 6:
p = Proc.new() {puts 'hello'}
p.call
m(&p)
>> hello #p.call
>> hello #m(&p)
Case 7:
p = method(:n).to_proc
m(&p)
>> inside n
Conclusions and Summary
- The decision of using yield or call in a method does not affect how the method is invoked. It can be given a block or a &Proc, or a &Method.
- If yield is used, then block_given? is used for checking.
- If call is used, then nil? is used for checking.
- For a method m, a parameter of the form &m2 can only appear at the end of the parameter list (therefore, at most once). This parameter corresponds to a block, or a &Proc, or a &Method.
- A method symbol (or a function pointer) can be created using "method(:
- A procedure can be created using "Proc.new(&x)" where x is a Method or a Proc. A procedure can also be created using Proc.new() {...} via a block.
Comments
Many thanks.