Aşağıdaki kod Ruby'de ne anlama geliyor?
||=
Sözdiziminin herhangi bir anlamı veya nedeni var mı?
Aşağıdaki kod Ruby'de ne anlama geliyor?
||=
Sözdiziminin herhangi bir anlamı veya nedeni var mı?
Yanıtlar:
Bu soru Ruby posta listelerinde ve Ruby bloglarında o kadar sık tartışılmıştır ki şimdi Ruby posta listesinde tek amacı bu sorunu tartışan Ruby posta listesindeki diğer tüm konulara bağlantılar toplamaktır. .
İşte bir tane: || = (VEYA Eşit) konuların ve sayfaların kesin listesi
Eğer varsa gerçekten ne olup bittiğini bilmek istiyorum, bir "Kısaltılmış atamaları" Bölüm 11.4.2.3 bakmak Yakut Dili Taslak Şartname .
İlk yaklaşım olarak,
a ||= b
eşittir
a || a = b
ve eşdeğer değil
a = a || b
Ancak bu, özellikle atanımsızsa , sadece bir ilk yaklaşımdır . Anlambilim ayrıca, basit bir değişken atama, yöntem atama veya dizin oluşturma atama olmasına bağlı olarak da değişir:
a ||= b
a.c ||= b
a[c] ||= b
hepsi farklı muamele görüyor.
a = false; a ||= truegelmez değil Cevabınız bir "nüans" yapar dediğini yap.
a ||= ba, koşullu atama operatörü . Bunun anlamı , eğer atanımlanmamış veya Falsey , daha sonra değerlendirmek bve set asonuca . Eşdeğer olarak, adoğruluk için tanımlanır ve değerlendirilirse, o zaman bdeğerlendirilmez ve hiçbir ödev gerçekleşmez. Örneğin:
a ||= nil # => nil
a ||= 0 # => 0
a ||= 2 # => 0
foo = false # => false
foo ||= true # => true
foo ||= false # => true
Şaşırtıcı bir şekilde, diğer atama operatörlerine (örneğin +=) benzer, ancak farklı davranır.
a += b Çevirir a = a + ba ||= b kabaca çevirir a || a = bBunun için kestirme bir yöntemdir a || a = b. Fark ne zaman, yani atanımsız, a || a = bgetireceğini NameErroroysa a ||= bsetleri aiçin b. Bu ayrım, eğer önemsizdir ave bhem yerel hem de değişken olan, ancak, ya bir sınıfın bir alıcı / ayarlayıcı yöntemi ise anlamlıdır.
Daha fazla okuma:
h = Hash.new(0); h[1] ||= 2. Şimdi h[1] = h[1] || 2vs iki olası genişletmeleri düşünün h[1] || h[1] = 2. Her iki ifade de değerlendirilir, 0ancak ilki gereksiz yere karma boyutunu artırır. Belki de bu yüzden Matz ||=ikinci genişleme gibi davranmayı seçti . (Bunu başka bir cevapta bağlantılı olan konuların
a || a = bbir NameErrorif yükseltir a. a ||= bdeğil, başlangıç adurumuna getirir ve olarak ayarlar b. Bildiğim kadarıyla ikisi arasındaki tek fark bu. Benzer şekilde, farkında olduğum a = a || bve a ||= bfark ettiğim tek fark , eğer a=bir yöntem ise, ne adöndürürse döndürsün çağrılır . Ayrıca arasındaki tek fark a = b unless ave a ||= bBildiğim kadarıyla buna ifadesi değerlendirir olmasıdır nilyerine aeğer atruthy olduğunu. Yaklaşık bir sürü, ama oldukça eşdeğer bir şey yok ...
a ||= b
aşağıdaki satırların her biri ile aynı şekilde değerlendirir
a || a = b
a ? a : a = b
if a then a else a = b end
-
Diğer yandan,
a = a || b
aşağıdaki satırların her biri ile aynı şekilde değerlendirir
a = a ? a : b
if a then a = a else a = b end
-
Düzenleme: AJedi32 yorumlarda belirtildiği gibi, bu sadece şu geçerli tutar: 1. a tanımlı bir değişkendir. 2. Bir kez ve iki kez değerlendirmek, program veya sistem durumunda bir fark yaratmaz.
a, false / zero / undefined ise, iki kez değerlendirildiğini gösterir. (Ama Ruby'yi bilmiyorum, bu yüzden değerlerin tam olarak 'değerlendirilebileceğini' bilmiyorum ...)
a || a = b, a ? a : a = b, if a then a else a = b endVe if a then a = a else a = b endeğer bir hata atar atanımlanmamış, oysa a ||= bve a = a || bbunu yapmaz. Ayrıca a || a = b, a ? a : a = b, if a then a else a = b end, a = a ? a : b, ve if a then a = a else a = b enddeğerlendirmek aiki kez ne zaman atruthy olduğunu oysa a ||= bve a = a || byapma.
a || a = bdeğerlendirmez . aa
the end state will be equivalent after the whole line has been evaluatedBu mutlaka doğru olmayabilir. Ya abir yöntem? Yöntemlerin yan etkileri olabilir. Örneğin İle public; def a=n; @a=n; end; def a; @a+=1; end; self.a = 5, self.a ||= b6 geri döner, ancak self.a ? self.a : self.a = b7 geri döner.
Anlamına gelir veya eşittir. Soldaki değerin tanımlanıp tanımlanmadığını kontrol eder, sonra bunu kullanın. Değilse, sağdaki değeri kullanın. Modellerde örnek değişkenleri önbelleğe almak için Rails'te kullanabilirsiniz.
Oturum açmış olan kullanıcıyı getirmek için bir işlev oluşturduğumuz hızlı Rails tabanlı bir örnek:
class User > ActiveRecord::Base
def current_user
@current_user ||= User.find_by_id(session[:user_id])
end
end
@Current_user örnek değişkeninin ayarlanıp ayarlanmadığını kontrol eder. Öyleyse, döndürür ve böylece bir veritabanı çağrısını kaydeder. Ancak ayarlanmazsa, çağrıyı yaparız ve sonra @current_user değişkenini buna ayarlarız. Bu gerçekten basit bir önbellekleme tekniğidir, ancak aynı örnek değişkenini uygulamada birden çok kez aldığınızda mükemmeldir.
undefined, aynı zamanda falseve nilbununla ilgili olmayabilir ve current_userözellikle falsediğer durumlarda beklenmedik olabilir
x ||= y
dır-dir
x || x = y
"x yanlış veya tanımsızsa x, y'yi gösterir"
Kesin olarak a ||= b"belirtilen yöntemler atanımlanmamış ya da (falsy olan falseya da nil), set aiçin bve (diğer bir deyişle dönüş) değerlendirmek bbaşka bir şekilde değerlendirilmesi, a".
Diğerleri a ||= bbunu a || a = bveya ile eşdeğer diyerek bunu göstermeye çalışırlar a = a || b. Bu eşdeğerleri konsepti anlamak için yararlı olabilir, ancak bunlar farkında olabilir değil her koşulda doğru. Açıklamama izin ver:
a ||= b⇔a || a = b ?
Bu ifadelerin davranışı, atanımsız bir yerel değişken olduğunda farklılık gösterir . Bu durumda, a ||= bkoyacaktır aiçin b(ve değerlendirmek boysa) a || a = bolacak zam NameError: undefined local variable or method 'a' for main:Object.
a ||= b⇔a = a || b ?
Bu ifadelerin denklik çoğu zaman benzer bir denklik diğeri için de geçerlidir, çünkü varsayılır kısaltılmış atama operatörleri (yani +=, -=, *=, /=, %=, **=, &=, |=, ^=, <<=, ve >>=). Ancak, için ||=bu tabloların davranış olabilir zaman farklı a=bir nesne üzerinde bir yöntem olup, atruthy olup. Bu durumda, a ||= b(hiç değerlendirmek başka bir şey yapacak a, oysa) a = a || barayacak a=(a)üzerinde a'in alıcısı. Diğerlerinin de belirttiği gibi , bu arama yaparken a=abir karmaya anahtar eklemek gibi yan etkileri olduğunda fark yaratabilir .
a ||= b⇔a = b unless a ??
Bu ifadelerin davranışı, yalnızca doğru olduğunda ne değerlendirdiklerine agöre değişir. Bu durumda, a = b unless adeğerlendirilecek nil(yine ade beklendiği gibi ayarlanmayacak), oysa a ||= bdeğerlendirecektir a.
a ||= b⇔defined?(a) ? (a || a = b) : (a = b) ????
Hala hayır. Bu ifadeler, method_missingdoğruluk değeri döndüren bir yöntem bulunduğunda farklılık gösterebilir a. Bu durumda, a ||= bher ne kadar değerlendirecek method_missingdönüşleri ve sete denemez a, oysa defined?(a) ? (a || a = b) : (a = b)belirleyecektir aiçin bve değerlendirmek b.
Tamam, tamam, peki olduğu a ||= b eşdeğer? Bunu Ruby'de ifade etmenin bir yolu var mı?
Eh, ben inanıyorum, ben bir şey bakan değilim varsayarak a ||= b(... işlevsel eşdeğerdir Trampet )
begin
a = nil if false
a || a = b
end
Tut! Bundan önce noop olan ilk örnek değil mi? Pek iyi değil. Daha önce nasıl söylediğimi hatırlıyorum a ||= b, ancak tanımlanmamış bir yerel değişkenin a || a = bne zaman eşdeğer olmadığını a? Eh, a = nil if falseolmasını sağlar abu hat asla çalıştırılmaz halde tanımsız asla. Ruby'deki yerel değişkenler sözlüksel olarak kapsamlıdır.
(a=b unless a) or a
abir yöntemdir, bunun yerine (bir truthy değerini ilk kez dönerse) bir kez iki kez çağrılır. Örneğin, ageri dönmesi uzun sürerse veya yan etkileri varsa davranışların farklı olmasına neden olabilir .
biçina sol eksen hala rhs'sine değerini belirlemez, rhs'si hala lhs atamak değil veya başka bir deyişle?
a ||= bİnternette bulduğum en iyi cevap. Teşekkürler.
Varsayalım a = 2veb = 3
O zaman, yani değeri a ||= b ile sonuçlanacaktır .a2
Bir değerle sonuçlanmadığı zaman ortaya çıkan falseya da nil.. Bu yüzden değerini lldeğerlendirmez b.
Şimdi varsayalım a = nilve b = 3.
O a ||= bzaman 3yani b'değeri ile sonuçlanacaktır .
İlk olarak a'nın değerini, nilyani bunun değerini değerlendirmeyi denedi b.
Ror uygulamasında kullanılan en iyi örnek:
#To get currently logged in iser
def current_user
@current_user ||= User.find_by_id(session[:user_id])
end
# Make current_user available in templates as a helper
helper_method :current_user
Nerede, User.find_by_id(session[:user_id])yalnızca ve @current_userdaha önce başlatılmazsa tetiklenir .
a || = b
'A' içinde herhangi bir değerin olup olmadığını ve bu değeri kullanarak keep değerini değiştirmek istemediğinizi belirtir, aksi takdirde 'a' herhangi bir değere sahip değilse, 'b' değerini kullanın.
Basit kelimeler, eğer sol taraf boş değilse, mevcut değere, diğer taraf sağ taraftaki değere işaret eder.
a ||= b
eşittir
a || a = b
ve yok
a = a || b
varsayılan değeri olan bir karma tanımladığınız durum nedeniyle (karma tanımsız anahtarlar için varsayılan değeri döndürür)
a = Hash.new(true) #Which is: {}
Eğer kullanırsan:
a[10] ||= 10 #same as a[10] || a[10] = 10
a hala:
{}
ama böyle yazdığınızda:
a[10] = a[10] || 10
a olur:
{10 => true}
çünkü 10varsayılan olarak true değerine ayarlanmış olan anahtarın kendisinin değerini atamış olursunuz , öyleyse artık 10ödevi asla yerine getirmek yerine anahtar için tanımlanmıştır .
Lütfen ||=bunun bir atomik işlem olmadığını ve bu nedenle iş parçacığı için güvenli olmadığını unutmayın. Genel kural olarak, sınıf yöntemleri için kullanmayın.
Bu varsayılan atama gösterimi
örneğin: x || = 1
bu, x'in sıfır olup olmadığını kontrol eder. X gerçekten sıfır ise, o zaman bu yeni değeri atar (örneğimizde 1)
daha açık:
if x == nil
x = 1
son
nilda false, sadecenil
Eğer Xbir değere sahip DEĞİLDİR, bu değeri atanacaktır Y. Aksi takdirde, bu örnekte 5 olan orijinal değerini koruyacaktır:
irb(main):020:0> x = 5
=> 5
irb(main):021:0> y = 10
=> 10
irb(main):022:0> x ||= y
=> 5
# Now set x to nil.
irb(main):025:0> x = nil
=> nil
irb(main):026:0> x ||= y
=> 10
||= yalnızca left == nil (veya undefined veya false ise) sağa değer atar.
Bu yakut dili sözdizimi. Doğru cevap ruby-lang belgelerini kontrol etmektir. Diğer tüm açıklamalar gizlidir .
"ruby-lang dokümanlar Kısaltılmış Atama".
https://docs.ruby-lang.org/en/2.4.0/syntax/assignment_rdoc.html#label-Abbreviated+Assignment
b = 5
a ||= b
Bu şu anlama gelir:
a = a || b
hangisi olacak
a = nil || 5
en sonunda
a = 5
Şimdi tekrar ararsanız:
a ||= b
a = a || b
a = 5 || 5
a = 5
b = 6
Şimdi tekrar ararsanız:
a ||= b
a = a || b
a = 5 || 6
a = 5
Eğer gözlemlerseniz, bdeğer atanmaz a. ahala olacak 5.
Accesso'ları hızlandırmak için Ruby'de kullanılan bir Memoization Kalıbı.
def users
@users ||= User.all
end
Bu temelde şu anlama gelir:
@users = @users || User.all
Bu nedenle, bu yöntemi ilk çağırdığınızda veritabanına bir çağrı yapacaksınız.
Bu yönteme gelecekteki çağrılar @usersörnek değişkeninin değerini döndürecektir .
||= koşullu atama operatörü olarak adlandırılır.
Temel olarak çalışır, =ancak bir değişken önceden atanmışsa hiçbir şey yapmayacaktır.
İlk örnek:
x ||= 10
İkinci örnek:
x = 20
x ||= 10
İlk örnekte xşimdi 10'a eşittir. Ancak, ikinci örnekte xzaten 20 olarak tanımlanmıştır. Dolayısıyla koşullu işlecin bir etkisi yoktur. xkoştuktan sonra hala 20 yaşında x ||= 10.
a ||= bdemekle aynı a = b if a.nil?veyaa = b unless a
Ancak 3 seçeneğin tümü aynı performansı gösteriyor mu? Ruby 2.5.1 ile bu
1000000.times do
a ||= 1
a ||= 1
a ||= 1
a ||= 1
a ||= 1
a ||= 1
a ||= 1
a ||= 1
a ||= 1
a ||= 1
end
bilgisayarımda 0.099 saniye sürüyor
1000000.times do
a = 1 unless a
a = 1 unless a
a = 1 unless a
a = 1 unless a
a = 1 unless a
a = 1 unless a
a = 1 unless a
a = 1 unless a
a = 1 unless a
a = 1 unless a
end
0.062 Saniye sürer. Bu neredeyse% 40 daha hızlı.
ve sonra:
1000000.times do
a = 1 if a.nil?
a = 1 if a.nil?
a = 1 if a.nil?
a = 1 if a.nil?
a = 1 if a.nil?
a = 1 if a.nil?
a = 1 if a.nil?
a = 1 if a.nil?
a = 1 if a.nil?
a = 1 if a.nil?
end
0.166 Saniye sürüyor.
Bunun genel olarak önemli bir performans etkisi yaratacağı değil, ancak son optimizasyon bitine ihtiyacınız varsa, bu sonucu göz önünde bulundurun. Bu arada: a = 1 unless aacemi için okunması daha kolaydır, açıklayıcıdır.
Not 1: Atama satırını birden çok kez tekrar etmenin nedeni, ölçülen sürede döngü yükünü azaltmaktır.
Not 2: a=nilHer atamadan önce sıfır yaparsam sonuçlar benzerdir .