How to prevent the case when parameters do not match in yield? - ruby

For example, it causes problem when I use yield(param) but pass a block {|p1,p2| ...} which has two parameters. How should I prevent this if I do not know what parameters yield takes a head of time?

Use a splat in the block, or simply pass variables which may be there and test for their definition:
def foo
yield 1, 2, 3
end
foo do |*args|
if 3 == args.length
# ... then I know I'm dealing with 3 args
end
end
foo do |a, b, c, d|
if !d.nil?
# ... then I know i was passed `d`
end
end

See this excellent blog post on Ruby Blocks, Procs, and Lambdas:
Understanding Ruby Blocks, Procs and Lambdas
It explains that Blocks (such as the one being passed in foo() {|p1,p2| ...}) act like Procs, which do not check the number of arguments passed. Lambdas do, however. So if you require strict checking of the number of arguments, you could potentially switch from accepting a Block in your method to accepting a Lambda as a method argument.

You should use a block argument instead of yield, which provides more information than yield such as arity.
def foo *params, &block
...
block.call(*params) if params.length == block.arity
...
end
foo(3){|x| puts x*3} # => 9
foo(3, 4){|x| puts x*3} # => Does not do anything

Related

Advantages of using block, proc, lambda in Ruby

Example: LinkedList printing method.
For this object, you will find a printing method using block, proc, and lambda.
It is not clear to me what the advantages/disadvantages are (if any).
Thank you
What is a LinkedList?
A LinkedList is a node that has a specific value attached to it (which is sometimes called a payload), and a link to another node (or nil if there is no next item).
class LinkedListNode
attr_accessor :value, :next_node
def initialize(value, next_node = nil)
#value = value
#next_node = next_node
end
def method_print_values(list_node)
if list_node
print "#{list_node.value} --> "
method_print_values(list_node.next_node)
else
print "nil\n"
return
end
end
end
node1 = LinkedListNode.new(37)
node2 = LinkedListNode.new(99, node1)
node3 = LinkedListNode.new(12, node2)
#printing the linked list through a method defined within the scope of the class
node3.method_print_values(node3)
#---------------------------- Defining the printing method through a BLOCK
def block_print_value(list_node, &block)
if list_node
yield list_node
block_print_value(list_node.next_node, &block)
else
print "nil\n"
return
end
end
block_print_value(node3) { |list_node| print "#{list_node.value} --> " }
#---------------------------- Defining the printing method through a PROC
def proc_print_value(list_node, callback)
if list_node
callback.call(list_node) #this line invokes the print function defined below
proc_print_value(list_node.next_node, callback)
else
print "nil\n"
end
end
proc_print_value(node3, Proc.new {|list_node| print "#{list_node.value} --> "})
#---------------------------- Defining the printing method through a LAMBDA
def lambda_print_value(list_node, callback)
if list_node
callback.call(list_node) #this line invokes the print function defined below
lambda_print_value(list_node.next_node, callback)
else
print "nil\n"
end
end
lambda_print_value(node3, lambda {|list_node| print "#{list_node.value} --> "})
#---------------------------- Defining the printing method outside the class
def print_values(list_node)
if list_node
print "#{list_node.value} --> "
print_values(list_node.next_node)
else
print "nil\n"
return
end
end
print_values(node3)
Examples display how to use different things to do the same. So, there is no principal difference between them in this context:
my_proc = Proc.new { |list_node| print "#{list_node.value} --> " }
node3.block_print_values(node3, &my_proc)
node3.proc_print_value(node3, my_proc)
node3.lambda_print_value(node3, my_proc)
Also, there is possible to define a method by using any of them:
define_method(:my_method, p, &proc { puts p })
my_method 'hello' #=> hello
define_method(:my_method, p, &-> { puts p })
my_method 'hello' #=> hello
But Proc, Lambda, block are not the same. Firstly, need a bit more display how to works magic &. The great article can help with that:
&object is evaluated in the following way:
if object is a block, it converts the block into a simple proc.
if object is a Proc, it converts the object into a block while preserving the lambda? status of the object.
if object is not a Proc, it first calls #to_proc on the object and then converts it into a block.
But this does not show the differences between them. So, now let go to the ruby source:
Proc objects are blocks of code that have been bound to a set of local variables. Once bound, the code may be called in different contexts and still access those variables.
And
+lambda+, +proc+ and Proc.new preserve the tricks of a Proc object given by & argument.
lambda(&lambda {}).lambda? #=> true
proc(&lambda {}).lambda? #=> true
Proc.new(&lambda {}).lambda? #=> true
lambda(&proc {}).lambda? #=> false
proc(&proc {}).lambda? #=> false
Proc.new(&proc {}).lambda? #=> false
Proc created as:
VALUE block = proc_new(klass, FALSE);
rb_obj_call_init(block, argc, argv);
return block;
When lambda:
return proc_new(rb_cProc, TRUE);
Both are Proc. In this case, the difference is just in TRUE or FALSE. TRUE, FALSE - check the number of parameters passed when called.
So, lambda is like more strict Proc:
is_proc = !proc->is_lambda;
Summary of Lambda vs Proc:
Lambdas check the number of arguments, while procs do not.
Return within the proc would exit the method from where it is called.
Return within a lambda would exit it from the lambda and the method would continue executing.
Lambdas are closer to a method.
Blocks: They are called closures in other languages, it is a way of grouping code/statements. In ruby single line blocks are written in {} and multi-line blocks are represented using do..end.
Block is not an object and can not be saved in a variable. Lambda and Proc are both an object.
So, let do small code test based on this answer:
# ruby 2.5.1
user system total real
0.016815 0.000000 0.016815 ( 0.016823)
0.023170 0.000001 0.023171 ( 0.023186)
0.117713 0.000000 0.117713 ( 0.117775)
0.217361 0.000000 0.217361 ( 0.217388)
This shows that using block.call is almost 2x slower than using yield.
Thanks, #engineersmnky, for good references in comments.
Proc is an object wrapper over block. Lambda basically is a proc with different behavior.
AFAIK pure blocks are more rational to use compared to procs.
def f
yield 123
end
Should be faster than
def g(&block)
block.call(123)
end
But proc can be passed on further.
I guess you should find some articles with performance comparison on the toppic
IMO, your block_print_value method is poorly designed/named, which makes it impossible to answer your question directly. From the name of the method, we would expect that the method "prints" something, but the only printing is the border condition, which does a
print "nil\n"
So, while I would strongly vote against using this way to print the tree, it doesn't mean that the whole idea of using a block for the printing problem is bad.
Since your problem looks like a programming assignment, I don't post a whole solution, but give a hint:
Replace your block_print_value by a, say block_visit_value, which does the same like your current method, but doesn't do any printing. Instead, the "else" part could also invoke the block to let it do the printing.
I'm sure that you will see afterwards the advantage of this method. If not, come back here for a discussion.
At a high level, procs are methods that can be stored inside variables like so:
full_name = Proc.new { |first,last| first + " " + last }
I can call this in two ways, using the bracket syntax followed by the arguments I want to pass to it or use the call method to run the proc and pass in arguments inside of parentheses like so:
p full_name.call("Daniel","Cortes")
What I did with the first line above is create a new instance of Proc and assigned it to a variable called full_name. Procs can take a code block as a parameter so I passed it two different arguments, arguments go inside the pipes.
I can also make it print my name five times:
full_name = Proc.new { |first| first * 5 }
The block I was referring to is called a closure in other programming languages. Blocks allow you to group statements together and encapsulate behavior. You can create blocks with curly braces or do...end syntax.
Why use Procs?
The answer is Procs give you more flexibility than methods. With Procs you can store an entire set of processes inside a variable and then call the variable anywhere else in your program.
Similar to Procs, Lambdas allow you to store functions inside a variable and call the method from other parts of the program. So really the same code I had above can be used like so:
full_name = lambda { |first,last| first + " " + last }
p full_name["daniel","cortes"]
So what is the difference between the two?
There are two key differences in addition to syntax. Please note that the differences are subtle, even to the point that you may never even notice them while programming.
The first key difference is that Lambdas count the arguments you pass to them whereas Procs do not. For example:
full_name = lambda { |first,last| first + " " + last }
p full_name.call("Daniel","Cortes")
The code above works, however, if I pass it another argument:
p full_name.call("Daniel","Abram","Cortes")
The application throws an error saying that I am passing in the wrong number of arguments.
However, with Procs it will not throw an error. It simply looks at the first two arguments and ignores anything after that.
Secondly, Lambdas and Procs have different behavior when it comes to returning values from methods, for example:
def my_method
x = lambda { return }
x.call
p "Text within method"
end
If I run this method, it prints out Text within method. However, if we try the same exact implementation with a Proc:
def my_method
x = Proc.new { return }
x.call
p "Text within method"
end
This will return a nil value.
Why did this occur?
When the Proc saw the word return it exited out of the entire method and returned a nil value. However, in the case of the Lambda, it processed the remaining part of the method.

