Running a method between each method call - ruby

Basically I want something like this:
some_method do
method1()
method2()
method3()
end
where between each of these 3 methods, there would be sleep 5, I just don't want to repeat sleep 5 after each and every method call. Is there a way to define some_method such as, between each method call, a particular method like sleep 5 is being executed? I don't want to pollute my code by inserting a bunch of sleep commands after each and every method call.

If, as in the example, the methods take no arguments or blocks, and the return values are not used, you could do the following.
module M
def method1
puts "method 1"
end
def method2
puts "method 2"
end
def method3
puts "method 3"
end
end
class A
include M
def method4
puts "method 4"
end
def execute_methods
M.instance_methods.each { |m| send m; sleep 5 }
end
end
A.new.execute_methods
# method 1
# method 2
# method 3
One advantage of including a module containing the methods to be executed is that you can add, remove or rename methods in the module without changing any other code. This technique might be potentially useful, for example, when executing a series of validation methods that each return true or false:
def validate(obj)
M.instance_methods.all? { |m| send m, obj }
end
This is also an example of methods that have arguments and whose return values are used.

Note, I don't know Ruby, so this will be in a javascripty flavour of pseudocode, and won't make use of any "special features" of Ruby.
This is probably the simplest way to achieve what you're looking for:
function execute_in_sequence(delay, fs) {
foreach(f in fs) {
f();
sleep(delay);
}
}
Then you can use it like:
function p() {
print(1);
}
execute_in_sequence(500,
[p, p, p]
);
You could also get rid of the explicit list using variadic functions, which could let you write it as:
execute_in_sequence(500,
p,
p,
p
);
In this example, p is pretty simple. To do this with functions that require arguments, you would need to wrap the calls in a lambda first.
Also note that the obvious flaw is that you can't return any values this way. All of the functions must operate soley through side effects, which limits the use of this.

Here's one possible some_method implementation.
Parameters are the methods names as symbol (i.e :method1 for method1()), and if a block is given, it's executed after each method call.
def method1
puts "Method1"
end
def method2
puts "Method2"
end
def method3
puts "Method3"
end
def some_method(*methods)
methods.each{|m|
send m
yield if block_given?
}
end
some_method(:method1, :method2, :method3) do
puts " Waiting 5 sec."
sleep 5
end
It returns :
Method1
Waiting 5 sec.
Method2
Waiting 5 sec.
Method3
Waiting 5 sec.
With some tweaks and more logic, you could also send parameters to the different methods and saves what the methods return in an Array.

Related

Is there any way to call all the methods inside the class with the single line code in Ruby?

