Czy można wdrożyć? operator w Ruby?C# ?? operator w Ruby?
a = nil
b = 1
x = a ?? b # x should == 1
x = b ?? 2 # x should == 1
Czy można wdrożyć? operator w Ruby?C# ?? operator w Ruby?
a = nil
b = 1
x = a ?? b # x should == 1
x = b ?? 2 # x should == 1
Szukacie cesji warunkowej:
a ||= b # Assign if a isn't already set
i || Operator
a = b || 2 # Assign if b is assigned, or assign 2
x = b || 2
IT (??
C#) jest wywoływana przez operatora COALESCE.
To nie zadziała, z powodów, które przedstawiłem w mojej odpowiedzi. Spróbuj ustawić b na false w przykładzie. –
W Ruby, gdy zwarcie operatory logiczne (||
, &&
, and
i or
) nie zwracają true
lub false
, ale pierwszy operand, który decyduje o wyniku całego wyrażenia. To działa, ponieważ Ruby ma raczej proste pojęcie o prawdzie. Lub raczej ma raczej prosty pomysł fałszu: nil
jest fałszywy, i oczywiście false
jest fałszywy. Wszystko inne jest prawdziwe.
Tak, ponieważ ||
jest prawdziwe, gdy co najmniej jeden jej argumentów jest prawdziwy, a argumenty są obliczane od lewej do prawej, oznacza to, że a || b
powraca a
, gdy a
jest prawdą. Ale gdy a
jest fałszywe, wynik wyrażenia jest wyłącznie zależny od b
, a zatem zwracany jest b
.
Oznacza to, że ponieważ nil
jest fałszywe, można po prostu użyć ||
zamiast ??
dla podanych przykładów. (Istnieje również ładne a ||= b
operator, jakiego rodzaju prac, takich jak a || a = b
, ale nie całkiem.)
jednak, że tylko prace, bo nie używać wartości logicznych w swoich przykładach. Jeśli spodziewasz się radzić sobie z wartości logicznych, które nie będą działać:
b = false
x = b || 2 # x should be == false, but will be 2
W takim przypadku trzeba będzie używać #nil?
i wyrażenia warunkowe:
b = false
x = unless b.nil? then b else 2 end # x should be == 2
lub używając trójoperandowy warunkowy operator:
b = false
x = b.nil? ? 2 : b # x should be == false
Jeśli chcesz, możesz owinąć że w miłym sposobem:
class Object
def _? b = nil
return self
end
end
class NilClass
def _? b = nil
return yield if block_given?
return b
end
end
b = false
x = b._? { 2 } # x should be == false
x = b._? 2 # x should be == false
Ten uroczy fragment przedstawia Państwu przez polimorfizm, otwartych klas oraz fakt, że nil
jest rzeczywiście obiekt reprezentujący nicość (w przeciwieństwie do, powiedzmy, Jawa, gdzie null
jest właściwie nic).
'a || = b' to nie tyle" rodzaj "' a || a = b', ale dokładnie 'a = a || b'. Nie jest to przydział warunkowy, zadanie zawsze się powiedzie. – Theo
@ Theo: tak brzmi aktualny projekt specyfikacji języka Ruby ISO, ale jest to błędne. MRI, YARV, JRuby, Rubinius, XRuby, MacRuby, IronRuby, Ruby.NET, MagLev, SmallRuby, tinyrb, RubyGoLightly i wszystkie inne implementacje Ruby, jakie kiedykolwiek stworzono, implementują to jako warunkowe zadanie zwarcia. Ruby Programming Language (napisany wspólnie przez Matza), Programowanie Ruby i każda inna książka napisana przez Ruby dokumentuje to w ten sposób. Testy testowe RubySpec testują to w ten sposób. Kilka dyskusji na temat StackOverflow i dziesiątek dyskusji na temat ruby-talk mówi tak. Sam Matz tak mówi. –
Obligatoryjny link do artykułu Petera Coopera: http://www.rubyinside.com/what-rubys-double-pipe-or-equals-really-does-5488.html –
Istnieje klejnot coalesce, który jest tak blisko, jak to tylko możliwe.
nil || 5 # => 5
false || 5 # => 5 :(
false._? 5 # => false :)
To nie zadziała, z powodów opisanych w mojej odpowiedzi. Spróbuj ustawić wartość false w pierwszym przykładzie lub b na false w drugim przykładzie. –
Popraw, @ JörgWMittag. Strzeżcie się prawdy/falsey! –
Jestem także pewien, że nie można uzyskać błędu "nie można przypisać do zera" z ??. Ale możesz napisać metodę, jeśli nie na obiekcie i na NilClass, aby ocenić blok, jak w smalltalk – Rivenfall