Why do you have to specify 2 arguments explicitly to curry :>

Consider this, which works fine:
:>.to_proc.curry(2)[9][8] #=> true, because 9 > 8
However, even though > is a binary operator, the above won't work without the arity specified:
:>.to_proc.curry[9][8] #=> ArgumentError: wrong number of arguments (0 for 1)
Why aren't the two equivalent?
Note: I specifically want to create the intermediate curried function with one arg supplied, and then call then call that with the 2nd arg.
curry has to know the arity of the proc passed in, right?
:<.to_proc.arity # => -1
Negative values from arity are confusing, but basically mean 'variable number of arguments' one way or another.
Compare to:
less_than = lambda {|a, b| a < b}
less_than.arity # => 2
When you create a lambda saying it takes two arguments, it knows it takes two arguments, and will work fine with that style of calling #curry.
less_than.curry[9][8] # => false, no problem!
But when you use the symbol #to_proc trick, it's just got a symbol to go on, it has no idea how many arguments it takes. While I don't think < is actually an ordinary method in ruby, I think you're right it neccessarily takes two args, the Symbol#to_proc thing is a general purpose method that works on any method name, it has no idea how many args the method should take, so defines the proc with variable arguments.
I don't read C well enough to follow the MRI implementation, but I assume Symbol#to_proc defines a proc with variable arguments. The more typical use of Symbol#to_proc, of course, is for a no-argument methods. You can for instance do this with it if you want:
hello_proc = :hello.to_proc
class SomeClass
def hello(name = nil)
puts "Hello, #{name}!"
end
end
obj = SomeClass.new
obj.hello #=> "Hello, !"
obj.hello("jrochkind") #=> "Hello, jrochkind!"
obj.hello("jrochkind", "another")
# => ArgumentError: wrong number of arguments calling `hello` (2 for 1)
hello_proc.call(obj) # => "Hello, !"
hello_proc.call(obj, "jrochkind") # => "Hello, jrochkind!"
hello_proc.call(obj, "jrochkind", "another")
# => ArgumentError: wrong number of arguments calling `hello` (2 for 1)
hello_proc.call("Some string")
# => NoMethodError: undefined method `hello' for "Some string":String
Note I did hello_proc = :hello.to_proc before I even defined SomeClass. The Symbol#to_proc mechanism creates a variable arity proc, that knows nothing about how or where or on what class it will be called, it creates a proc that can be called on any class at all, and can be used with any number of arguments.
If it were defined in ruby instead of C, it would look something like this:
class Symbol
def to_proc
method_name = self
proc {|receiver, *other_args| receiver.send(method_name, *other_args) }
end
end
I think it is because Symbol#to_proc creates a proc with one argument. When turned into a proc, :> does not look like:
->x, y{...}
but it looks like:
->x{...}
with the requirement of the original single argument of > somehow tucked inside the proc body (notice that > is not a method that takes two arguments, it is a method called on one receiver with one argument). In fact,
:>.to_proc.arity # => -1
->x, y{}.arity # => 2
which means that applying curry to it without argument would only have a trivial effect; it takes a proc with one parameter, and returns itself. By explicitly specifying 2, it does something non-trivial. For comparison, consider join:
:join.to_proc.arity # => -1
:join.to_proc.call(["x", "y"]) # => "xy"
:join.to_proc.curry.call(["x", "y"]) # => "xy"
Notice that providing a single argument after Currying :join already evaluates the whole method.
#jrochkind's answer does a great job of explaining why :>.to_proc.curry doesn't have the behavior you want. I wanted to mention, though, that there's a solution to this part of your question:
I specifically want to create the intermediate curried function with one arg supplied, and then call then call that with the 2nd arg.
The solution is Object#method. Instead of this:
nine_is_greater_than = :>.to_proc.curry[9]
nine_is_greater_than[8]
#=> ArgumentError: wrong number of arguments (0 for 1)
...do this:
nine_is_greater_than = 9.method(:>)
nine_is_greater_than[8]
# => true
Object#method returns a Method object, which acts just like a Proc: it responds to call, [], and even (as of Ruby 2.2) curry. However, if you need a real proc (or want to use curry with Ruby < 2.2) you can also call to_proc on it (or use &, the to_proc operator):
[ 1, 4, 8, 10, 20, 30 ].map(&nine_is_greater_than)
# => [ true, true, true, false, false, false ]

