Call optional proc only if proc was set - ruby

So I am porting a tool from ruby were a callback block could be defined on an object and I want it to be called in case the callback was set.
So basically something like this.
def set_block(&block)
#new_kid_on_the_block = block
end
def call_the_block_if_it_was_defined
block.call("step by step") if block = #new_kid_on_the_block
end
I am pretty sure this is an easy task but somehow I just run into problems.
Thank you in advance!

In Crystal you almost always have to specify types of instance variables explicitly. So here is how it could look:
class A
alias BlockType = String -> String
def set_block(&block : BlockType)
#block = block
end
def call_block
#block.try &.call("step by step")
end
end
a = A.new
pp a.call_block # => nil
a.set_block { |a| a + "!" }
pp a.call_block # => "step by step!"
Take a look at Capturing blocks for more.

Related

Is it possible to bind a parameter to a (unary) Proc object?

(Crossposting note: I have asked this already at the Ruby Forum one week ago, but did not get any response yet).
Here is a (very) simplified, working version of what I have so far:
# A class S with two methods, one which requires one parameter, and
# one without parameters.
class S
def initialize(s); #ms = s; end
def s_method1(i); puts "s_method1 #{i} #{#ms}"; end
def s_method2; puts "s_method2 #{#ms}"; end
end
# A class T which uses S, and "associates" itself to
# one of the both methods in S, depending on how it is
# initialized.
class T
def initialize(s, choice=nil)
#s = S.new(s)
# If choice is true, associate to the one-parameter-method, otherwise
# to the parameterless method.
#pobj = choice ? lambda { #s.s_method1(choice) } : #s.method(:s_method2)
end
# Here is how I use this association
def invoke
#pobj.call
end
end
In this example, depending on how T is constructed, T#invoke calls
either S#s_method1 or S#S_method2, but in the case of calling
S#s_method1, the parameter to s_method1 is already fixed at creation
time of the T object. Hence, the following two lines,
T.new('no arguments').invoke
T.new('one argument', 12345).invoke
produce the output
s_method2 no arguments
s_method1 12345 one argument
which is exactly what I need.
Now to my question:
In the case, where choice is nil, i.e. where I want to invoke the
parameterless method s_method2, I can get my callable object in an
elegant way by
#s.method(:s_method2)
In the case where choice is non-nil, I had to construct a Proc object
using `lambda. This not only looks clumsy, but also makes me feel a bit
uncomfortable. We have a closure here, which is connected to the
environment inside the initialize method, and I'm not sure whether this
could cause trouble by causing memory leaks in some circumstances.
Is there an easy way to simply bind a method object (in this case
#s.method(:s_method1) to a fixed argument?
My first idea was to use
#s.method(:s_method1).curry[choice]
but this does not achieve my goal. It would not return a callable Proc object, but instead actually execute s_method1 (this is not a bug, but documented behaviour).
Any other ideas of how my goal could be achieved?
Saving parameters separately
This option is simple, but it might not be what you're looking for :
class T
def initialize(s, choice=nil)
s = S.new(s)
#choice = choice
#pobj = s.method(choice ? :s_method1 : :s_method2)
end
def invoke
#pobj.call(*#choice)
end
end
T.new('no arguments').invoke
T.new('one argument', 12345).invoke
#=> s_method2 no arguments
#=> s_method1 12345 one argument
Method refinements for default parameters (Ruby 2.0+)
# Allows setting default parameters for methods, after they have been defined.
module BindParameters
refine Method do
def default_parameters=(params)
#default_params = params
end
def default_parameters
#default_params || []
end
alias_method :orig_call, :call
def call(*params)
merged_params = params + (default_parameters[params.size..-1] || [])
orig_call(*merged_params)
end
end
end
Here's an example :
def f(string)
puts "Hello #{string}"
end
def g(a, b)
puts "#{a} #{b}"
end
using BindParameters
f_method = method(:f)
f_method.default_parameters = %w(World)
f_method.call('user') # => Hello user
f_method.call # => Hello World
g_method = method(:g)
g_method.default_parameters = %w(Hello World)
g_method.call # => Hello World
g_method.call('Goodbye') # => Goodbye World
g_method.call('Goodbye', 'User') # => Goodbye User
Your code can be rewritten :
class T
using BindParameters
def initialize(s, *choice)
s = S.new(s)
#pobj = s.method(choice.empty? ? :s_method2 : :s_method1)
#pobj.default_parameters = choice
end
def invoke
#pobj.call
end
end
T.new('no arguments').invoke # => s_method2 no arguments
T.new('one argument', 12_345).invoke # => s_method1 12345 one argument
Monkey-Patching Method class (Ruby 1.9+)
If it is acceptable to patch the Method class, you could use :
class Method
def default_parameters=(params)
#default_params = params
end
def default_parameters
#default_params || []
end
alias_method :orig_call, :call
def call(*params)
merged_params = params + (default_parameters[params.size..-1] || [])
orig_call(*merged_params)
end
end
T becomes :
class T
def initialize(s, *choice)
s = S.new(s)
#pobj = s.method(choice.empty? ? :s_method2 : :s_method1)
#pobj.default_parameters = choice
end
def invoke
#pobj.call
end
end
Wrapping Method class (Ruby 1.9+)
This way is probably cleaner if you don't want to pollute Method class :
class MethodWithDefaultParameters
attr_accessor :default_parameters
attr_reader :method
def initialize(receiver, method_symbol)
#method = receiver.public_send(:method, method_symbol)
#default_parameters = []
end
def call(*params)
merged_params = params + (default_parameters[params.size..-1] || [])
method.call(*merged_params)
end
def method_missing(sym, *args)
method.send(sym, *args)
end
end
T becomes :
class T
def initialize(s, *choice)
s = S.new(s)
#pobj = MethodWithDefaultParameters.new(s, choice.empty? ? :s_method2 : :s_method1)
#pobj.default_parameters = choice
end
def invoke
#pobj.call
end
end
Any comment or suggestion are welcome!

Ruby - Is &prc different than &block?

I'm writing a simple method that adds num to the return value of the block that is passed to it and I noticed that &block and &prc both work. I know that a proc is an object and can be assigned to a variable which could be handy. Is that the only difference though? Is there any difference between these two when it comes to performance, convention, or versatility? Is it ever better to use &block instead of &prc?
def adder(num = 1, &block)
yield + num
end
vs.
def adder(num = 1, &prc)
yield + num
end
Is there any difference between these two when it comes to
performance, convention, or versatility?
There is no difference between these, you able to name it as you want, it's just a name. Some devs call it &blk some &block or &b or &foo ...
>> def foo &foo
>> yield
>> end
=> :foo
>> foo do
?> puts '1'
>> end
1
Strictly saying & is an operator which you can apply to any object, and it will take care of converting that object to a Proc by calling to_proc().
>> def bar(&some_proc)
>> some_proc
>> end
=> :bar
>> p = bar { puts 'Call proc' }
=> #<Proc:0x005601e6d69c80#(irb):4>
>> p.call
=> Call proc
>> p.class
=> Proc
Only the one thing is important, the name should be informative.
Line any argument to your method the name is largely subjective. Typically you'll see &block used if only by convention, but the name itself can be anything you want so long as it's a valid variable name.
In your example you're declaring a block name but not actually using the name. Keep in mind that any Ruby method can be given a block, there's no way to restrict this, but it's up to the method itself to use the block if it wants. That block can be called zero or more times either immediately or at some point in the future. Giving the block to the method surrenders control, so be sure to read the documentation on any given method carefully. There can be surprises.
If you need to chain through a block, declare it with a name:
def passes_through(&block)
[ 1, 2, 3, 4 ].each(&block)
end
If you are going to yield on the block there's no need here:
def direct_call
[ 1, 2, 3, 4 ].each do |n|
yield n
end
end
If you're going to preserve the call and use it later, that's also a case for naming it:
def preserved_call(&block)
#callback = block
end
def make_callback
#callback and #callback.call
end
Any method can check if a block was supplied:
def tests_for_block
if (block_given?)
yield 'value'
else
'value'
end
end
There's a small but measurable cost to capturing a block by declaring it in the method signature, a lot of computation has to be done to properly capture all the variables that might be used in a closure situation. In performance sensitive code you'll want to avoid this.
You can dynamically create a block:
def captures_conditionally
if (block_given?)
#callback = Proc.new
end
end
The Proc.new method will assume control over whatever block has been supplied to the method if one has been.
in your example, there is not a difference between &block and &prc, because in each case you are just passing a block to be call into the method.
Block and proc are similar in that they are both blocks of code.
[1,2,3].each {|x| puts x }
everything within the {} is the block.
A proc is just a block of code that you can name and can be called at a later time.
put_element = Proc.new {|x| puts x}
then you use put_element as an argument in your function.

Access outer attribute from a function override

I have a wrapper class which redefines a method of the wrapped class. Is there any way the wrapper's state can be accessed from inside the override method?
class WidgetWrapper
attr_accessor :result_saved_by_widget
def initialize(widget)
#widget = widget
# we intercept the widget's usual "save" method so we can see
# what the widget tries to save
def #widget.save_result(result) # this override works fine ...
OUTER.result_saved_by_widget = result # .. but I need something like this inside it!
end
end
def call
widget.calculate # this will call "save_result" at some stage
end
end
# How it gets used
wrapper = Wrapper.new(Widget.new)
wrapper.call
puts wrapper.result_saved_by_widget
Based on your example, I would extend the object with a module:
module WidgetExtension
attr_accessor :results_saved_by_widget
def save_result(result)
#results_saved_by_widget = result
super
end
end
w = Widget.new
w.extend(WidgetExtension)
w.calculate
w.results_saved_by_widget #=> stored value
Solved this with a perfectly stupid hack - injecting the wrapper object beforehand, using instance_variable_set.
class WidgetWrapper
attr_accessor :result_saved_by_widget
def initialize(widget)
#widget = widget
#widget.instance_variable_set :#wrapper, self
# we intercept the widget's usual "save" method so we can see
# what the widget tries to save
def #widget.save_result(result) # this override works fine ...
#wrapper.result_saved_by_widget = result # ... and this works too :)
end
end
def call
widget.calculate # this will call "save_result" at some stage
end
end
# How it gets used
wrapper = Wrapper.new(Widget.new)
wrapper.call
puts wrapper.result_saved_by_widget
I don't quite understand your question but I think did something quite similar in the past, maybe the following lines can help you :
documents_to_wrap.each do |doc|
doc.define_singleton_method(:method){override_code}
tmp = doc.instance_variable_get(:#instance_var).
doc.instance_variable_set(:#other_instance_var, tmp.do_something)
end
Actually, it's not that hard. A couple of points:
You probably want to call the original save_result. Otherwise, it's not much of a wrapper.
You need to use closure to capture current lexical context (meaning, memorize that we're in WidgetWrapper)
class Widget
def calculate
save_result(3)
end
def save_result(arg)
puts "original save_result: #{arg}"
end
end
class WidgetWrapper
attr_accessor :result_saved_by_widget, :widget
def initialize(widget)
#widget = widget
wrapper = self # `self` can/will unpredictably change.
#widget.define_singleton_method :save_result do |result|
wrapper.result_saved_by_widget = result
super(result)
end
end
def call
widget.calculate
end
end
# How it gets used
wrapper = WidgetWrapper.new(Widget.new)
wrapper.call
puts 'intercepted value'
puts wrapper.result_saved_by_widget
# >> original save_result: 3
# >> intercepted value
# >> 3

Ruby yield newbie issue

I have recently started using Ruby, so quite new to this. My current objective is to use a ruby module called retort, my problem is that I don't understand the configure method which is looking like this:
def configure
config = Config.new
yield config
##service = XMLRPC::Client.new2(config.url)
end
Config class is simple and looks like:
class Config
attr_accessor :url
end
I tried to create a small example to play around in order to understand how exactly that is supposed to work:
class TestClass
def test_method
config = String.new
yield config
p config
end
end
d = TestClass.new
d.test_method { 'test string' }
Of course it doesn't return 'test string' but an empty string.
Thank you for any help :)
Can you be clearer about what's confusing you? Does this code make sense to you?
class TestClass
def test_method
config = yield
p config
end
end
d.test_method { "test string" }
The yield statement invokes the block. The block returns a string, which is assigned to the config variable back in the test_method and is then printed. Does that make it clearer?
In your code, the line yield config is invoking the block while passing in the just-instantiated Config object. For instance:
def foo
s = "a string"
yield s
p "In foo printing " + s
end
foo { |x| p "In block printing " + x }

Change the binding of a Proc in Ruby

I have this code:
l = lambda { a }
def some_function
a = 1
end
I just want to access a by the lambda and a special scope which has defined a already somewhere like inside some_function in the example, or just soon later in the same scope as:
l = lambda { a }
a = 1
l.call
Then I found when calling l, it is still using its own binding but not the new one where it was called.
And then I tried to use it as:
l.instance_eval do
a = 1
call
end
But this also failed, it is strange that I can't explain why.
I know the one of the solution is using eval, in which I could special a binding and executing some code in text, but I really do not want to use as so.
And, I know it is able to use a global variable or instance variable. However, actually my code is in a deeper embedded environment, so I don't want to break the completed parts if not quite necessary.
I have referred the Proc class in the documentation, and I found a function names binding that referred to the Proc's context. While the function only provided a way to access its binding but cannot change it, except using Binding#eval. It evaluate text also, which is exactly what I don't like to do.
Now the question is, do I have a better (or more elegant) way to implement this? Or using eval is already the regular manner?
Edit to reply to #Andrew:
Okay, this is a problem which I met when I'm writing a lexical parser, in which I defined a array with fixed-number of items, there including at least a Proc and a regular expression. My purpose is to matching the regular expressions and execute the Procs under my special scope, where the Proce will involved some local variables that should be defined later. And then I met the problem above.
Actually I suppose it is not same completely to that question, as mine is how to pass in binding to a Proc rather than how to pass it out.
#Niklas:
Got your answer, I think that is what exactly I want. It has solved my problem perfectly.
You can try the following hack:
class Proc
def call_with_vars(vars, *args)
Struct.new(*vars.keys).new(*vars.values).instance_exec(*args, &self)
end
end
To be used like this:
irb(main):001:0* lambda { foo }.call_with_vars(:foo => 3)
=> 3
irb(main):002:0> lambda { |a| foo + a }.call_with_vars({:foo => 3}, 1)
=> 4
This is not a very general solution, though. It would be better if we could give it Binding instance instead of a Hash and do the following:
l = lambda { |a| foo + a }
foo = 3
l.call_with_binding(binding, 1) # => 4
Using the following, more complex hack, this exact behaviour can be achieved:
class LookupStack
def initialize(bindings = [])
#bindings = bindings
end
def method_missing(m, *args)
#bindings.reverse_each do |bind|
begin
method = eval("method(%s)" % m.inspect, bind)
rescue NameError
else
return method.call(*args)
end
begin
value = eval(m.to_s, bind)
return value
rescue NameError
end
end
raise NoMethodError
end
def push_binding(bind)
#bindings.push bind
end
def push_instance(obj)
#bindings.push obj.instance_eval { binding }
end
def push_hash(vars)
push_instance Struct.new(*vars.keys).new(*vars.values)
end
def run_proc(p, *args)
instance_exec(*args, &p)
end
end
class Proc
def call_with_binding(bind, *args)
LookupStack.new([bind]).run_proc(self, *args)
end
end
Basically we define ourselves a manual name lookup stack and instance_exec our proc against it. This is a very flexible mechanism. It not only enables the implementation of call_with_binding, it can also be used to build up much more complex lookup chains:
l = lambda { |a| local + func(2) + some_method(1) + var + a }
local = 1
def func(x) x end
class Foo < Struct.new(:add)
def some_method(x) x + add end
end
stack = LookupStack.new
stack.push_binding(binding)
stack.push_instance(Foo.new(2))
stack.push_hash(:var => 4)
p stack.run_proc(l, 5)
This prints 15, as expected :)
UPDATE: Code is now also available at Github. I use this for one my projects too now.
class Proc
def call_with_obj(obj, *args)
m = nil
p = self
Object.class_eval do
define_method :a_temp_method_name, &p
m = instance_method :a_temp_method_name; remove_method :a_temp_method_name
end
m.bind(obj).call(*args)
end
end
And then use it as:
class Foo
def bar
"bar"
end
end
p = Proc.new { bar }
bar = "baz"
p.call_with_obj(self) # => baz
p.call_with_obj(Foo.new) # => bar
Perhaps you don't actually need to define a later, but instead only need to set it later.
Or (as below), perhaps you don't actually need a to be a local variable (which itself references an array). Instead, perhaps you can usefully employ a class variable, such as ##a. This works for me, by printing "1":
class SomeClass
def l
#l ||= lambda { puts ##a }
end
def some_function
##a = 1
l.call
end
end
SomeClass.new.some_function
a similar way:
class Context
attr_reader :_previous, :_arguments
def initialize(_previous, _arguments)
#_previous = _previous
#_arguments = _arguments
end
end
def _code_def(_previous, _arguments = [], &_block)
define_method("_code_#{_previous}") do |_method_previous, _method_arguments = []|
Context.new(_method_previous, _method_arguments).instance_eval(&_block)
end
end
_code_def('something') do
puts _previous
puts _arguments
end

Resources