【问题标题】:Idiomatic ruby for temporary variables within a method方法中临时变量的惯用红宝石
【发布时间】:2010-05-20 01:25:54
【问题描述】:

在一个方法中,我在计算其他变量时使用ij 作为临时变量。一旦不再需要 ij ,有什么惯用的方式摆脱它们?我应该为此目的使用块吗?

i = positions.first
while nucleotide_at_position(i-1) == nucleotide_at_position(i)
  raise "Assumption violated" if i == 1
  i -= 1
end
first_nucleotide_position = i
j = positions.last
while nucleotide_at_position(j+1) == nucleotide_at_position(j)
  raise "Assumption violated" if j == sequence.length
  j += 1
end
last_nucleotide_position = j

背景:我想在不再需要 ij 时删除它们,以便方法中的任何其他代码都不会使用它们。减少我的代码出错的机会。我不知道这个概念的名称——它是“封装”吗?我能想到的最接近的概念是(警告:TV Tropes 的链接 - 工作时不要访问)Chekhov'sGunYouHaveOutlivedYourUsefulness

另一种选择是将代码放入它们自己的方法中,但这可能会降低可读性。

【问题讨论】:

    标签: ruby scope encapsulation idioms


    【解决方案1】:

    是什么让您认为将代码拆分为多个方法会损害可读性?根据我的经验,即使将中小型代码片段拆分为多个方法,也可以大大提高可读性。

    【讨论】:

      【解决方案2】:

      Ruby(如 JS)默认情况下不会为每个块创建新范围(如 C++ 等)。但是,在 Ruby 1.9 中,您可以尝试:

      last_nucleotide_position = nil
      proc { |;i, j|
        i = positions.first
        while nucleotide_at_position(i-1) == nucleotide_at_position(i)
          raise "Assumption violated" if i == 1
          i -= 1
        end
        first_nucleotide_position = i
        j = positions.last
        while nucleotide_at_position(j+1) == nucleotide_at_position(j)
          raise "Assumption violated" if j == sequence.length
          j += 1
        end
        last_nucleotide_position = j
      }.call()
      

      How to make block local variables the default in ruby 1.9?。您希望在块外使用的任何变量都应事先定义(如 last_核苷酸位置)。

      FM 是对的,一个单独的方法可能更具可读性。

      【讨论】:

        【解决方案3】:

        我认为您正在寻找的术语是变量范围——换句话说,您正在寻找限制ij 范围的方法。但你不必担心这一点。手头的问题需要创建单独的方法——不管范围考虑。

        这将提高可读性,因为它允许读者从高层次开始深入了解代码,然后仅在需要时深入研究。它还将提高可测试性,因为您的小方法将只做一件事

        def calc_first_nucleotide_position(po)
          i = po.first
          while nucleotide_at_position(i-1) == nucleotide_at_position(i)
            raise "Assumption violated" if i == 1
            i -= 1
          end
          i
        end
        
        # etc...
        
        first_nucleotide_position = calc_first_nucleotide_position(positions)
        last_nucleotide_position  = calc_last_nucleotide_position(positions)
        
        # etc...
        

        【讨论】:

          【解决方案4】:

          您正在寻找与 Lisp 的 let 特殊运算符等效的 Ruby。 Ruby 不支持开箱即用,但你可以很容易地破解它,生成的语法是这样的:

          x = 10
          scope { |x|
              x = 30
          }
          puts x #=> 10
          

          见:http://banisterfiend.wordpress.com/2010/01/07/controlling-object-scope-in-ruby-1-9/

          【讨论】:

            【解决方案5】:

            如果您只想防止新变量溢出到程序的其余部分,您可以使用1.times 将代码包装在一个块中。当您关闭该块时,您在块内创建的任何新变量都将被销毁。请记住,一旦块关闭,您对预先存在的变量所做的任何更改都将保留。

            y = 20
            1.times do
              # put your code in here
              i = 1
              puts x = y # => 20, because y is available from outside the block
              y = 'new value' # We can change the value of y but our changes will 
                # propagate to outside the block since y was defined before we opened
                # the block.
            end
            
            defined? i # => nil, i is lost when you close the block
            defined? x # => nil, x is also local to the block
            puts y # => 'new value'
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2017-04-01
              • 1970-01-01
              • 2011-01-25
              • 2015-03-21
              • 1970-01-01
              • 2010-09-28
              • 2011-02-28
              相关资源
              最近更新 更多