方法内临时变量的惯用 ruby

发布于 2024-09-02 08:13:22 字数 943 浏览 3 评论 0原文

在方法中,我在计算其他变量时使用 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,我想删除它们,这样它们就不会被任何其他人使用方法中的代码。减少我的代码出错的机会。我不知道这个概念的名称——是“封装”吗?我能想到的最接近的概念是(警告:电视比喻的链接 - 不要在工作时访问) 契诃夫之枪YouHaveOutlivedYourUseativity

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

Within a method, I am using i and j as temporary variables while calculating other variables. What is an idiomatic way of getting rid of i and j once they are no longer needed? Should I use blocks for this purpose?

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

Background: I'd like to get rid of i and j once they are no longer needed so that they aren't used by any other code in the method. Gives my code less opportunity to be wrong. I don't know the name of the concept - is it "encapsulation"? The closest concepts I can think of are (warning: links to TV Tropes - do not visit while working) Chekhov'sGun or YouHaveOutlivedYourUsefulness.

Another alternative would be to put the code into their own methods, but that may detract from readability.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

无需解释 2024-09-09 08:13:22

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

What makes you think splitting the code up into multiple methods will hurt the readability? In my experience, splitting even small or medium sized pieces of code into multiple methods can greatly improve readability.

森林散布 2024-09-09 08:13:22

默认情况下,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()

参见 如何使块局部变量成为 ruby​​ 1.9 中的默认值?。您想要在块外使用的任何变量都应该事先定义(如last_核苷酸_位置)。

FM 是正确的,单独的方法可能更具可读性。

Ruby (like JS) doesn't create a new scope for each block by default (as C++, etc. do). However, in Ruby 1.9, you can try:

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()

See How to make block local variables the default in ruby 1.9?. Any variables that you want to be used outside the block should be defined before-hand (like last_nucleotide_position).

FM is right that a separate method may be more readable.

被翻牌 2024-09-09 08:13:22

我认为您正在寻找的术语是可变范围 - 换句话说,您正在寻找限制 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...

I think the term you are looking for is variable scope -- in other words, you are looking for ways to confine the scope of i and j. But you don't need to worry about that. The problem at hand calls for creating separate methods -- regardless of scope considerations.

This will improve readability, because it will allow the reader to grok the code starting at the high level and then boring in deeper only as needed. It will also improve testability because your small methods will do exactly one thing.

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...
壹場煙雨 2024-09-09 08:13:22

您正在寻找 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 /

You are looking for the Ruby equivalent of Lisp's let special operator. Ruby does not support it out of the box but you can hack it in very easily, and the resulting syntax is like this:

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

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

幸福不弃 2024-09-09 08:13:22

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

If all you want is to keep new variables from spilling out into the rest of your program, you can wrap your code in a block using 1.times. Any new variables you create inside the block will be destroyed when you close the block. Just keep in mind that any changes you make to pre-existing variables will remain once the block closes.

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'
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文