9

次のコードでは、引数エラーが発生します。

n = 15
(n % 4 == 0)..(n % 3 == 0)
# => bad value for range (ArgumentError)

これは、次のように評価されるためだと思います。

false..true

およびさまざまなタイプのクラスが range:TrueClassおよびで使用されますFalseClass。ただし、次のコードではエラーは発生しません。何故ですか?Enumerable#collectそれをキャッチしますか?

(11..20).collect { |i| (i % 4 == 0)..(i % 3 == 0) ? i : nil }
# => no error

後で追加: fcnが 15 を返す 場合、範囲の前半のみが評価されます

def fcn(x)
  puts x
  15
end

if  (fcn(1) % 4 == 0)..(fcn(2) % 3 == 0); end
# => 1

しかし、戻り値を 16 に変更すると、入力は

# => 1
# => 2

この場合、式は次のように評価されるため、奇妙です。

true..false

そして、そのような範囲は、以下のsawaの回答によると無効です。

次に、最初のケース ( defの戻り値 15 を使用) では、終了部分のない部分的な範囲しかありませんか? それはとても奇妙です:)

4

2 に答える 2

8

Rubyif start..finishではフリップフロップがあり、高速であいまいなスクリプトを記述するための特別な構文です。通常、ループで使用されます。

while input = gets
  puts "Processing #{input.inspect}" if input =~ /start/ .. input =~ /end/
end

最初の条件が true の場合、2 番目の条件が true と評価されるまで、連続して実行されるたびに条件全体が true と見なされます。上記のスクリプトで遊んで、アイデアを得ることができます。ここに私の入力と出力があります:

foo
start
Processing "start\n"
foo
Processing "foo\n"
bar
Processing "bar\n"
end
Processing "end\n"
foo
bar
start
Processing "start\n"

条件が開始されていない場合、Ruby は終了条件を評価しないことに注意してください。

これをループの外で使用することはあまり意味がありませんが、Ruby はそれを制限していません。

>> if nil..raise; :nothing_gonna_happen; end
=> nil
于 2012-09-12T13:09:41.427 に答える
0

まず、次の有効なリテラルと無効なリテラルに注意してください。

true..true # => valid
false..false # => valid
true..false # => invalid
false..true # => invalid

したがって、問題は、ループ条件に埋め込まれたときに評価されて有効になるfalse..true式がなぜ有効になるのかということになります。ドキュメントtrue..falseによると、ループ条件の範囲リテラルは実際には範囲を作成しません。むしろ、sed や awk に似た特別な意味があります。つまり、範囲の開始が真であるとループが開始され、範囲の終了が真であるとループが終了します。ここにいくつかの例があります

于 2012-09-12T11:48:01.583 に答える