무엇을 &. 루비에서 (앰퍼샌드) 의미합니까?


답변:


205

안전 탐색 연산자라고합니다. Ruby 2.3.0에서 도입 된이 객체를 사용하면 Rails메소드 와 유사하게 오브젝트가 오류가 발생 nil하는 것을 걱정하지 않고 오브젝트에서 메소드를 호출 할 수 있습니다.undefined method for nil:NilClasstry .

그래서 당신은 쓸 수 있습니다

@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
Grzegorz

58

참고 : @Santosh가 명확하고 완전한 대답을했지만 배경 지식을 더 추가하고 인스턴스가 아닌 변수와의 사용에 관한 중요한 참고 사항을 추가하고 싶습니다 .


" 안전 내비게이션 연산자 "( "선택적 체인 연산자", "무조건 연산자"등 )라고합니다. Matz는 이것을 "고독한 연산자"라고 부릅니다. 그것은 한 루비 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에서 채택 할 수 없습니다. 때문에 ?메소드 이름 허용함으로써하고, ?.심볼 시퀀스는 이미 유효한 루비 코드이다. 예를 들면 다음과 같습니다.

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 문제 추적기에 대한 이 기능 소개 토론 을 참조하십시오 .


뭐가 '.?' ? 이 구문을 사용할 수 없다고 결정되었습니다. '&.'만받을 수 있습니다. 일하다.
Keith Bennett

2
내가 쓴대로 .?다른 옵션도 고려되었지만 &.선택되었습니다! 따라서 &.작동합니다.
우즈벡 존

죄송합니다. 끝까지 철저히 읽지 않았습니다. 그래도 예제에 올바른 구문이 있으면 더 좋지 않습니까?
Keith Bennett

@KeithBennett 무슨 말인지 알겠습니다. 첫 번째 예에서 오타가있었습니다. 당신이해야 옳다 &.아니라 .?나의 나쁜. 내 답변을 업데이트했습니다. 고마워요!
우즈 베키 온

@Uzbekjon Edge 사례 예 (옵션 1) 에는 여전히 오타 user.?profile가 있습니다 user&.profile.
Yanis Vieilly

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?반환 true되고 str.empty?호출되지 않으므로 puts명령문이 실행됩니다. 그러나 두 번째 예에서는 false를 str&.empty?반환 nil하고 puts명령문은 실행되지 않습니다.


흥미롭게도 첫 번째 진술에서 기술적으로 str.nil?사실이지만 ( str.empty?실제로 말하면) 실제로 호출되지는 않습니다 ( ||연산자가 작동하는 방식). 나머지 진술은 정확합니다.
Ollie Bennett

1
잘 잡아 내가 어떻게 그리웠는지 모르겠습니다. 내 게시물을 수정하겠습니다. 감사합니다!
Thomas Deranek

2
잘못된 논리를 사용하는 것이 훨씬 쉽지만 여기서 다른 것을 확인하고 있습니다. 두 번째 줄은 str && str.empty? 아니 || 빈. 안전한 항법 조작자는 여전히 흐름 제어에 사용하기에 완벽하게 유효합니다 puts "hello" unless str&.present?(현재? 방법에 대해서만 레일)
Sampson Crowley

1

예를 들어 kotlin 및 swift와 같이 무 검사에 사용되었습니다. 객체-> 스위프트와 코 틀린

model = car?.model

car 클래스에서 모델 값을 정의하지 않은 경우이 모델은 nil (Swift) 또는 null (Kotlin) 일 수 있습니다. 루비에서는 물음표 대신 앰퍼샌드를 사용합니다.

model = car&.model

앰퍼샌드없이 car.model을 사용하고 모델이 nil이면 시스템을 계속 실행할 수 없습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.