web-dev-qa-db-ja.com

&とは(アンパサンドドット)はRubyでの意味ですか?

Rubyコードのこの行に出会いました。これで&.はどういう意味ですか?

@object&.method
128
Sami

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

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

@person&.spouse&.name

の代わりに

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

Docs から:

my_object.my_method

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

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

161
Santhosh

注:@Santoshは明確で完全な回答を提供しましたが、背景を追加し、重要なメモを追加したいと思います非インスタンス変数での使用に関して。


Safe Navigation Operatoraka "Optional chaining operator"、 "Null-conditional operator"など)」と呼ばれます。マッツはそれを「孤独なオペレーター」と呼んでいるようです。 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メソッドを内部的に使用して、メソッドを呼び出します。 Matz推奨 遅いため、これは組み込みの言語機能である必要があります。

他の多くのプログラミング言語にも同様の機能があります:Objective C、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

構文を選択する際に、開発者はさまざまなEdgeのケースを検討し、議論は非常に有益です。演算子のすべてのバリエーションとニュアンスを確認したい場合は、公式Ruby課題トラッカーの この機能の紹介の説明 をご覧ください。

50
Uzbekjon

警戒してください!安全なナビゲーション演算子は便利ですが、それを使ってロジックを変更するように簡単に仕掛けることもできます。フロー制御での使用を避けることをお勧めします。例:

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?はtrueを返し、str.empty?は呼び出されないため、putsステートメントが実行されます。ただし、2番目の例では、str&.empty?はfalseであるnilを返し、putsステートメントは実行されません。

4
Thomas Deranek

kotlinやSwiftなどのnilチェックに使用されます。たとえば、オブジェクト-> SwiftおよびKotlinを使用

model = car?.model

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

model = car&.model

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

1
Umut ADALI