2010-01-04 63 views
3

Ruby 1.9的給予定義都只是局部的一個塊,不收,較同名變量的外部範圍的變量的能力:如何使塊本地變量默認在紅寶石1.9?

x = 10 
proc { |;x| 
    x = 20 
}.call 
x #=> 10 

我想有這種行爲的默認一些我定義的塊 - 無需使用|; x,y,z |語法(注意分號)。

我不認爲Ruby本身允許這個,但是有可能破解這個功能嗎?

我目前有一個解決方案,但它非常難看,因爲它需要檢查哪些本地人在塊的末尾發生了變化,然後在塊之前將它們還原爲它們的值。如果您的解決方案需要指定哪些變量是塊地方在塊的開始即scope(:x) { x = 20 }

+0

請問爲什麼你喜歡你的語法Ruby 1.9的?你不喜歡的方法是什麼? – 2010-01-04 23:00:55

+0

@Myrddin,它在DSL上下文中使用,所以分號和塊變量語法看起來不合適。 – horseyguy 2010-01-05 02:18:46

回答

6

我是基於bobbywilson0的想法選擇的解決方案,我不介意。下面是它如何工作的:

x = 99 
y = 98 

scope { |x, y| 
    x = 20 
    y = 30 
} 

x #=> 99 
y #=> 98 

scope使用的變量在範圍開始創建,不關閉在外面定義的任何變量,這是有用的,他們也GC'd在結束範圍。

下面是執行:

def scope(&block) 
    num_required = block.arity >= 0 ? block.arity : ~block.arity 
    yield *([nil] * num_required) 
end 

該解決方案還採用默認值考慮使其在功能上等同於LISP一個let*

scope { |x = 20, z = (x * 3)| 
    x #=> 20 
    z #=> 60 
} 

,我在博客上這裏:http://banisterfiend.wordpress.com/2010/01/07/controlling-object-scope-in-ruby-1-9/

4

x = 10; proc{ |x| x = 20 }.call(0)

+0

這是一個聰明的想法,但我不認爲我可以使用它爲我所想到的 – horseyguy 2010-01-05 02:21:28

+0

可否請您澄清問題 – bobbywilson0 2010-01-05 02:56:14

+0

看看這個,他談論做正是你想要的http:// www.daniel-azuma.com/blog/view/z3bqa0t01uugg1/implementing_dsl_blocks – bobbywilson0 2010-01-05 19:02:40