Nedir &. (ve işareti nokta) Ruby'de ne demek?


Yanıtlar:


205

Buna Güvenli Gezinme İşleci denir. Ruby 2.3.0'da tanıtılan, nesneler üzerinde, Rails'teki yönteme benzer şekilde, nesnenin olabileceğinden nil(bir undefined method for nil:NilClasshatadan kaçınma ) endişe etmeden yöntemleri çağırmanıza izin verir .try

Böylece yazabilirsiniz

@person&.spouse&.name

onun yerine

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

Gönderen Dokümanlar :

my_object.my_method

Bu my_method mesajını my_object öğesine gönderir. Herhangi bir nesne bir alıcı olabilir, ancak yöntemin görünürlüğüne bağlı olarak bir mesaj göndermek NoMethodError değerini yükseltebilir.

Kullanabilirsin &. bir alıcı atamak için my_method çağrılmaz ve alıcı sıfır olduğunda sonuç sıfır olur. Bu durumda, my_method argümanları değerlendirilmez.


13
aslında, try!yöntem gibi çalışır , değiltry
Grzegorz

58

Not: @Santosh açık ve tam bir cevap verse de, biraz daha fazla arka plan eklemek ve örnek olmayan değişkenlerle kullanımı hakkında önemli bir not eklemek istiyorum .


Buna " Güvenli Navigasyon Operatörü " denir ( "İsteğe bağlı zincirleme operatörü", "Boş koşullu operatör" vb. ). Matz buna "yalnız operatör" diyor. Bu edilmiş Ruby 2.3 tanıtıldı . Bir nesneye yalnızca değilse bir yöntem gönderir nil.

Misal:

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

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

Yerel değişkenlerle "kenar durumu":

Yukarıdaki kodun örnek değişkenleri kullandığını lütfen unutmayın. Yerel değişkenlerle güvenli navigasyon operatörü kullanmak istiyorsanız, önce yerel değişkenlerinizin tanımlandığını kontrol etmeniz gerekir.

# `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

Bu sorunu gidermek için önce yerel değişkeninizin tanımlanmış olup olmadığını kontrol edin veya bunu nil olarak ayarlayın:

# 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

Yöntem arka planı

Rails, trytemelde aynısını yapan bir metoda sahiptir . Bir sendyöntemi çağırmak için dahili olarak yöntemi kullanır . Matz yavaş olduğunu ve bunun yerleşik bir dil özelliği olması gerektiğini öne sürdü .

Diğer birçok programlama dili benzer özelliklere sahiptir: Amaç C, Swift, Python, Scala, CoffeeScript, vb. Ancak, ortak bir sözdizimi ?.(soru noktası). Ancak bu sözdizimi Ruby tarafından benimsenemedi. Çünkü ?yöntem adlarında izin ve böylece edildi ?.sembol dizisi zaten geçerli Yakut kodudur. Örneğin:

2.even?.class  # => TrueClass

Bu yüzden Ruby topluluğu farklı bir sözdizimi bulmak zorunda kaldı. Bu aktif bir tartışma oldu ve farklı seçenekler (kabul edildi .?, ?, &&vb.) İşte bazı düşüncelerin listesi:

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

# And finally
u&.profile&.thumbnails

Sözdizimini seçerken, geliştiriciler farklı uç durumlara baktı ve tartışma ilerlemek için oldukça yararlı. Operatörün tüm varyantlarını ve nüanslarını incelemek istiyorsanız, lütfen resmi Ruby sorun izleyicisi hakkındaki bu özellik tanıtım tartışmasına bakın .


Nedir '.?' ? Bu sözdiziminin kullanılmasının mümkün olmadığına karar verildiğini düşünüyorum. Sadece '&' alabilirim. çalışmak.
Keith Bennett

2
Tam olarak, yazdığım .?ve diğer seçenekler dikkate alındı, ancak &.seçildi! Yani, sadece &.işe yarayacak.
Özbekjon

Üzgünüm, sonuna kadar okumadım. Örnekler doğru sözdizimine sahip olsa daha iyi olmaz mıydı?
Keith Bennett

@ KeithBennett Ne demek istediğini anlıyorum. İlk örneğimde bir yazım hatası vardı. Haklısın, öyle olmalı &.ve olmamalı .?, benim hatam. Cevabım güncellendi. Söylediğin için teşekkürler!
Özbekjon

@Uzbekjon Edge vaka örneğinde hala bir yazım hatası var (seçenek 1): user.?profileolmalı user&.profile(sadece 1 karakterlik bir düzenleme olduğu için kendim düzenleyemedim!).
Yanis Vieilly

7

Dikkatli olmak! Güvenli navigasyon operatörü uygun olsa da, mantığınızı onunla değiştirmek için kendinizi kandırmak da kolay olabilir. Akış kontrolünde kullanımından kaçınılmasını öneriyorum. Misal:

str = nil

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

İlk örnekte, ifadenin yürütülmesine neden olan str.nil?döndürür trueve str.empty?asla çağrılmaz puts. Ancak ikinci örnekte , falsey olan str&.empty?döndürür nilve putsifade asla yürütülmez.


İlginçtir, teknik olarak ilk ifadenizde str.nil?doğru olsa da (dediğiniz gibi) bu str.empty?aslında hiç çağrılmayacak demektir ( ||operatör bu şekilde çalışır). İfadenizin geri kalanı doğrudur.
Ollie Bennett

1
Ah, iyi yakala. Bunu nasıl özlediğimden emin değilim. Yazımı düzeltirim. Teşekkür ederim!
Thomas Deranek

2
yanlış mantığı kullanmanın çok daha kolay olduğu doğrudur, ancak burada farklı şeyleri kontrol ediyorsunuz. ikinci satır if str && str.empty? nil değil || boş. güvenli navigasyon operatörü akış kontrolü için hala mükemmel bir şekilde geçerlidir puts "hello" unless str&.present?(sadece mevcut? yöntem için raylar)
Sampson Crowley

1

kotlin ve swift gibi sıfır kontrolü için kullanılır. Örneğin; Nesneli -> Swift ve Kotlin

model = car?.model

araba modelinde model değerini tanımlamamışsak, bu model sıfır (Swift) veya sıfır (Kotlin) olabilir. yakutta soru işareti yerine o işareti kullanırız

model = car&.model

ve işareti olmadan car.model kullanıyorsanız ve model sıfırsa sistem çalışmaya devam edemez.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.