Early return from the block specified in instance_exec

I need to allow blocks to be defined and called within the class using instance_exec(via Rails 2.3.2). However, some of these blocks should return early in some situations, which causes me a problem.

My application was created using ruby ​​1.8.6, but I need to run it on 1.8.7. It seems that between the two versions the ability to return from lambda has been removed. The following works in 1.8.6, but throws a LocalJumpError(unexpected return) in 1.8.7:

class Foo
  def square(n)
    n ** 2
  end

  def cube(n)
    n ** 3
  end

  def call_block(*args, &block)
    instance_exec *args, &block
  end
end

block = lambda { |n|
  return square(n) if n < 5
  cube(n)
}

f = Foo.new
f.call_block(5, &block) # returns 125
f.call_block(3, &block) # returns 9 in 1.8.6, throws a LocalJumpError in 1.8.7

I decided that I could make it work in 1.8.7 if I replaced returnin my block with next, but it next square(n) if n < 5leads to nilin 1.8.6.

1.8.6, 1.8.7? , , , , .

, , , ruby ​​1.9?

: , , 1.8.6, 1.8.7, , 1.8.7 instance_exec C, 1.8.6 Rails. instance_exec 1.8.7 Rails, .

+3
1

. post.

class Foo

  def square(n)
    n ** 2
  end

  def cube(n)
    n ** 3
  end

  def call_block(*args, &block)
      instance_exec *args, &block
    end
end




def a
  block = lambda { | n|
    return square(n) if n < 5
    cube(n)
  }
 f = Foo.new 
puts f.call_block(3, &block) # returns 125
puts "Never makes it here in 1.8.7"
puts f.call_block(5, &block) # returns 9 in 1.8.6, returns nothing in 1.8.7
end

a

, puts.

procs lambdas 1.9. , .

, 3 vm. , 1.9 .

class Foo

  def square(n)
    n ** 2
  end

  def cube(n)
    n ** 3
  end

  def call_block(*args, &block)
    block.call(self, *args)
  end
end

block = lambda { |obj, n|
  return obj.square(n) if n < 5
  obj.cube(n)
}

f = Foo.new
puts f.call_block(5, &block) # returns 125
puts f.call_block(3, &block) # returns 9

post .

+1

Source: https://habr.com/ru/post/1722516/


All Articles