Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I write a ruby method to accept and save a lambda, block, or Proc?

Tags:

ruby

In ruby, I want to create a method on a class which will save a callable object of any sort into an instance variable. This includes lambdas, blocks, and Procs. For example:

obj.save_callable(lambda { |x| x * 2 })
assert_equal(10, obj.invoke_callable(5))

obj.save_callable { |x| x * 3 }
assert_equal(15, obj.invoke_callable(5)) 

obj.save_callable(Proc.new { |x| x * 4 })
assert_equal(20, obj.invoke_callable(5)) 

I know this can be a hairy area. One approach that I've already seen is to create different methods, one for each type:

class MyClass
  # pass proc or lambda
  def save_callable(p)
    @callable = p
  end

  # pass a block
  def save_callable_block(&b)
    @callable = b
  end

  def invoke_callable(*args)
    @callable && @callable.call(*args)
  end
end

Question: Is there some way to boil this down further to just a single save_callable method?

like image 771
ms-ati Avatar asked Mar 10 '26 01:03

ms-ati


1 Answers

Alright... after writing this question, on a lark, I tried the following. This actually appears to work in both ruby 1.8.7 and 1.9.2:

class UnifiedSaveCallable
  def save_callable(p=nil, &b)
    @callable = p || b
  end
  def invoke_callable(*args)
    @callable && @callable.call(*args)
  end
end

obj = UnifiedSaveCallable.new

obj.save_callable(lambda { |x| x * 2 })
assert_equal(10, obj.invoke_callable(5))

obj.save_callable { |x| x * 3 }
assert_equal(15, obj.invoke_callable(5)) 

obj.save_callable(Proc.new { |x| x * 4 })
assert_equal(20, obj.invoke_callable(5)) 

This idiom seems to work for me. Still interested in hearing if there's a better or more idiomatic way to do this in ruby.

like image 155
ms-ati Avatar answered Mar 11 '26 15:03

ms-ati



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!