0

I have three functions A, B, and C. I need to pass A and B to C. How can I do this?

def A a
end

def B b
end

def C( &f1, &f2 ) #  syntax error, unexpected ',', expecting ')'
  f1.call 123
  f2.call 234
end

def C( f1, f2 ) # this one ok
  f1.call 123
  f2.call 234
end

C( &A, &B) # syntax error, unexpected ',', expecting ')'
sawa
  • 165,429
  • 45
  • 277
  • 381
Kokizzu
  • 24,974
  • 37
  • 137
  • 233
  • 2
    possible duplicate of [Passing a method as a parameter in Ruby](http://stackoverflow.com/questions/522720/passing-a-method-as-a-parameter-in-ruby) – SBI Jun 29 '15 at 13:15
  • 1
    no it isn't, but it has a good hint.. – Kokizzu Jun 29 '15 at 13:16
  • 1
    you could use [`Object#public_send`](http://ruby-doc.org/core-1.9.3/Object.html#method-i-public_send) e.g. `def c(f1,f2); public_send(f1,123);public_send(f2,234);end;` and all with `c(:a, :b)` but what is the reasoning for the need of this functionality are you sure there is no better solution? Also only constants are capitalized in ruby; method definitions should be lower snake_cased. – engineersmnky Jun 29 '15 at 13:33
  • @engineersmnky That's good enough to be an answer. Exactly what I would recommend, especially the naming part. – tadman Jun 29 '15 at 14:53

2 Answers2

2

I would recommend using Object#public_send to perform this operation although I think there are probably better ways to handle your situation if you were to define it more clearly.

Also in only constants should be capitalized methods should be defined in lower snake case.

Example:

#puts used for clarification purposes
class SomeClass
  def a(val)
    puts "method a called with #{val}"
  end
  def b(val)
    puts "method b called with #{val}"
  end
  def c (f1,f2)
   public_send(f1,123)
   public_send(f2,234)
  end
end

Usage

s = SomeClass.new
s.c(:a,:b)
#method a called with 123
#method b called with 234
#=> nil

Hope this helps you like I said if you define the use case more clearly there may be and most likely are better ways to handle the problem.

Note: the above code will not work in the context of main:Object directly when typed into irb. Instead it will inform you that a private method was called for main:Object. This is because when defining a method in irb it is privatized in the context of main.

Also note you could use Object#send but this will give access to private as well as public methods (which might be a security concern dependent upon usage)

Another option would be to define a and b as lambdas or Procs e.g.

a= ->(val) {puts "method a called with #{val}"}
b= ->(val) {puts "method b called with #{val}"}
def c(f1,f2)
  f1.call(123)
  f2.call(234)
end
c(a,b)
#method a called with 123
#method b called with 234
#=> nil   
engineersmnky
  • 25,495
  • 2
  • 36
  • 52
0

there's a method method to convert function to method, so we can do this:

def A a
end

def B b
end

def C( f1, f2 ) # this one ok
  f1.call 123
  f2.call 234
end

C( method(:A), method(:B))
Kokizzu
  • 24,974
  • 37
  • 137
  • 233
  • 3
    "convert function to method" does not make sense. The former is an informal/wrong way to call the latter in a context of Ruby. – sawa Jun 29 '15 at 13:29