私は 、Ruby の (心に訴える) Guide to Ruby、いくつかの他のガイド、Ruby スタイル ガイドを参照して、Rubyist の考え方を確認しました。しかし、末尾のアンダースコアを見るのはこれが初めてです。これらは何ですか?それらは有用ですか?もしそうなら、いつ使用し、splat オペレーターでどのように使用しますか?
(Ruby スタイルガイドのリンクは実際の例に固定されています)
私は 、Ruby の (心に訴える) Guide to Ruby、いくつかの他のガイド、Ruby スタイル ガイドを参照して、Rubyist の考え方を確認しました。しかし、末尾のアンダースコアを見るのはこれが初めてです。これらは何ですか?それらは有用ですか?もしそうなら、いつ使用し、splat オペレーターでどのように使用しますか?
(Ruby スタイルガイドのリンクは実際の例に固定されています)
有効な変数名は_
. のようなもの*_
は に似てい*x
ます。末尾のアンダースコア変数という用語は、実際には、割り当てステートメントの左側にあるコンマ区切りの一連の変数の最後の変数名を指します。たとえば、次のようになります。
a, b, _ = [1, 2, 3, 4]
splat 演算子には 2 つの用途があります。
どちらが発生するかは、splat 演算子が使用される コンテキストによって異なります。
以下は、Ruby スタイル ガイドで悪いとされている例です。
a, b, _ = *foo
この例の末尾のアンダースコア変数は不要です。最初の 2 つの要素をfoo
変数にa
代入し、次のようb
に記述できるためです。
a, b = *foo
アンダースコア変数は、「 I don't care about this variablea
」と言うために使用されるため、この例では、 andに代入するだけであれば必要ありませんb
。
演算子も必要ないため、例も悪いスタイルと見なされる可能性があり*
ます (クレジット: Cary Swoveland):
a, b = [1, 2, 3]
p a, b
--output:--
1
2
*
を右側で使用すると、次のような効果が得られます。
x, y, z = 10, [20, 30]
p x, y, z
--output:--
10
[20, 30]
nil
x, y, z = 10, *[20, 30]
p x, y, z
--output:--
10
20
30
したがって、スタイル ガイドの残りの例では*
、右側に が余分にあることに注意してください。
次の悪い例は次のとおりです。
a, _, _ = *foo
より具体的な例を次に示します。
a, _, _ = *[1, 2, 3, 4]
p a, _
puts "-" * 10
a, _ = *[1, 2, 3, 4]
p a, _
--output:--
1
3
----------
1
2
以下は、例の最初のセクションで割り当てがどのように機能するかを示しています。
a, _, _
^ ^ ^
| | |
[1, 2, 3, 4]
いずれにせよ、左側の 2 番目のアンダースコア変数a
を削除すると、同じものが割り当てられます。両方のアンダースコア変数を取り除くのはどうですか?
a = *[1, 2, 3, 4]
p a
--output:--
[1, 2, 3, 4]
いいえ。したがって、左側の最初のアンダースコア変数が必要なようです。ただし、末尾のアンダースコア変数を使用せずに同じ結果を得る別の構文があります。
a, = *[1, 2, 3, 4]
p a
--output:--
1
したがって、3 番目の悪い例:
a, *_ = *foo
次のように書くこともできます。
a, = *foo
これにより、末尾のアンダースコア変数を回避します。
最後に、スタイル ガイドは次の不可解なアドバイスを提供します。
割り当ての左側に定義された splat 変数があり、splat 変数がアンダースコアではない場合、末尾のアンダースコア変数が必要です。
次のようなことを指している可能性があると思います。
*a = *[1, 2, 3, 4]
p a
--output:--
[1, 2, 3, 4]
a
配列の最初の 3 つの要素を割り当てたい場合は、次のように記述する必要があります。
*a, _ = *[1, 2, 3, 4]
p a
--output:--
[1, 2, 3]
何らかの理由で、パーサーは以下を処理できません。
*a, = *[1, 2, 3, 4]
--output:--
*a, = *[1, 2, 3, 4]
^
1.rb:6: syntax error, unexpected '\n', expecting :: or '[' or '.'
良い例の 1 つを次に示します。
*a, b, _ = *foo
foo の最後の要素に 2 番目の要素を に割り当てたい場合は、末尾のアンダースコア変数が必要ですb
。
次の良い例は、少しややこしいです:
a, _b = *[1, 2, 3, 4]
a, _b, = *[1, 2, 3, 4]
それらを試してみましょう:
a, _b = *[1, 2, 3, 4]
p a, _b
puts "-" * 10
a, _b, = *[1, 2, 3, 4]
p a, _b
--output:--
1
2
----------
1
2
ruby では、 などの変数名は、または_b
という名前の変数と同じです。Erlang のような関数型言語では、変数とは異なる効果を持ちますが、Ruby ではそうではありません。_
b
_
_B
B
ところで、私はそのスタイルを学ぶのに 5 分も費やすつもりはありません。難解すぎます。
変数の先頭にアンダースコアを付ける_
ことに構文上の意味はなく、単なる慣例です (つまり、厳密な規則ではなく、コードを壊さずにいつでも壊すことができます)。
Ruby ではあまり使用されませんが、@
RuTeX プログラミングで関数の先頭にアットマークを追加するのに相当するものです。私の理解では、「下位」、「サブルーチン」、「コア」、「要素」などの概念を表すために使用されます。「複数化」の反対と考えることもできます。
例 1. 要素が単数形の名前で参照される配列の変数名を複数形にするのが一般的です。
items = [1, 2, 3]
items.each{|item| ...}
少し奇妙かもしれませんが、この慣行は、要素が単語以外の変数名で参照されている場合でも見られることがあります。
is = [1, 2, 3]
is.each{|i| ...}
ここで、配列にあらかじめ単数形の名前が付けられていて、それから要素名を区別したいとします。このような場合、要素名の先頭にアンダースコアを追加できます。
item = [1, 2, 3]
item.each{|_item| ...}
x = [1, 2, 3]
x.each{|_x| ...}
例 2. 別のメソッドを呼び出すメソッドがあり、後者はサブルーチンとしてのみ使用され、前者が行うことのほとんどを行うとします。そのような場合、後者の前にアンダースコアを追加できます。
def foo a, b
... # Do something just a bit here
_foo(a, b)
end
def _foo a, b
... # Do still a bit here
__foo(a, b)
end
def __foo a, b
... # Most of the job is done here
end
例 3. これは、ハードコードされた Ruby の一部であり、(1 つではなく) 2 つのアンダースコアを使用し、変数を (先頭に追加する代わりに) 囲んでいるという点で少し異なります。send
を呼び出すメソッドがあります__send__
。これは、がsend
別のものに再定義された場合でも__send__
使用できるようにするためです。