Re: [問題] AND operator

作者: ducksteven (鴨七‧林新)   2014-05-03 03:25:37
※ 引述《nohaha (不是開玩笑的)》之銘言:
: 2.
: ruby有short-cicuiting的特性
: 當and前的值,為false,則無視and後的值為何,此式為false
: (e.g. if false and true => 結果為false)
: 當or前的值為true,則無視and後的值為何,此式為true
: (e.g. if true or false =>結果為true)
: 這部分我懂,但當拿fixnum來作運算時,我就不能理解結果了
short circuit 的特性在許多程式語言裡面都有,它甚至還有一個 Wikipedia 條目:
http://en.wikipedia.org/wiki/Short-circuit_evaluation
簡單來說就是,判定 if 條件的時候,若有多個條件,
則會依序執行條件,一但滿足,就不再判斷其他條件。
這種特性我猜是編譯器編出來的機器語言所致,
不過我先不探討編譯出來的結果(其實是我不熟…)。
這種特性其實最明顯會出現在「有副作用的 if condition」
什麼叫有副作用呢?
通常的 if condition 是判斷變數算出來的 boolean 值:
if @post.published? && @post.featured?
# ...
end
這種很常見的,單純一問一答的 method ,人畜無害。
但如果今天這個 method 剛好有副作用,會修改到其他變數的內容,
例如 Rails 裡面的 ActiveModel#valid?:
if @post.valid? && @comment.valid?
# response OK
else
# response @post.errors and @comment.errors
end
這時候如果 @post 跟 @comment 都不是 valid 的,就杯具了:
* 因為 short-circuit 特性,所以只有 @post.valid? 會被執行
* 然後 #valid? 其實會塞 errors 到該 instance 裡面
* if 判斷式因為第一個條件是 false 就跳到 else
* 於是,雖然 @comment 也不是 valid 但卻沒有被驗證到
* 最後在 else 裡面只能得到 @post.errors 而得不到 @comment.errors
以這個例子來說,要迴避 short-circuit 的話,
就要確保全部都有 call 到 #valid? ,那麼一個做法就是:
if [@post.valid?, @comment.valid?].all?
#...
做法是,先做一個 array ,裡面填這兩個 instance 的 #valid? 結果,
會是 true or false ,然後 call Array#all? 檢查全部都是 true
作者: NPFC10 (高容量電池哥)   2014-05-14 12:42:00
有用推

Links booklink

Contact Us: admin [ a t ] ucptt.com