I have done online research on this and also searched for the solution on SO but still didn't got any.
Need a simple, efficient, time and space saving way to call all the functions in a class
Here i have a class with many methods defined inside. after the end of the class, i have to call all the defined methods to execute the block of code inside each methods.
class Sample
def initialize(arg1, arg2)
#arg1 = arg1
#arg2 = arg2
end
def method1
puts #arg1
end
def method2
puts #arg2
end
def method3
puts "This is method3"
end
def method4
puts "This is method4"
end
.............
.............
............. etc...
end
Now creating an object for calling the class and method
object = Sample.new(par1, par2)
object.method1
object.method2
object.method3
object.method4
.............
............. etc...
calling the methods one by one using the object.method_name(parameter) is really hard and taking very long space and time.
is it possible to call all the methods by a single line code (or) with any other efficient way?
is it possible to call all the methods by a single line code
Yes, that is possible.
Personally, I don't get the obsession with squeezing everything into a single line. It does not make code smaller, it does not make code better, it does not make code easier to read. But it is technically possible.
In Ruby, line breaks are always optional. They can always be replaced with something else. If the line break is used as an expression separator, it can be replaced with a semicolon (;), which is also an expression separator. If the line break is used to terminate some syntactic element, it can be replaced with either a semicolon (;), a keyword (for example then in if and unless, when in case, do in for, while, and until, and so on), and sometimes just whitespace.
So, you could write your code in a single line like this:
object = Sample.new(par1, par2); object.method1; object.method2; object.method3; object.method4; # … etc …
calling the methods one by one using the object.method_name(parameter) is really hard and taking very long space and time.
Whether you write the code on one line or multiple lines has no effect on the space or time requirements of your program.
If you execute the methods sequentially, the space requirement will be the maximum of the space requirements of all the methods and the time requirement will be the sum of the time requirements of all the methods.
You can execute the methods in parallel. In that case, the space requirement will be the sum of the space requirements of all the methods and the time requirement will be the maximum of the time requirements of all the methods plus any time needed to coordinate the parallel execution and merge the results back together. Also, executing the methods in parallel will change the result of the program!
Either way, you can only improve either space or time, not both.
You need to add any prefix like auto __call__ in method name that you need to call automatically in single line dynamic code
just find method names using simple string operation in method names array then call them using send method
class Sample
def initialize(arg1, arg2)
#arg1 = arg1
#arg2 = arg2
end
def auto__call__method1
puts #arg1
end
def auto__call__method2
puts #arg2
end
def auto__call__method3
puts "This is method3"
end
def auto__call__method4
puts "This is method4"
end
end
object = Sample.new('arg1', 'arg2')
object.public_methods
.select{ |m| m.to_s.include? 'auto__call__'}
.each{ |auto__call_method| object.send(auto__call_method) }
output
arg2
This is method3
This is method4
arg1
if you need to any presidency in method calling then add presidency prefix then sort method names then call it
like below
class Sample
def initialize(arg1, arg2)
#arg1 = arg1
#arg2 = arg2
end
def auto__call_4_method1
puts #arg1
end
def auto__call_3_method2
puts #arg2
end
def auto__call_2_method3
puts "This is method3"
end
def auto__call_1_method4
puts "This is method4"
end
end
object = Sample.new('arg1', 'arg2')
object.public_methods
.select{ |m| m.to_s.include? 'auto__call_'}
.sort
.each{ |my_method_name| object.send(my_method_name) }
output
This is method4
This is method3
arg2
arg1
Can you give more context what these methods are supposed to do?
I think I would go for adding an extra method in there that calls them for you.
def call_em_all
method1
method2
method3
method4
end

Proc.new binding change and loops logic abstraction

I've two loops in two different methods which look very similar. I wanted to abstract most of their logic in a Proc.new
This works
def matches_base?
proc_exec = Proc.new do |subclass, breakpoint|
# next and return are meant to act inside the loop and quit it if needed
response = process_match(subclass)
next if response == :continue
return true if response == false
return response
end
subclasses(BASE_NAMESPACE).each do |subclass|
proc_exec.call(subclass)
end
false
end
The obvious issue here is the proc_exec is defined inside the method itself, but I want to use it in another method
def matches_breakpoints?
breakpoints.fetch.each do |breakpoint|
# I want to include the proc_exec here too
end
false
end
So I just tried to extract it at the class level like so
This does not work
def proc_exec
Proc.new do |subclass, breakpoint|
response = process_match(subclass)
next if response == :continue
return true if response == false
return response
end
end
def matches_base?
subclasses(BASE_NAMESPACE).each do |subclass|
proc_exec.call(subclass)
end
false
end
Then I could have called it like proc_exec.call from within both instance methods. Currently it throws
LocalJumpError:
unexpected return
I tried many tricks such as instance_eval or instance_exec without success. I'm out of solution right now.
Easily executable, simplified example of what I want below.
class MyLoops
def proc_exec
Proc.new do |num|
next if num == 1
# we want this `return` to act in the method context
# as it would do if I defined it inside a method directly
return if num == 4
puts "Current number : #{num}"
end
end
def method_a
[0,1,2].each do |num|
proc_exec.call(num)
end
false
end
def method_b
[3,4,5].each do |num|
proc_exec.call(num)
end
end
# this `false` below should never be reached ; that's the trick
false
end
loops = MyLoops.new
loops.method_a
loops.method_b
You can't have your cake and eat it too. If you want return from the proc to abort the method, it must be in the method's lexical scope* (which is another way to say "it must be defined within the same method").
An alternative is to have proc/lambda return a "stop" value, which caller will use to abort its execution.
(Your experiments with instance_eval/instance_exec were misdirected, sadly. Those methods only change current self. This problem has nothing to do with current self, but rather current lexical scope, in which return is executed.)
* The error you're getting, it is caused by return trying to return from a method that is no longer running (proc_exec).

