3

If I have a class:

class KlassWithSecret
  def initialize
    @secret = 99
  end
end

and run:

puts KlassWithSecret.new.instance_eval { @secret }

it prints 99, but if I run:

puts KlassWithSecret.new.instance_eval do
  @secret
end

It returns an error: `instance_eval': wrong number of arguments (0 for 1..3) (ArgumentError)

Why can't I use do/end blocks with instance_eval?

P.S. I am using Ruby 2.1.0.

Alexander Popov
  • 23,073
  • 19
  • 91
  • 130
  • 1
    works here (ruby 2.0.0) what ruby version are you using? – levinalex Jan 10 '14 at 11:15
  • Works for me (2.1.0). Are you sure the code you pasted causes an error? – Marek Lipka Jan 10 '14 at 11:16
  • Cann't reproduce in 1.9.3 . If you have some older/different Ruby implementation it may something to do with lower precedence of `do..end` block then `{..}` block. – David Unric Jan 10 '14 at 11:17
  • Sorry guys, I meant to use it with `puts`, my bad. Edited the question. – Alexander Popov Jan 10 '14 at 11:18
  • This is a duplicate of [Ruby Block Syntax Error](http://StackOverflow.Com/q/6854283/), [Code block passed to `each` works with brackets but not with `do`-`end` (ruby)](http://StackOverflow.Com/q/6718340/), [Block definition - difference between braces and `do`-`end` ?](http://StackOverflow.Com/q/6179442/), [Ruby multiline block without `do` `end`](http://StackOverflow.Com/q/3680097/), [Using `do` block vs brackets `{}`](http://StackOverflow.Com/q/2122380/), [What is the difference or value of these block coding styles in Ruby?](http://StackOverflow.Com/q/533008/), … – Jörg W Mittag Jan 11 '14 at 16:23
  • … [Ruby block and unparenthesized arguments](http://StackOverflow.Com/q/420147/), [Why aren't `do`/`end` and `{}` always equivalent?](http://StackOverflow.Com/q/7487664/), [Wierd imperfection in Ruby blocks](http://StackOverflow.Com/q/7620804/), [Passing block into a method - Ruby](http://StackOverflow.Com/q/10909496/), [`instance_eval` block not supplied?](http://StackOverflow.Com/q/12175788/), and [block syntax difference causes “`LocalJumpError: no block given (yield)`”](http://StackOverflow.Com/q/18623447/). – Jörg W Mittag Jan 11 '14 at 16:23

5 Answers5

5

Enclose expression supplied to puts in parenthesis because lower precedence of do..end block.

puts( KlassWithSecret.new.instance_eval do
  @secret
end )

or use brace syntax of block

puts KlassWithSecret.new.instance_eval {
  @secret
}
David Unric
  • 7,421
  • 1
  • 37
  • 65
4

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.

Marek Lipka
  • 50,622
  • 7
  • 87
  • 91
3

This is because when you use do..end block, the block is passed to the puts function. The code with do..end block will work if you write it like this

puts(KlassWithSecret.new.instance_eval do
  @secret
end)
vidang
  • 1,761
  • 13
  • 13
0
a = Proc.new {@secret}
puts KlassWithSecret.new.instance_eval(&a)
# 99

It say that puts KlaccWithSecret do @secret end does not gain the Proc(block).

chuang wang
  • 65
  • 1
  • 6
-1

Ruby(2.0.0) works. Code:

KlassWithSecret.new.instance_eval do
  p @secret
end
# 99

no problem.

chuang wang
  • 65
  • 1
  • 6