Ruby:在方法的上下文中运行代码

时间:2017-02-17 16:44:57

标签: ruby scope encapsulation

irb(main):001:0> def some_method
irb(main):002:1>   begin
irb(main):003:2*     xyz = 5
irb(main):004:2>     zyx = 6
irb(main):005:2>   end
irb(main):006:1>   puts xyz
irb(main):007:1>   puts zyx
irb(main):008:1> end
=> :some_method
irb(main):009:0> 
irb(main):010:0* some_method
5
6
=> nil

在这个简单的例子中,开始/结束'块'(实际上是一个表达式)创建了两个在开始/结束之外可访问的变量(即xyz和zyx)。当然它确实如此:开头/结尾是一个表达。

我想要做的是以某种方式转换开始/结束,以便我可以在开始/结束时分解代码并将其放在别处,但仍然可以在some_method中创建变量。我怀疑这样做需要缩小范围,但我无法弄清楚如何做到这一点。

我想我想做点什么:

def some_method
  create_variables_here
  puts xyz
  puts zyx
end

define_method :create_variables_here do
  xyz=5
  zyx=6
end

问题:

  1. 我想做什么呢?我已经调查过使用绑定但这似乎不起作用。至少不适合我。
  2. 是否有可能像C #include一样,将代码放在Ruby代码中的特定位置?我不认为加载需要可以做到这一点。

1 个答案:

答案 0 :(得分:0)

你不想那样。你要求的是一个副作用,它是一个除了返回值以及修改自己的对象和参数之外的功能。更糟糕的是,它直接影响到来电者。副作用是可维护代码的祸根。它们打破了封装,让你必须仔细研究每个函数调用并考虑它的副作用。

通过返回值并将其赋值给变量可以更好地解决这个问题。 Ruby even supports returning multiple values,因此您可以将其作为两个值返回,而不是两个值的数组。

def create_variables_here
  xyz=5
  zyx=6

  return xyz, zyx
end

def some_method
  xyz, zyx = create_variables_here
  puts xyz
  puts zyx
end

你没有看到这么多,因为返回值通常是相关的,如果它们相关,它们应该作为单个对象返回。如果它们没有关系,这可能是一个很好的迹象,表明函数正在做太多事情。

它可以完成您想要的所有操作,并且可以让调用者决定调用哪些变量。这一点很重要,因为A)对于调用者来说是一个较少的东西,B)避免与函数中的变量发生冲突,C)使这些变量的来源变得明显。

作为一个反例,让我们说你有这个。

def some_method
    do_this
    do_that
    do_some_other_thing

    puts xyz
    puts zyx
end

... xyzzyx来自哪里?!通常答案很简单:它们是未初始化的。但是,根据您提出的功能,读者现在必须仔细检查每个do_blah函数调用是否存在可能设置xyzzyx的副作用。

(你可能会说,“但任何使用副作用变量的函数都应该有一个像create_vars_for_blah这样的名字。”是的,它们应该,但你不能指望它。最好没有首先是危险的特征,而不是相信每个人都会谨慎使用它。)

更糟糕的是,如果他们所有xyzzyx设置为不同的值会怎样?现在你发生了冲突。调用者必须找到这种冲突,并做一些令人费解的事情,如:

def some_method
    do_this
    this_xyz = xyz
    this_zyx = zyx

    do_that
    that_xyz = xyz
    that_zyx = zyx

    do_some_other_thing
    some_other_xyz = xyz
    some_other_zyx = zyx

    ...
end

这个想法的另一个问题是打破局部变量。局部变量最重要的一个方面是,您可以一目了然地查看可能影响它的所有代码。例如。

def some_method
    xyz = 10
    zyx = 20

    do_this
    do_that
    do_some_other_thing

    puts xyz
    puts zyx
end

在普通的Ruby中,我们知道将打印10和20的事实。有了这个提议的功能,谁知道它们会是什么?

您要求的是在函数末尾消失的全局变量。