Ruby 一个区块如何检测到它在另一个区块内?

Ruby 一个区块如何检测到它在另一个区块内?,ruby,Ruby,这是我的代码: def block puts "from block" yield end block do puts "from command line" block do end end 以下是输出: from block from command line from block 我想知道第二个块是如何检测到它在另一个块(相同方法)内的 因此,输出将改为: from block 1 from command line from block 2 这可能吗?因为我

这是我的代码:

def block
  puts "from block"
  yield
end

block do
  puts "from command line"
  block do

  end
end
以下是输出:

from block
from command line
from block
我想知道第二个块是如何检测到它在另一个块(相同方法)内的

因此,输出将改为:

from block 1
from command line
from block 2
这可能吗?因为我希望嵌套块知道这一点,并运行一些额外的代码


谢谢

您可以使用实例变量跟踪块级别,在输入块时递增,在离开块时递减:

def block
  @block_level ||= 0
  @block_level += 1

  puts "from block #@block_level"

  yield

  @block_level -= 1
end

这个答案主要是为了好玩,我不建议你使用它

Ruby允许您以回溯的形式检查调用堆栈,但仅当引发异常时。因此,让我们提出一个例外,然后伸出我们的手臂,在它传递给其他人之前抓住它,然后:回溯是我们的

然后,您所需要做的就是在回溯(数组)中搜索对名为“block”的方法的任何方法调用,并对它们进行计数

class InspectBacktrace < Exception
end

def block
  raise InspectBacktrace
rescue InspectBacktrace => e
  level = e.backtrace.count { |x| x =~ /in `block'/ }
  puts "from block #{level}"
  yield
end

block do
  puts "from command line"
  block do
    puts "from command line"
    block do
      puts "from command line"
    end
  end
end
Edit:我后来遇到了
Kernel#caller
方法,它只提供当前的执行堆栈,没有任何麻烦。因此,只要在同一个文件中没有两个名为“block”的方法相互调用,以下代码可能是可以接受的:

def block
  level = caller.count { |x| x =~ /^#{ Regexp.escape(__FILE__) }:\d+:in `block'$/ } + 1
  puts "from block #{level}"
  yield
end

yjerem说,只要使用
确保
避免异常问题,它听起来像一个全局变量,而不是实例变量

def block
  begin
    $block_level ||= 0
    $block_level += 1
    puts "from block #{$block_level}"
    yield
  ensure
    $block_level -= 1
  end
end

有没有更好的方法来构造代码,这样就没有必要了?我喜欢你的创造性=)
def block
  begin
    $block_level ||= 0
    $block_level += 1
    puts "from block #{$block_level}"
    yield
  ensure
    $block_level -= 1
  end
end