Je li f()==5 i 5==f() isto?
Vi koji ste radili sa C-olikim jezicima setićete se jedne od konvencija pri pisanju if-uslova, da se vrednost sa kojom se promenljiva poredi piše sa leve strane znaka jednakosti, a promenljiva s desne (if 5 == i naspram uobičajenog if i == 5), zbog česte greške da se umesto dvostrukog znaka jednakosti stavi jednostruki, i odradi dodela vrednosti promenljivoj s leve strane, za šta se neki kompajleri ne bi bunili.
Samo naoko sličan problem javlja se ponekad i u Rubiju, ali ne zbog moguće greške u kucanju, već zbog prirode znaka jednakosti.
Analizirajući performanse jedne skripte profajlerom, primetio sam da se u listi pozivanih metoda neočekivano javlja metoda Time#<=> (koja opet, iz ko zna kog razloga, zove BasicObject#method_missing), iako sam bio prilično siguran da u kodu nemam poređenje objekata klase Time. Detaljnijim pregledom shvatio sam da se poziv te metode javlja pri proveri rezultata jedne metode, tj. u otprilike ovakvom koodu:
return if m() == false
(Pre nego što počnete prozivku zbog onog == false, reći ću da mi je bila potrebna eksplicitna provera za false, tj. nisam hteo da mi se uslov ispuni ako je rezultat metode nil, već samo false.)
Ispostavilo se da metoda m u nekim slučajevima vraća objekat klase Time. (Ok, još malo pravdanja: metoda m je zapravo metoda send na jednom objektu, i može zapravo pozivati različite metode, otud nije baš uvek izvesno šta će se naći kao vraćena klasa.) S obzirom da je u Rubiju manje-više sve ili objekat ili poziv metode nekog objekta, ono == je takođe poziv metode. U slučaju klase Time, ovaj operator ne vrši jednostavno poređenje referenci, pa se usled toga == kome je poziv metode sa leve strane različito ponaša od onog gde je sa leve strane npr. false. Ok, da ne grešim dušu, kood se ponaša isto, ali se izvršava različitom brzinom, što opet nekad može da bude bitno.
Da bi se izbegla nepotrebna logika vezana za konkretnu implementaciju metode == levog objekta, dovoljno je promeniti redosled:
return if false == m()
false je u Rubiju instanca klase FalseClass, i njeno == je isto što i obično Object#==, odnosno jednostavna provera jesu li u pitanju isti objekti.