ruby, two ways how to pass params to proc

I looked through this code and found author passes params to block using []. I tryed it myself
my_proc = proc { |x| x + 1 }
a = 0
my_proc[a] # => 1
my_proc.call(a) # => 1
What is the difference between this two calls? Is this a syntax sugar?
Both ways are exactly the same and are aliases to each other. Thus, both variants call the same method which is not determined by any special syntax. It is basically defined as:
class Proc
def call(*args)
#...
end
alias [] call
end
You might be interested to note that there is even a third way:
my_proc.(a)
This is actually syntactic sugar (i.e. is an extension of the syntax of the Ruby language language). All objects accepting #call can be "called" that way and Ruby ensures to invoke the call method.
They are functionally identical. You can use whichever style you prefer.

Is it possible to access block's scope in method?

I'd like to write the method (define_variables) which can get a block and use the variables defined in it. Is it possible? For example, I'd like to get 5 in output:
module A
def self.define_variables
yield
puts a # not 5 :(
end
end
A::define_variables do
a = 5
end
Maybe there is some tricks with eval, but haven't found anyone yet.
In short, no. After you've called yield those variables defined in the block are gone (sort of, as we shall see), except for what is returned—that's just how scope works. In your example, the 5 is still there in that it is returned by the block, and thus puts yield would print 5. Using this you could return a hash from the block {:a => 5}, and then access multiple "variables" that way. In Ruby 1.8 (in IRb only) you can do:
eval "a = 5"
a # => 5
Though I don't know of anyway to eval the contents of a block. Regardless, in Ruby 1.9 the scope of eval was isolated and this will give you a NameError. You can do an eval within the context of a Binding though:
def foo
b = yield
eval(a, b) + 2
end
foo do
a = 5
binding
end # => 7
It seems to me that what you're trying to do is emulate macros in Ruby, which is just not possible (at least not pure Ruby), and I discourage the use of any of the "workarounds" I've mentioned above.
Agreed that this is a bit backwards, and Andrew's explanation is correct. If your use case is defining variables, however, there are already class_variable_set and instance_variable_set methods that are great for this:
module A
def self.define_variables(vars = {})
vars.each { |n, v| class_variable_set n, v }
puts ##a
end
end
A::define_variables :##a => 5
The above is more of an example of how it would work within the code you've posted rather than a recommendation.

