&とは何ですか。(アンパサンドドット)はRubyで意味しますか?


回答:


205

これはセーフナビゲーションオペレーターと呼ばれます。Ruby 2.3.0で導入され、Railsメソッドと同様に、オブジェクトがnilundefined method for nil:NilClassエラーを回避して)存在することを心配せずにオブジェクトのメソッドを呼び出すことができます。try

だからあなたは書くことができます

@person&.spouse&.name

の代わりに

@person.spouse.name if @person && @person.spouse

ドキュメントから:

my_object.my_method

これにより、my_methodメッセージがmy_objectに送信されます。任意のオブジェクトをレシーバーにすることができますが、メソッドの可視性によっては、メッセージを送信するとNoMethodErrorが発生する場合があります。

&を使用できます。レシーバを指定する場合、my_methodは呼び出されず、レシーバがnilの場合、結果はnilになります。その場合、my_methodの引数は評価されません。


13
実際に、それは同じように動作try!する方法、ではないtry
グジェゴシ

58

注:@Santoshが明確かつ完全な回答を提供しましたが、背景を追加し、非インスタンス変数での使用に関する重要な注記を追加します。


これは「安全なナビゲーションオペレーター」と呼ばれます「オプションのチェーンオペレーター」、「ヌル条件演算子」など)。マッツはそれを「孤独なオペレーター」と呼んでいるようです。それはされたのRuby 2.3で導入されました。ない場合にのみ、メソッドをオブジェクトに送信しますnil

例:

# Call method `.profile` on `user` only if `user` is not `nil`
@user&.profile

# Equivalent to
unless @user.nil?
  @user.profile
end

ローカル変数を使用した「エッジケース」:

上記のコードはインスタンス変数を使用していることに注意してください。ローカル変数でセーフナビゲーション演算子を使用する場合は、ローカル変数が最初に定義されていることを確認する必要があります。

# `user` local variable is not defined previous
user&.profile

# This code would throw the following error:
NameError: undefined local variable or method `user' for main:Object

この問題を修正するには、ローカル変数が最初に定義されているかどうかを確認するか、nilに設定します。

# Option 1: Check the variable is defined
if defined?(user)
  user&.profile
end

# Option 2: Define your local variable. Example, set it to nil
user = nil
user&.profile     # Works and does not throw any errors

メソッドの背景

Railsにはtry基本的に同じことをするメソッドがあります。send内部でmethodを使用してメソッドを呼び出します。Matzはそれは遅いのでこれは組み込みの言語機能であるべきだと提案しました。

他の多くのプログラミング言語にも同様の機能があります。ObjectiveC、Swift、Python、Scala、CoffeeScriptなどです。ただし、一般的な構文は?.(疑問符)です。しかし、この構文はRubyでは採用できませんでした。そのため?、メソッド名で許可されたので、?.シンボル系列は、すでに有効なRubyのコードです。例えば:

2.even?.class  # => TrueClass

Rubyコミュニティが異なる構文を考え出す必要があったのはそのためです。これは、(活発な議論と異なるオプションを考慮した.??&&など)。ここにいくつかの考慮事項のリストがあります:

u.?profile.?thumbnails
u\profile\thumbnails
u!profile!thumbnails
u ? .profile ? .thumbnails
u && .profile && .thumbnails

# And finally
u&.profile&.thumbnails

構文を選択する際、開発者はさまざまなエッジケースを検討しましたが、この議論は非常に役に立ちます。オペレーターのすべてのバリアントとニュアンスを確認したい場合は、公式のRuby Issue Tracker に関するこの機能紹介のディスカッションを参照しください。


とは '。?' ?この文法は使えないと決めたと思います。「&」しか取得できません。仕事に。
キースベネット

2
正確には、私が書いたとおり、.?他のオプションが検討&.されましたが、選択されました!したがって、&.機能します。
ウズベクホン

ああ、すみません、最後までしっかり読んでいませんでした。例に正しい構文があればもっと良いのではないでしょうか?
キースベネット

@KeithBennett私はあなたが何を意味するかを参照してください。最初の例ではタイプミスがありました。あなたは正しい、それは私の悪いことであるに違い&.ない.?。私の答えを更新しました。ヘッドアップをありがとう!
ウズベクジョン

@Uzbekjon Edgeケースの例(オプション1)にはまだタイプミスがあります:するuser.?profile必要がありますuser&.profile(1文字の編集なので、自分で編集することはできません!)。
Yanis Vieilly 16

7

注意してください!安全なナビゲーションオペレーターは便利ですが、それを使用してロジックを変更するように騙すのも簡単です。フロー制御では使用しないことをお勧めします。例:

str = nil

puts "Hello" if str.nil? || str.empty?
# The above line is different than the below line
puts "Hello" if str&.empty?

最初の例では、str.nil?返すtruestr.empty?原因、と呼ばれることはありませんputs文が実行されます。ただし、2番目の例ではfalse str&.empty?が返さnilれ、putsステートメントは実行されません。


おもしろいですが、技術的には最初のステートメントstr.nil?で(あなたが言うように)trueですが、これはstr.empty?実際にはまったく呼び出されないことを意味します(つまり、||演算子はこのように動作します)。あなたのステートメントの残りの部分は正しいです。
Ollieベネット

1
ああ良いキャッチ。どうやってそれを逃したのかわかりません。投稿を修正します。ありがとうございました!
Thomas Deranek

2
間違ったロジックを使用する方がはるかに簡単であることは事実ですが、ここではさまざまなことを確認しています。2行目はif str && str.empty?と同等です。なしではない|| 空の。安全なナビゲーションオペレーターは、フロー制御puts "hello" unless str&.present?(現在のみレールですか?)に使用するのに完全に有効です
Sampson Crowley

1

KotlinやSwiftなどのnilチェックに使用されます。オブジェクト-> SwiftとKotlin

model = car?.model

車のクラスでモデル値を定義していない場合、このモデルはnil(Swift)またはnull(Kotlin)になります。ルビでは疑問符の代わりにアンパサンドを使用します

model = car&.model

アンパサンドなしでcar.modelを使用し、モデルがnilの場合、システムは実行を継続できません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.