Return a curried function, like in Haskell

I want to be able to call a function this way:
func = ->(a, b) {
if ...
method1 # error - it requires 2 arguments when it's being called
# it should be method1(a, b)
# but I don't want that redundancy here
elsif ...
method2 # error - it requires 2 arguments when it's being called
elsif ...
method3 # error - it requires 2 arguments when it's being called
else ...
method4 # error - it requires 2 arguments when it's being called
end
}
param1 = ....
param2 = ....
func.call(param1, param2) # ok so far but error in the block above
def method1(var1, var2)
end
def method2(var1, var2)
end
def method3(var1, var2)
end
def method4(var1, var2)
end
But I don't want to repeat myself inside the block func = ->(a, b) { by adding 2 arguments to the functions. Those of you who know Haskell will understand what I mean.
Is there any way to do it?
You can store the name of the method you want to call as a string-variable (or symbol); then use send to pass this variable along with the arguments.
An example:
def method_one(a, b)
# something_one
end
def method_two(a, b)
# something_two
end
def method_three(a, b) # the method you call
if condition_one
method_name = "method_one"
elsif condition_two
method_name = "method_two"
else
# something else
end
send(method_name, a, b) if method_name
end
If method_one and method_two are public methods, I would recommend using public_send instead of send simply because it is more explicit which could potentially help others who read your code.
From the Haskell wiki: "Currying is the process of transforming a function that takes multiple arguments into a function that takes just a single argument and returns another function if any arguments are still needed."
OP does not provide a single argument, but no arguments at all. Anyway, Ruby does have a curry method which results in a proc:
proc1 = ->(var1,var2){p var1+var2}.curry
proc2 = proc1[1] #same as proc2 = proc1.call(1)
proc2[2] # => 3
Asking for clarification here since this isn't going to fit in a comment:
My understanding of currying:
method_one(a, b) takes two arguments.
If you call it using method_one(a), it should return a partial function which expects one argument, and applies the first to the second. Eg.
def multiply(a, b=nil)
if b
a*b
else
Proc.new { |b| a*b }
end
end
This allows you to do stuff like:
def multiply_by_three(b)
multiply(3).call
end
So do you want to:
pass in a and b to func and get back a Proc acting on a and b or,
define your separate methods outside and apply it inside func without using the method_name(a,b) form?

Overloading in Ruby

