I'm wondering if it's possible to pass a block to a Proc. Simply passing a block to Proc.call doesn't work:
foo = Proc.new {
yield
}
foo.call {
puts "test"
}
Results in:
LocalJumpError: no block given (yield)
The same happens with lambdas. However this does work with method objects:
class Foo
def bar
yield
end
end
bar = Foo.new.method :bar
bar.call { puts "Success!" }
Results in:
Success!
The odd thing is that it still works after converting the method object into a proc:
bar.to_proc.call { puts "Success!" }
Results in:
Success!
So how come the Proc that was made from a block doesn't accept blocks, but the Proc that was originally a method does? Is it possible to create Procs from blocks that accepts blocks?
Procs can't accept blocks as implicit arguments (the format you're trying). A proc can receive other proc objects as arguments, either explicitly, or using & arguments. Example:
a = Proc.new do |&block|
block.call
end
a.call() {puts "hi"}
yield is a bit of laguage level magic that only works in the context of a method.
The above answer is not 100% correct therefore can't be accepted answer. Especially the part;
Procs can't accept blocks as implicit arguments (the format you're trying). A proc can receive other proc objects as arguments, either explicitly, or using & arguments.
This is wrong. Procs and lambdas can call yield in their bodies. The fact to keep in mind is, Proc/lambda bodies have a lexical scope! Which means, if there is a block while defining the Proc/lambda, yield would successfully execute, like so;
def foo
my_proc = Proc.new { yield }
my_proc.call
end
foo { puts "Hello world!" } # would print "Hello world!"
As you can see, yield worked! Because there was block while defining the Proc.
One can say, the Proc is unfolded into method which has block while calling therefore yield worked. This is also wrong and can be disproved easily with the following snippet;
def foo
#my_proc ||= Proc.new { yield }
#my_proc.call
end
foo { puts "Hello again!" } # would print "Hello world!"
foo # would print "Hello world!"
As you can again see, it's about having block while defining the Proc.
If you want to have better understanding of whats being lexically scoped mean, let's have a look at the following example.
class Foo
def self.hello_proc
Proc.new { puts name }
end
def self.name
"Alice"
end
end
class Bar
def self.put_name
Foo.hello_proc.call
end
def self.name
"Bob"
end
end
Bar.put_name # would print "Alice"
You can copy and paste above code to an irb session to see what is the output. The reason it puts "Alice" is, the name was "Alice" while the Proc's being defined.
I expect the code
foo=proc{puts "foo"}
instance_exec(1,2,3,&foo) do |*args , &block|
puts *args
block.call
puts "bar"
end
to output
1
2
3
foo
bar
But got the error
both block arg and actual block given
Can I pass a block which itself expect a block to instance_exec in ruby?
&foo tries to pass foo as a block to instance_exec, and you are already passing an explicit block. Omitting ampersand sends foo just like any other argument (except that it is a Proc instance). So, try this instead:
instance_exec(1,2,3,foo) do |*args, block|
puts *args
block.call
puts "bar"
end
This also means that you can do something like:
bar = proc{ |*args, block|
puts *args
block.call
puts "bar"
}
instance_exec(1,2,3,foo,&bar)
And get the same result.
More info at Difference between block and &block in Ruby
I'm about 3 years late to this party, but I thought I'd share an approach that let's you treat the inner block more like a real block, rather than just a plain old argument.
The best way I know of to go about this is to create an object to act as a binding context and define the outer block as a method. So if I rewrite the original example as follows without the instance_exec call...
inner_proc = proc { puts "inner" }
outer_proc = proc { |*args, &inner_block|
puts *args
inner_block.call
puts "bar"
}
We can define outer_proc as a method on an object
scope_object = Object.new
scope_object.define_singleton_method :bound_proc, &outer_proc
Now you can call scope_object.bound_proc instead of the instance_exec call above.
scope_object.bound_proc 1, 2, 3, &inner_proc
You'll get:
1
2
3
inner
bar
Unfortunately, you'll get a LocalJumpError if you try to yield inside of outer_proc, rather than the inner_block.call, I'm not entirely sure why. If someone has that answer then I'd be interested.
I want to store a "code block" in a variable to be reused, something like:
block = do
|test| puts test
end
3.upto(8) block
Can someone show me what am I doing so obviously wrong? (Or if it's just impossible)
There are many ways to do this in Ruby, one of which is to use a Proc:
foo = Proc.new do |test|
puts test
end
3.upto(8) { foo.call("hello world") }
Read more about Procs:
http://www.reactive.io/tips/2008/12/21/understanding-ruby-blocks-procs-and-lambdas
http://www.skorks.com/2010/05/ruby-procs-and-lambdas-and-the-difference-between-them/
Update, the above method could be rewritten as follows:
# using lower-case **proc** syntax, all on one line
foo = proc { |test| puts test }
3.upto(8) { foo.call("hello world") }
# using lambda, just switch the method name from proc to lambda
bar = lambda { |test| puts test }
3.upto(8) { bar.call("hello world") }
They're basically very similar methods, with subtle differences.
And finally, there are probably more elegant ways to do what I've outlined, be good to hear from anyone with a better way. Hope this helps.
I have seen here and there code like this one
Specification.new do |s|
s.name = %q{casein}
s.version = "3.1.11"
....
Can someone explain me what is the idea behind "do |s|" ?
This is an example of using blocks in ruby. Block is a chunk of code that you can pass to a method (new is just a regular method).
class Foo
def initialize
puts "doing some work"
yield('Foo') if block_given?
end
end
Foo.new do |s|
puts "output from #{s}"
end
# >> doing some work
# >> output from Foo
Here initializer in Foo calles a block (if one is given) and passes it a parameters. Block then can receive that parameter and do its work.
Educational reading here.
it's an argument that gets exposed to block by initializer of Specification
things probably look like this in that class:
class Specification
def initialize
# ...
yield self
# ...
end
end
that yield executes a block and passes a single argument to it - self (it might be any other object so better go check the source)
code block usually looks like this:
do |arguments, list|
# code here
end
but arguments are optional(unless it's lambda and you will get exception for too few or too many)
I am trying to understand blocks and yield and how they work in Ruby.
How is yield used? Many of the Rails applications I've looked at use yield in a weird way.
Can someone explain to me or show me where to go to understand them?
Yes, it is a bit puzzling at first.
In Ruby, methods can receive a code block in order to perform arbitrary segments of code.
When a method expects a block, you can invoke it by calling the yield function.
Example:
Take Person, a class with a name attribute and a do_with_name method. When the method is invoked it will pass the name attribute to the block.
class Person
def initialize( name )
#name = name
end
def do_with_name # expects a block
yield( #name ) # invoke the block and pass the `#name` attribute
end
end
Now you can invoke this method and pass an arbitrary code block.
person = Person.new("Oscar")
# Invoking the method passing a block to print the value
person.do_with_name do |value|
puts "Got: #{value}"
end
Would print:
Got: Oscar
Notice the block receives as a parameter a variable called value. When the code invokes yield it passes as argument the value of #name.
yield( #name )
The same method can be invoked with a different block.
For instance to reverse the name:
reversed_name = ""
# Invoke the method passing a different block
person.do_with_name do |value|
reversed_name = value.reverse
end
puts reversed_name
=> "racsO"
Other more interesting real life examples:
Filter elements in an array:
days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"]
# Select those which start with 'T'
days.select do | item |
item.match /^T/
end
=> ["Tuesday", "Thursday"]
Or sort by name length:
days.sort do |x,y|
x.size <=> y.size
end
=> ["Monday", "Friday", "Tuesday", "Thursday", "Wednesday"]
If the block is optional you can use:
yield(value) if block_given?
If is not optional, just invoke it.
You can try these examples on your computer with irb (Interactive Ruby Shell)
Here are all the examples in a copy/paste ready form:
class Person
def initialize( name )
#name = name
end
def do_with_name # expects a block
yield( #name ) # invoke the block and pass the `#name` attribute
end
end
person = Person.new("Oscar")
# Invoking the method passing a block to print the value
person.do_with_name do |value|
puts "Got: #{value}"
end
reversed_name = ""
# Invoke the method passing a different block
person.do_with_name do |value|
reversed_name = value.reverse
end
puts reversed_name
# Filter elements in an array:
days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"]
# Select those which start with 'T'
days.select do | item |
item.match /^T/
end
# Sort by name length:
days.sort do |x,y|
x.size <=> y.size
end
In Ruby, methods can check to see if they were called in such a way that a block was provided in addition to the normal arguments. Typically this is done using the block_given? method but you can also refer to the block as an explicit Proc by prefixing an ampersand (&) before the final argument name.
If a method is invoked with a block then the method can yield control to the block (call the block) with some arguments, if needed. Consider this example method that demonstrates:
def foo(x)
puts "OK: called as foo(#{x.inspect})"
yield("A gift from foo!") if block_given?
end
foo(10)
# OK: called as foo(10)
foo(123) {|y| puts "BLOCK: #{y} How nice =)"}
# OK: called as foo(123)
# BLOCK: A gift from foo! How nice =)
Or, using the special block argument syntax:
def bar(x, &block)
puts "OK: called as bar(#{x.inspect})"
block.call("A gift from bar!") if block
end
bar(10)
# OK: called as bar(10)
bar(123) {|y| puts "BLOCK: #{y} How nice =)"}
# OK: called as bar(123)
# BLOCK: A gift from bar! How nice =)
It's quite possible that someone will provide a truly detailed answer here, but I've always found this post from Robert Sosinski to be a great explanation of the subtleties between blocks, procs & lambdas.
I should add that I believe the post I'm linking to is specific to ruby 1.8. Some things have changed in ruby 1.9, such as block variables being local to the block. In 1.8, you'd get something like the following:
>> a = "Hello"
=> "Hello"
>> 1.times { |a| a = "Goodbye" }
=> 1
>> a
=> "Goodbye"
Whereas 1.9 would give you:
>> a = "Hello"
=> "Hello"
>> 1.times { |a| a = "Goodbye" }
=> 1
>> a
=> "Hello"
I don't have 1.9 on this machine so the above might have an error in it.
I found this article to be very useful. In particular, the following example:
#!/usr/bin/ruby
def test
yield 5
puts "You are in the method test"
yield 100
end
test {|i| puts "You are in the block #{i}"}
test do |i|
puts "You are in the block #{i}"
end
which should give the following output:
You are in the block 5
You are in the method test
You are in the block 100
You are in the block 5
You are in the method test
You are in the block 100
So essentially each time a call is made to yield ruby will run the code in the do block or inside {}. If a parameter is provided to yield then this will be provided as a parameter to the do block.
For me, this was the first time that I understood really what the do blocks were doing. It is basically a way for the function to give access to internal data structures, be that for iteration or for configuration of the function.
So when in rails you write the following:
respond_to do |format|
format.html { render template: "my/view", layout: 'my_layout' }
end
This will run the respond_to function which yields the do block with the (internal) format parameter. You then call the .html function on this internal variable which in turn yields the code block to run the render command. Note that .html will only yield if it is the file format requested. (technicality: these functions actually use block.call not yield as you can see from the source but the functionality is essentially the same, see this question for a discussion.) This provides a way for the function to perform some initialisation then take input from the calling code and then carry on processing if required.
Or put another way, it's similar to a function taking an anonymous function as an argument and then calling it in javascript.
I wanted to sort of add why you would do things that way to the already great answers.
No idea what language you are coming from, but assuming it is a static language, this sort of thing will look familiar. This is how you read a file in java
public class FileInput {
public static void main(String[] args) {
File file = new File("C:\\MyFile.txt");
FileInputStream fis = null;
BufferedInputStream bis = null;
DataInputStream dis = null;
try {
fis = new FileInputStream(file);
// Here BufferedInputStream is added for fast reading.
bis = new BufferedInputStream(fis);
dis = new DataInputStream(bis);
// dis.available() returns 0 if the file does not have more lines.
while (dis.available() != 0) {
// this statement reads the line from the file and print it to
// the console.
System.out.println(dis.readLine());
}
// dispose all the resources after using them.
fis.close();
bis.close();
dis.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Ignoring the whole stream chaining thing, The idea is this
Initialize resource that needs to be cleaned up
use resource
make sure to clean it up
This is how you do it in ruby
File.open("readfile.rb", "r") do |infile|
while (line = infile.gets)
puts "#{counter}: #{line}"
counter = counter + 1
end
end
Wildly different. Breaking this one down
tell the File class how to initialize the resource
tell the file class what to do with it
laugh at the java guys who are still typing ;-)
Here, instead of handling step one and two, you basically delegate that off into another class. As you can see, that dramatically brings down the amount of code you have to write, which makes things easier to read, and reduces the chances of things like memory leaks, or file locks not getting cleared.
Now, its not like you can't do something similar in java, in fact, people have been doing it for decades now. It's called the Strategy pattern. The difference is that without blocks, for something simple like the file example, strategy becomes overkill due to the amount of classes and methods you need to write. With blocks, it is such a simple and elegant way of doing it, that it doesn't make any sense NOT to structure your code that way.
This isn't the only way blocks are used, but the others (like the Builder pattern, which you can see in the form_for api in rails) are similar enough that it should be obvious whats going on once you wrap your head around this. When you see blocks, its usually safe to assume that the method call is what you want to do, and the block is describing how you want to do it.
In Ruby, a block is basically a chunk of code that can be passed to and executed by any method. Blocks are always used with methods, which usually feed data to them (as arguments).
Blocks are widely used in Ruby gems (including Rails) and in well-written Ruby code. They are not objects, hence cannot be assigned to variables.
Basic Syntax
A block is a piece of code enclosed by { } or do..end. By convention, the curly brace syntax should be used for single-line blocks and the do..end syntax should be used for multi-line blocks.
{ # This is a single line block }
do
# This is a multi-line block
end
Any method can receive a block as an implicit argument. A block is executed by the yield statement within a method. The basic syntax is:
def meditate
print "Today we will practice zazen"
yield # This indicates the method is expecting a block
end
# We are passing a block as an argument to the meditate method
meditate { print " for 40 minutes." }
Output:
Today we will practice zazen for 40 minutes.
When the yield statement is reached, the meditate method yields control to the block, the code within the block is executed and control is returned to the method, which resumes execution immediately following the yield statement.
When a method contains a yield statement, it is expecting to receive a block at calling time. If a block is not provided, an exception will be thrown once the yield statement is reached. We can make the block optional and avoid an exception from being raised:
def meditate
puts "Today we will practice zazen."
yield if block_given?
end meditate
Output:
Today we will practice zazen.
It is not possible to pass multiple blocks to a method. Each method can receive only one block.
See more at: http://www.zenruby.info/2016/04/introduction-to-blocks-in-ruby.html
I sometimes use "yield" like this:
def add_to_http
"http://#{yield}"
end
puts add_to_http { "www.example.com" }
puts add_to_http { "www.victim.com"}
Yields, to put it simply, allow the method you create to take and call blocks. The yield keyword specifically is the spot where the 'stuff' in the block will be performed.
There are two points I want to make about yield here. First, while a lot of answers here talk about different ways to pass a block to a method which uses yield, let's also talk about the control flow. This is especially relevant since you can yield MULTIPLE times to a block. Let's take a look at an example:
class Fruit
attr_accessor :kinds
def initialize
#kinds = %w(orange apple pear banana)
end
def each
puts 'inside each'
3.times { yield (#kinds.tap {|kinds| puts "selecting from #{kinds}"} ).sample }
end
end
f = Fruit.new
f.each do |kind|
puts 'inside block'
end
=> inside each
=> selecting from ["orange", "apple", "pear", "banana"]
=> inside block
=> selecting from ["orange", "apple", "pear", "banana"]
=> inside block
=> selecting from ["orange", "apple", "pear", "banana"]
=> inside block
When the each method is invoked, it executes line by line. Now when we get to the 3.times block, this block will be invoked 3 times. Each time it invokes yield. That yield is linked to the block associated with the method that called the each method. It is important to notice that each time yield is invoked, it returns control back to the block of the each method in client code. Once the block is finished executing, it returns back to the 3.times block. And this happens 3 times. So that block in client code is invoked on 3 separate occasions since yield is explicitly called 3 separate times.
My second point is about enum_for and yield. enum_for instantiates the Enumerator class and this Enumerator object also responds to yield.
class Fruit
def initialize
#kinds = %w(orange apple)
end
def kinds
yield #kinds.shift
yield #kinds.shift
end
end
f = Fruit.new
enum = f.to_enum(:kinds)
enum.next
=> "orange"
enum.next
=> "apple"
So notice every time we invoke kinds with the external iterator, it will invoke yield only once. The next time we call it, it will invoke the next yield and so on.
There's an interesting tidbit with regards to enum_for. The documentation online states the following:
enum_for(method = :each, *args) → enum
Creates a new Enumerator which will enumerate by calling method on obj, passing args if any.
str = "xyz"
enum = str.enum_for(:each_byte)
enum.each { |b| puts b }
# => 120
# => 121
# => 122
If you do not specify a symbol as an argument to enum_for, ruby will hook the enumerator to the receiver's each method. Some classes do not have an each method, like the String class.
str = "I like fruit"
enum = str.to_enum
enum.next
=> NoMethodError: undefined method `each' for "I like fruit":String
Thus, in the case of some objects invoked with enum_for, you must be explicit as to what your enumerating method will be.
Yield can be used as nameless block to return a value in the method. Consider the following code:
Def Up(anarg)
yield(anarg)
end
You can create a method "Up" which is assigned one argument. You can now assign this argument to yield which will call and execute an associated block. You can assign the block after the parameter list.
Up("Here is a string"){|x| x.reverse!; puts(x)}
When the Up method calls yield, with an argument, it is passed to the block variable to process the request.