Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/EmptyTag/142.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby:在方法的上下文中运行代码_Ruby_Scope_Encapsulation - Fatal编程技术网

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

Ruby:在方法的上下文中运行代码,ruby,scope,encapsulation,Ruby,Scope,Encapsulation,在这个简单的示例中,begin/end“block”(实际上是一个表达式)创建了两个可在begin/end外部访问的变量(即xyz和zyx)。当然是这样:开始/结束是一个表达式 我想做的是以某种方式转换begin/end,这样我就可以在begin/end中分解代码并将其放置在其他地方,但仍然可以在某些方法中创建变量。我怀疑这样做需要缩小范围,但我不知道怎么做 我想我想做一些事情,比如: irb(main):001:0> def some_method irb(main):002:1>

在这个简单的示例中,begin/end“block”(实际上是一个表达式)创建了两个可在begin/end外部访问的变量(即xyz和zyx)。当然是这样:开始/结束是一个表达式

我想做的是以某种方式转换begin/end,这样我就可以在begin/end中分解代码并将其放置在其他地方,但仍然可以在某些方法中创建变量。我怀疑这样做需要缩小范围,但我不知道怎么做

我想我想做一些事情,比如:

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
问题:

  • 我想做的事有可能吗?我已经研究过使用绑定,但这似乎不起作用。至少对我来说不是
  • 有没有可能像C#include这样在Ruby代码中的某个特定点上按词法放置代码?我不认为加载要求可以做到这一点

  • 你不会想要的。您所要求的是一个副作用,它是一个函数,除了返回值和修改自己的对象和参数之外,还可以执行其他操作。更糟糕的是,它直接影响到调用者。副作用是可维护代码的祸根。他们打破封装,使你必须仔细研究每一个函数调用,并考虑其副作用。 通过返回值并将其分配给变量,可以更好地解决此问题,因此可以将其作为两个值返回,而不是两个值的数组

    def some_method
      create_variables_here
      puts xyz
      puts zyx
    end
    
    define_method :create_variables_here do
      xyz=5
      zyx=6
    end
    
    您看不到这一点,因为返回值通常是相关的,如果它们是相关的,则可能应该作为单个对象返回。若它们不相关,这可能是一个很好的迹象,表明函数正在做太多的事情

    这就完成了你想要的一切,它让调用者决定变量的调用。这很重要,因为A)调用方不需要记住一件事,B)它避免与函数中的变量冲突,C)使这些变量的来源变得明显


    作为反例,假设你有这个

    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
    
    …xyz和zyx是从哪里来的?!通常答案很简单:它们是未初始化的。但是对于您提出的功能,读者现在必须仔细检查每个
    do_blah
    函数调用是否存在可能设置
    xyz
    zyx
    的副作用

    (你可能会说,“但是任何使用副作用变量的函数都应该有一个像
    create_vars_for_blah
    ”这样的名称。是的,它们应该有,但你不能指望。与其相信每个人都会小心地使用它,不如一开始就不要有危险的特性。)

    更糟糕的是,如果它们都将
    xyz
    zyx
    设置为不同的值会怎么样?现在你有了冲突。调用者必须找到这一冲突,并执行一些复杂的操作,如:

    def some_method
        do_this
        do_that
        do_some_other_thing
    
        puts xyz
        puts zyx
    end
    
    这个想法的另一个问题是破坏局部变量。局部变量最重要的一个方面是,您可以一目了然地看到所有可能影响它的代码。比如说

    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
    
    在普通Ruby中,我们知道一个事实,它将打印10和20。有了这个功能,谁知道它们会是什么呢


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

    不,我不认为(使用局部变量)可以在我的头脑中完成,你能做的最好的事情就是大量分配变量
    xyz,zyx=创建变量
    。使代码更具可读性:)用例是什么?我的意思是,为什么不创建一个返回xyz,zyx值的方法呢?据我所知,你想要的方式只适用于全局变量。谢谢大家的回答。是的,你说得很对,在这种情况下,我只想要副作用。谢谢你们的回答。是的,你说得很对,在这种特殊情况下,我只想要副作用。从某种意义上说,知道我想做的事做不到是件好事。另一方面,它确实让我感到沮丧@haffla问我心目中的用例是什么。在我的代码中,在控制器之后的控制器中有一种特定的模式:验证参数,并在验证时同时构建其他数据结构。我想,我可以复制代码,但是,当然,代码不会枯燥。@RalphShnelvar如果您有问题,并且您试图通过将代码注入另一个函数的中间来解决它,那么您现在有两个问题。相反,您可能需要重新构造该函数。@RalphShnelvar;你问的不是真正的问题,而是你的解决方案,这不是一个好的解决方案。你应该发布一个关于你试图解决的真正问题的问题,我们可能会提供更好的解决方案。
    def some_method
        xyz = 10
        zyx = 20
    
        do_this
        do_that
        do_some_other_thing
    
        puts xyz
        puts zyx
    end