I want to use overloading feature in Ruby like many other languages, but Ruby itself does not support this feature.
Do I have to implement it using the way that define a method with *args argument and determine the number and types of the arguments inside the method? Some like:
class A
def foo(*args)
case (args.length)
when 1
do something
when 2
do something-else
....
end
end
end
You can see, it is really ugly than directly overloading.
I want to know whether there is any keywords or some other manners (like a meta-programming module) that could allow me to define an overloading method in a more elegant way.
You could try some meta programming to reach your target.
See the following code:
class OverloadError < ArgumentError; end
class Class
=begin rdoc
=end
def define_overload_method( methodname, *methods )
methods.each{ | proc |
define_method("#{methodname}_#{proc.arity}".to_sym, &proc )
}
define_method(methodname){|*x|
if respond_to?("#{methodname}_#{x.size}")
send "#{methodname}_#{x.size}", *x
else
raise OverloadError, "#{methodname} not defined for #{x.size} parameters"
end
}
end
end
class X
define_overload_method :ometh,
Proc.new{ "Called me with no parameter" },
Proc.new{ |p1| "Called me with one parameter (#{p1.inspect})" },
Proc.new{ |p1,p2| "Called me with two parameter (#{p1.inspect}, #{p2.inspect})" }
end
x = X.new
p '----------'
p x.ometh()
p x.ometh(1)
p x.ometh(1,2)
p x.ometh(1,2,3) #OverloadError
You can define your overloaded method with define_overload_method. Parameters are the method name and a list of procedures. The method methodname is created and calls the corresponding method. Which method is determined by the number of parameters (Not type!).
An alternative syntax would be:
class OverloadError < ArgumentError; end
class Class
def def_overload( methodname)
define_method(methodname){|*x|
if respond_to?("#{methodname}_#{x.size}")
send "#{methodname}_#{x.size}", *x
else
raise OverloadError, "#{methodname} not defined for #{x.size} parameters"
end
}
end
def overload_method( methodname, proc )
define_method("#{methodname}_#{proc.arity}".to_sym, &proc )
end
end
class X
def_overload :ometh
overload_method :ometh, Proc.new{ "Called me with no parameter" }
overload_method :ometh, Proc.new{ |p1| "Called me with one parameter (#{p1.inspect})" }
overload_method :ometh, Proc.new{ |p1,p2| "Called me with two parameter (#{p1.inspect}, #{p2.inspect})" }
end
def_overload defines the frame for your overloaded methods, overload_method defines one 'overload-method'.
But as already mentioned by Holger:
You should try to adapt to the Ruby way. There is a reason why there is no overloading in Ruby. Methods should only do one thing, not magically decide to do vastly different things just because of different arguments. Instead try to take advantage of Duck Typing and if in doubt, use different methods with meaningful names.
I was curious how I could implement a version with type sensitive overloading. Here it is:
class OverloadError < ArgumentError; end
class Class
def def_overload( methodname)
define_method(methodname){|*x|
methname = "xxx"
methname = "#{methodname}_#{x.size}#{x.map{|p| p.class.to_s}.join('_')}"
if respond_to?(methname)
send methname, *x
elsif respond_to?("#{methodname}_#{x.size}")
send "#{methodname}_#{x.size}", *x
else
raise OverloadError, "#{methodname} not defined for #{x.size} parameters"
end
}
end
def overload_method( methodname, *args, &proc )
types = []
args.each{|arg| types << arg.to_s}
define_method("#{methodname}_#{proc.arity}#{types.join('_')}".to_sym, &proc )
end
end
class X
def_overload :ometh
overload_method(:ometh){ "Called me with no parameter" }
overload_method(:ometh, String ){ |p1| "Called me with one string parameter (#{p1.inspect})" }
overload_method(:ometh ){ |p1| "Called me with one parameter (#{p1.inspect})" }
overload_method(:ometh){ |p1,p2| "Called me with two parameter (#{p1.inspect}, #{p2.inspect})" }
end
When you call it with
p x.ometh(1)
p x.ometh('a')
You get
"Called me with one parameter (1)"
"Called me with one string parameter (\"a\")"
You can test for the existence of each argument separately as they are set to nil if not passed (assuming they are passed in order!).
If you insist on very different arguments I suggest an hash argument with symbols for each argument you intend.. and approriate tests.
** UPDATE **
Also you could also rename the methods that overload with more specific names, such as
def perform_task_with_qualifier_1
there are few gems that provide this feature to your ruby code
functional-ruby
defn(:greet, :male) {
puts "Hello, sir!"
}
defn(:greet, :female) {
puts "Hello, ma'am!"
}
foo.greet(:male) => "Hello, sir!"
foo.greet(:female) => "Hello, ma'am!"
you can find more Elixir like pattern matching features from here
contracts.ruby
Contract 1 => 1
def fact x
x
end
Contract C::Num => C::Num
def fact x
x * fact(x - 1)
end
this gem helps to right beautiful defensive code. there are some criticisms about performance. so benchmark and decide. more examples
The defining characteristic of overloading is that dispatch happens statically. In Ruby, dispatch always happens dynamically, there is no other way. Therefore, overloading is not possible in Ruby.

how to pass a Ruby iterator as a parameter?