Accessing a passed block in Ruby

I have a method that accepts a block, lets call it outer. It in turn calls a method that accepts another block, call it inner.
What I would like to have happen is for outer to call inner, passing it a new block which calls the first block.
Here's a concrete example:
class Array
def delete_if_index
self.each_with_index { |element, i| ** A function that removes the element from the array if the block passed to delete_if_index is true }
end
end
['a','b','c','d'].delete_if_index { |i| i.even? }
=> ['b','d']
the block passed to delete_if_index is called by the block passed to each_with_index.
Is this possible in Ruby, and, more broadly, how much access do we have to the block within the function that receives it?
You can wrap a block in another block:
def outer(&block)
if some_condition_is_true
wrapper = lambda {
p 'Do something crazy in this wrapper'
block.call # original block
}
inner(&wrapper)
else
inner(&passed_block)
end
end
def inner(&block)
p 'inner called'
yield
end
outer do
p 'inside block'
sleep 1
end
I'd say opening up an existing block and changing its contents is Doing it WrongTM, maybe continuation-passing would help here? I'd also be wary of passing around blocks with side-effects; I try and keep lambdas deterministic and have actions like deleting stuff in the method body. In a complex application this will likely make debugging a lot easier.
Maybe the example is poorly chosen, but your concrete example is the same as:
[1,2,3,4].reject &:even?
Opening up and modifying a block strikes me as code smell. It'd be difficult to write it in a way that makes the side effects obvious.
Given your example, I think a combination of higher order functions will do what you're looking to solve.
Update: It's not the same, as pointed out in the comments. [1,2,3,4].reject(&:even?) looks at the contents, not the index (and returns [1,3], not [2,4] as it would in the question). The one below is equivalent to the original example, but isn't vary pretty.
[1,2,3,4].each_with_index.reject {|element, index| index.even? }.map(&:first)
So here's a solution to my own question. The passed in block is implicitly converted into a proc which can be received with the & parameter syntax. The proc then exists inside the closure of any nested block, as it is assigned to a local variable in scope, and can be called by it:
class Array
def delete_if_index(&proc)
ary = []
self.each_with_index { |a, i| ary << self[i] unless proc.call(i) }
ary
end
end
[0,1,2,3,4,5,6,7,8,9,10].delete_if_index {|index| index.even?}
=> [1, 3, 5, 7, 9]
Here the block is converted into a proc, and assigned to the variable proc, which is then available within the block passed to each_with_index.

Resources