2010-01-04 44 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