I'd like to write a method that yields values in one place and pass it as a parameter to another method that will invoke it with a block. I'm convinced it can be done but somehow I'm not able to find the right syntax.
Here's some sample (non-working) code to illustrate what I'm trying to achieve:
def yielder
yield 1
yield 2
yield 3
end
def user(block)
block.call { |x| puts x }
end
# later...
user(&yielder)
$ ruby x.rb
x.rb:2:in `yielder': no block given (yield) (LocalJumpError)
from x.rb:12:in `<main>'
FWIW, in my real code, yielder and user are in different classes.
Update
Thanks for your answers. As Andrew Grimm mentioned, I want the iterator method to take parameters. My original example left this detail out. This snippet provides an iterator that counts up to a given number. To make it work, I made the inner block explicit. It does what I want, but it's a bit ugly. If anyone can improve on this I'd be very interested in seeing how.
def make_iter(upto)
def iter(upto, block)
(1 .. upto).each do |v|
block.call(v)
end
end
lambda { |block| iter(upto, block) }
end
def user(obj)
obj.call Proc.new { |x| puts x }
end
# later...
user(make_iter(3))
This doesn't use a lambda or unbound method, but it is the simplest way to go...
def f
yield 1
yield 2
end
def g x
send x do |n|
p n
end
end
g :f
When you write &yielder, you're calling yielder and then trying to apply the & (convert-to-Proc) operator on the result. Of course, calling yielder without a block is a no-go. What you want is to get a reference to the method itself. Just change that line to user(method :yielder) and it will work.
I think this might be along the lines of what you want to do:
def yielder
yield 1
yield 2
yield 3
end
def user(meth)
meth.call { |x| puts x }
end
# later...
user( Object.method(:yielder) )
Some related info here: http://blog.sidu.in/2007/11/ruby-blocks-gotchas.html
As it has been pointed out the baseline problem is that when you try to pass a function as a parameter Ruby executes it – as a side effect of parenthesis being optional.
I liked the simplicity of the symbol method that was mentioned before, but I would be afraid of my future self forgetting that one needs to pass the iterator as a symbol to make that work. Being readability a desired feature, you may then wrap your iterator into an object, which you can pass around without fear of having code unexpectedly executed.
Anonymous object as iterator
That is: using an anonymous object with just one fuction as iterator. Pretty immediate to read and understand. But due to the restrictions in the way Ruby handles scope the iterator cannot easily receive parameters: any parameters received in the function iterator are not automatically available within each.
def iterator
def each
yield("Value 1")
yield("Value 2")
yield("Value 3")
end
end
def iterate(my_iterator)
my_iterator.each do |value|
puts value
end
end
iterate iterator
Proc object as iterator
Using a Proc object as iterator lets you easily use any variables passed to the iterator constructor. The dark side: this starts looking weird. Reading the Proc.new block is not immediate for the untrained eye. Also: not being able to use yield makes it a bit uglier IMHO.
def iterator(prefix:)
Proc.new { |&block|
block.call("#{prefix} Value 1")
block.call("#{prefix} Value 2")
block.call("#{prefix} Value 3")
}
end
def iterate(my_iterator)
my_iterator.call do |value|
puts value
end
end
iterate iterator(prefix: 'The')
Lambda as iterator
Ideal if you want to obfuscate your code so hard that no one else besides you can read it.
def iterator(prefix:)
-> (&block) {
block.call("#{prefix} Value 1")
block.call("#{prefix} Value 2")
block.call("#{prefix} Value 3")
}
end
def iterate(my_iterator)
my_iterator.call do |value|
puts value
end
end
iterate iterator(prefix: 'The')
Class as iterator
And finally the good ol' OOP approach. A bit verbose to initialize for my taste, but with little or none surprise effect.
class Iterator
def initialize(prefix:)
#prefix = prefix
end
def each
yield("#{#prefix} Value 1")
yield("#{#prefix} Value 2")
yield("#{#prefix} Value 3")
end
end
def iterate(my_iterator)
my_iterator.each do |value|
puts value
end
end
iterate Iterator.new(prefix: 'The')

Resources