13

Ruby スプラット オペレーターについて自己紹介しました。そして、私はそれでたくさん遊んだ。しかし、以下の実験はどういうわけか私にそれについて二度考えさせました:)

langs = ["java", "csharp", "ruby", "haskell" ]
# => ["java", "csharp", "ruby", "haskell"]

 l1,*,l2 = *langs
# => ["java", "csharp", "ruby", "haskell"]
 l1
# => "java"
 l2
# => "haskell"

 l1,*,*,l2 = *langs
SyntaxError: (irb):27: syntax error, unexpected tSTAR
l1,*,*,l2 = *langs
      ^
    from /usr/bin/irb:12:in `<main>'

はい、*(splat)同じ引数リストで複数の演算子を使用したため、エラーは明らかです。

今、私はそれで遊んでみました。

l1,(*),(*),l2 = *langs
# => ["java", "csharp", "ruby", "haskell"]

ああ!ここで動作します。しかし、なぜそうなのか理解できませんでしたか?

 l1
# => "java"
 l2
# => "haskell"
 l1,(*),l2 = *langs
# => ["java", "csharp", "ruby", "haskell"]
 l1
# => "java"
 l2
# => "ruby"

上記の例から、配列要素のスキップを行っているようです。

質問は次のとおりです。

  • (a) 演算子 (*) は何と呼ばれていますか?

  • (b) 行で splat(*) を使用するl1,*,l2 = *langsと、すべての要素が消費されます - "csharp", "ruby"*技術的に何が消費されているかを確認する方法はありますか? 明らかに、私は使用してl1,*,l2 = *langsいない場合でも使用していl1,l*,l2 = *langsます。

4

3 に答える 3

9

これは、Matz によって説明されているように、並列代入で括弧がどのように機能するかによるものです。

例えば:

a, b, c = *[1, 2, 3]
a => 1
b => 2
c => 3

以下とは異なります。

a, (b, c) = *[1, 2, 3]
a => 1
b => 2
c => nil

基本的に、括弧は次のように述べています。このインデックスの右側の要素を括弧内の変数に割り当てます。したがって、 に 2 が割り当てられ、に割り当てるbインデックスには何も残っていません。同様に、(*) は、指定されたインデックスの要素のみを取得して配布します。1c

# the * is interpreted to mean 'take all remaining elements'
a, * = 1, 2, 3, 4

# the * is interpreted to mean 'take all remaining elements except
# the last element'
a, *, c = 1, 2, 3, 4

# incorrect syntax, can't splat more than once on all remaining
# elements
a, *, *, c = 1, 2, 3, 4

# the * is interpreted to mean 'take all elements at index 1'
a, (*), c = 1, 2, 3, 4

# the *'s are interpreted to mean 'take all elements at index 1,
# then again at index 2'
a, (*), (*), c = 1, 2, 3, 4

通常、*演算子は変数 as *foo- と組み合わせて使用​​されますが、そうでない場合は、その場所を保持し、変数であるかのように要素の割り当てを行います (基本的にそれらを破棄します)。

于 2013-02-18T20:28:22.143 に答える
6

(*)実際には、右側から1 つの要素を読み取るだけです。langs配列に 5 番目の要素がある次の例を考えてみましょう。

langs = ["java", "csharp", "ruby", "haskell", "python" ]

したがって、通常のスプラットを使用すると、次のようになります。

l1,*,l2 = langs

l1 #=> "java"
l2 #=> "python"

括弧を使用した例とは対照的に:

l1,(*),(*),l2 = langs

l1 #=> "java"
l2 #=> "haskell"

ただし、この場合、通常_は中間値を「なし」に割り当てるために使用することを言及したいと思います(最後の例と同等):

l1,_,_,l2 = langs

l1 #=> "java"
l2 #=> "haskell"

中間値の内側にあるものを確認したい場合は、次のように値を変数に明示的に割り当てることができます。

l1,*m,l2 = *langs

l1 #=> "java"
l2 #=> "python"
m  #=> ["csharp","ruby","haskell"]

または他の例で:

l1,(*m1),(*m2),l2 = langs

l1 #=> "java"
l2 #=> "haskell"
m1 #=> ["csharp"]
m2 #=> ["ruby"]

(*)ですから、これはそれ自体が演算子ではなく、実際には括弧内の感嘆符にすぎないため、独自の名前がないことを明確にすることを願っています.

于 2013-02-18T21:16:15.207 に答える
6

次のように考えてください: 括弧自体 (変数名またはスプラット演算子を無視) は、配列から単一の要素にアクセスしています。

l1,  (), (), l2 = *['a', 'b', 'c', 'd']
 ^   ^   ^   ^
'a' 'b' 'c' 'd'

配列の配列である場合は、括弧を使用する方が理にかなっています。

>> l1,(l3, l4),(l5, l6),l2 = *['a', ['b', 'c'], ['d', 'e'], 'f']
=> ["a", ["b", "c"], ["d", "e"], "f"]
>> l1
=> "a"
>> l3
=> "b"
>> l4
=> "c"
>> l5
=> "d"
>> l6
=> "e"
>> l2
=> "f"

したがって、(*) は配列から 1 つの要素を取得し、それをスプラットで代入しています。括弧自体は SINGLE 要素を取り、splat はその単一の要素を取り、それを「splats」します。

It's good to note that when performing multi-variable assignment from an array, the splat is not necessary on the array side:

>> a,b,c = ['a', 'b', 'c']
=> ["a", "b", "c"]
>> a
=> "a"
>> b
=> "b"
>> c
=> "c"
于 2013-02-18T20:49:54.503 に答える