Code block passed to each works with brackets but not with 'do'-'end' (ruby)
puts mystring.gsub(art[0]).each do
art[1][rand(art[1].length) -1]
end
Here you called puts
without parens, the do ... end
refers to the puts
method, that does nothing with a block and prints mystring.gsub(art[0]).each
(with is a Enumerator
).
The { ... }
is called with the nearest method. Becomes ugly, but you can do it with do ... end
:
puts(mystring.gsub(art[0]).each do
art[1][rand(art[1].length) -1]
end)
Or, better, put the result in a variable and print the variable:
var = mystring.gsub(art[0]).each do
art[1][rand(art[1].length) -1]
end
puts var
Anyway, the each
don't changes the object, it just iterate and returns the object itself. You may be wanting the map
method, test it.
Passing block into a method - Ruby
The difference between do .. end
and curly braces is that the curly braces bind to the rightmost expression, while do .. end
bind to the leftmost one. Observe the following examples:
def first(x=nil)
puts " first(#{x.inspect}): #{block_given? ? "GOT BLOCK" : "no block"}"
"f"
end
def second(x=nil)
puts " second(#{x.inspect}): #{block_given? ? "GOT BLOCK" : "no block"}"
"s"
end
first second do |x| :ok end # second(nil): no block
# first("s"): GOT BLOCK
first second {|x| :ok } # second(nil): GOT BLOCK
# first("s"): no block
In the first case, the block made with do..end
will be bound to the first function (leftmost). In the second case the block made with curly brackets will be bound to the second function (rightmost).
Usually it's good idea to use parentheses if you have two functions and a block - just for readability and to avoid mistakes.
It's very easy to accidentally pass a block to puts
method, just as in your question.
Instance_eval does not work with do/end block, only with {}-blocks
It's because when you pass block with curly braces, it is passed to instance_eval
method. But if you pass it with do-end
, it's passed to puts
method, so instance_eval
doesn't get block and raises an error.
do..end vs curly braces for blocks in Ruby
The general convention is to use do..end for multi-line blocks and curly braces for single line blocks, but there is also a difference between the two that can be illustrated with this example:
puts [1,2,3].map{ |k| k+1 }
2
3
4
=> nil
puts [1,2,3].map do |k| k+1; end
#<Enumerator:0x0000010a06d140>
=> nil
This means that {} has a higher precedence than do..end, so keep that in mind when deciding what you want to use.
One more example to keep in mind while you develop your preferences.
The following code:
task :rake => pre_rake_task do
something
end
really means:
task(:rake => pre_rake_task){ something }
And this code:
task :rake => pre_rake_task {
something
}
really means:
task :rake => (pre_rake_task { something })
So to get the actual definition that you want, with curly braces, you must do:
task(:rake => pre_rake_task) {
something
}
Maybe using braces for parameters is something you want to do anyways, but if you don't it's probably best to use do..end in these cases to avoid this confusion.
Using do block vs braces {}
Ruby cookbook says bracket syntax has higher precedence order than do..end
Keep in mind that the bracket syntax
has a higher precedence than the
do..end syntax. Consider the following
two snippets of code:
1.upto 3 do |x|
puts x
end
1.upto 3 { |x| puts x }
# SyntaxError: compile error
Second example only works when parentheses is used, 1.upto(3) { |x| puts x }
Block not called in Ruby
Add parentheses to puts
puts(m do
x = 2
y = 3
x * y
end)
The output is 6.
Your code is equivalent to
puts(m) do
x = 2
y = 3
x * y
end
Ruby multiline block without do end
There is a subtle difference between the two syntaxes. { }
are higher precedence than do ... end
. Thus, the following will pass bar
and a block to method foo
:
foo bar do ... end
while the following will pass a block to bar
, and the result of that to foo
:
foo bar { ... }
So your examples will act the same. However, if you left the parentheses off:
> 3.upto 9 {
puts "Hi"
}
SyntaxError: compile error
(irb):82: syntax error, unexpected '{', expecting $end
3.upto 9 {
^
from (irb):82
from :0
> 3.upto 9 do
puts "Hi"
end
Hi
Hi
Hi
Hi
Hi
Hi
Hi
=> 3
So, { }
are more likely to catch you up if you leave off parentheses in Ruby, which is fairly common; for this reason, and because Ruby conditionals and other control constructs all use end
as a delimiter, people usually use do ... end
for multi-line code blocks that come at the end of a statement.
However, { }
is frequently use in places where do ... end
would be cumbersome, for instance, if you are chaining several methods together which take blocks. This can allow you to write short, one line little blocks which can be used as part of a method chain.
> [1,2,3].sort{|x,y| y<=>x}.map{|x| x+1}
=> [4, 3, 2]
Here's an example to illustrate this difference:
def foo arg
if block_given?
puts "Block given to foo"
yield arg
else
puts "No block given to foo"
arg
end
end
def bar
if block_given?
puts "Block given to bar"
yield "Yielded from bar"
else
puts "No block given to bar"
end
"Returned from bar"
end
irb(main):077:0> foo bar { |arg| puts arg }
Block given to bar
Yielded from bar
No block given to foo
=> "Returned from bar"
irb(main):078:0> foo bar do |arg| puts arg end
No block given to bar
Block given to foo
Returned from bar
=> nil
Related Topics
The Authorization Mechanism You Have Provided Is Not Supported. Please Use Aws4-Hmac-Sha256
Ruby: How to Post a File Via Http as Multipart/Form-Data
Avoiding Applescript Through Ruby: Rb-Appscript or Rubyosa
Block Definition - Difference Between Braces and Do-End
Create Two-Dimensional Arrays and Access Sub-Arrays in Ruby
Rails Update_Attributes Without Save
What Is the -≫ (Stab) Operator in Ruby
What Is the Ruby ≪=≫ (Spaceship) Operator
Difference Between Class Variables and Class Instance Variables
Ruby Operator Precedence Table
In Ruby on Rails, to Extend the String Class, Where Should the Code Be Put In
Gem Installation Error: You Have to Install Development Tools First (Windows)