代码之家  ›  专栏  ›  技术社区  ›  Andrew Grimm atk

方法中临时变量的惯用Ruby

  •  3
  • Andrew Grimm atk  · 技术社区  · 14 年前

    在一种方法中,我使用 i j 当计算其他变量时作为临时变量。惯用的摆脱方法是什么 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
    

    背景: 我想摆脱 J 一旦不再需要它们,这样方法中的任何其他代码都不会使用它们。给我的代码更少出错的机会。我不知道这个概念的名字——它是“封装”的吗?我能想到的最接近的概念是(警告:链接到电视节目-工作时不要访问) Chekhov'sGun YouHaveOutlivedYourUsefulness .

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

    5 回复  |  直到 12 年前
        1
  •  2
  •   Community kfsone    7 年前

    露比(如JS)默认不为每个块创建一个新的范围(如C++等)。但是,在Ruby1.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? . 任何变量 希望 要在块外使用,应在手前确定(如最后一个核苷酸位置)。

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

        2
  •  4
  •   dbyrne    14 年前

    什么使您认为将代码拆分为多个方法会损害可读性?根据我的经验,将甚至是中小型的代码分割成多个方法都可以极大地提高可读性。

        3
  •  2
  •   FMc TLP    14 年前

    我认为您要寻找的术语是可变范围——换句话说,您正在寻找限制 i j . 但你不必为此担心。手头的问题需要创建单独的方法——不管范围考虑如何。

    这将提高可读性,因为它将允许读者从高级别开始摸索代码,然后只在需要时进行更深入的研究。它还将提高可测试性,因为您的小方法可以 只有一件事 .

    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
  •  1
  •   horseyguy    14 年前

    您正在寻找与Lisp等价的Ruby let 特殊操作员。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
  •   morri    12 年前

    如果您只想防止新变量溢出到程序的其余部分,可以使用 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'