I would like to replace the method implementation for the object with the block that the user points to. In JavaScript, this is easy to accomplish:
function Foo() { this.bar = function(x) { console.log(x) } } foo = new Foo() foo.bar("baz") foo.bar = function(x) { console.error(x) } foo.bar("baz")
In C # it is also quite easy
class Foo { public Action<string> Bar { get; set; } public Foo() { Bar = x => Console.WriteLine(x); } } var foo = Foo.new(); foo.Bar("baz"); foo.Bar = x => Console.Error.WriteLine(x); foo.Bar("baz");
But how can I do the same in Ruby? I have a solution that stores lambda in an instance variable, and the method calls lambda, but I don't really like the utility and syntax
class Foo def initialize @bar = lambda {|x| puts x} end def bar x @bar.call x end def bar= blk @bar = blk end end foo = Foo.new foo.bar "baz" foo.bar= lambda {|x| puts "*" + x.to_s} foo.bar "baz"
I would like to have this syntax:
foo.bar do |x| puts "*" + x.to_s end foo.bar "baz"
I came up with the following code
class Foo def bar x = nil, &blk if (block_given?) @bar = blk elsif (@bar.nil?) puts x else @bar.call x end end end
But this is disgusting for several parameters and still does not seem to be "correct." I could also define the set_bar method, but I don't like it :).
class Foo def bar x if (@bar.nil?) puts x else @bar.call x end end def set_bar &blk @bar = blk end end
So the question is: is there a better way to do this, and if not, which way do you prefer
Edit: The @ welldan97 approach works, but I am losing the scope of a local variable, i.e.
prefix = "*" def foo.bar x puts prefix + x.to_s end
does not work. I suggest that I have to stick with lambda to work?