2010-03-18 3 views
6

Это то, что я пытаюсь сделать:Ruby - Можно передать блок как параметр как фактический блок для другой функции?

def call_block(in_class = "String", &block) 
    instance = eval("#{in_class}.new") 
    puts "instance class: #{instance.class}" 
    instance.instance_eval{ block.call } 
end 


# --- TEST EXAMPLE --- 
# This outputs "class: String" every time 
"sdlkfj".instance_eval { puts "class: #{self.class}" } 

# This will only output "class: Object" every time 
# I'm trying to get this to output "class: String" though 
call_block("String") { puts "class: #{self.class}" } 

На линии, где он говорит: «instance.instance_eval {block.call}», я пытаюсь найти другой способ, чтобы сделать новую переменную экземпляра запустить экземпляр eval на блоке. Единственный способ, с помощью которого я могу заставить это сделать, - передать экземпляр_начального исходного блока, а не как переменную или что-то еще, а как настоящий блок, как в тестовом примере.

Любые советы?

ответ

8

Да. Вы можете передать блок к другому методу, предваряя переменный блок амперсанд как так:

def foo &blk 
    # now, blk is a variable bound to a block object 
    bar &blk 
end 

Причины ваш получают «класс: Object» является то, что Рубин использует лексическую область видимости. Это означает, что self в puts "class: #{self.class}" относится к main, контексту по умолчанию.

+0

Что ??? Это было так просто? Ахахах спасибо! Я застрял на этом один день! :) –

+0

термин для поиска был 'block parameters'; проще задним числом, хотя :) – Gishu