Я наткнулся на эту строку рубинового кода. Что здесь означает &.
?
@object&.method
Я наткнулся на эту строку рубинового кода. Что здесь означает &.
?
@object&.method
Он называется «Оператор безопасной навигации». Представленный в Ruby 2.3.0, он позволяет вам вызывать методы для объектов, не беспокоясь о том, что объект может быть nil
(избегая ошибки undefined method for nil:NilClass
), подобно try
в Rails.
Итак, вы можете написать
@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
не оцениваются.
try!
, а не try
- person Grzegorz; 13.12.2016
Примечание. Несмотря на то, что @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
внутри для вызова метода. предложен Матц что он медленный и это должно быть встроенной функцией языка.
Многие другие языки программирования имеют аналогичную функцию: 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
При выборе синтаксиса разработчики учитывали различные пограничные случаи, и обсуждение весьма полезно. Если вы хотите ознакомиться со всеми вариантами и нюансами оператора, см. введение в эту функцию на официальном трекере проблем Ruby.
.?
и другие варианты, но был выбран &.
! Итак, только &.
будет работать.
- person Uzbekjon; 23.04.2016
&.
, а не .?
, мой плохой. Обновил мой ответ. Спасибо за внимание!
- person Uzbekjon; 24.04.2016
user.?profile
должно быть user&.profile
(сам не смог отредактировать, так как это всего лишь редактирование 1 символа!).
- person Yanis Vieilly; 30.08.2016
&.
с #try
ActiveSupport. Они делают разные вещи, и попытка объяснить оператор безопасной навигации с точки зрения #try
скорее сбивает с толку, чем помогает. :-)
- person Drenmi; 02.01.2017
Будьте осторожны! Хотя оператор безопасной навигации удобен, с его помощью также легко обмануть себя, заставив изменить свою логику. Я рекомендую избегать его использования в управлении потоком. Пример:
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
. Однако во втором примере str&.empty?
возвращает nil
, что является ложным, а оператор puts
никогда не выполняется.
str.nil?
верно (как вы говорите), что означает, что str.empty?
на самом деле вообще не будет вызываться (так работает оператор ||
). В остальном ваше утверждение верно.
- person Ollie Bennett; 27.06.2018
puts "hello" unless str&.present?
(метод rails только для настоящего?)
- person Sampson Crowley; 06.11.2018
он используется для нулевой проверки, например, в kotlin и swift Например; с Объектом -> Свифт и Котлин
model = car?.model
эта модель может быть нулевой (Swift) или нулевой (Kotlin), если мы не определили значение модели в классе автомобиля. мы используем этот амперсанд вместо вопросительного знака в ruby
model = car&.model
если использовать car.model без амперсанда и если модель равна нулю, система не может продолжать работу.