從閱讀代碼上考慮,if里的">"、"<"用哪個更容易看懂?
例一:
var test = 2;
//個人覺得有""的情況下,這樣寫更接近"1 &< test &< 5",更易讀 if(1 &< test test &< 5){ alert("Is true"); } else{ alert("Is false"); }例二:
var test = -2;
//個人覺得有"||"的情況下,把變數放在同一邊,可以更直觀看出一個是"小於"一個是"大於"
if(test &< -1 || test &> 5){
alert("Is true");
}
else{
alert("Is false");
}
這問題問得很像「if語句只有一行加不加{}」,我的目地不是引戰,只是單純的討論:
一般你會怎麼寫,為什麼?
沒有太大分別。如果要更清晰,可以把表達式以「提取方法(extract method)」重構,如 。對於複雜的條件,「提取方法」後可以用多個 的方式簡化。
描述中也提到 和 ,注意可使用 德摩根定律(De Morgans laws)互相轉換,我通常會盡量簡化成不需要括弧的形式。
另外,由於許多語言是短路求值(Short-circuit evaluation)的,子表達式放左面和放右面有時候是會影響性能的。編譯器在不知道運行時的統計時,是不能自動優化的。
給受測者先講半天某一女強人最近正在經歷創業以來最大的經濟危機,再讓受測者看這位女人面無表情(不笑不哭不怒……)的相片。多數受測者說看到了這位女性內心的焦慮。
給受測者先講半天某一弱女子剛剛經歷人生第一次失戀,再讓受測者看這位女人面無表情(不笑不哭不怒……)的相片。多數受測者說看到了這位女性內心的痛楚。
給受測者先講半天某一女子來月事了,再讓受測者看這位女人面無表情(不笑不哭不怒……)的相片。多數受測者說看到了這位女性這種表情,應該是在痛經。
沒錯,這叫 暗示。叫誘導。
你先給一程序員看「1 &< test &< 5」這個式子,再給他看 「if ( 1 &< test test &< 5)」。十個有八個覺得就應該這樣寫,因為看起來好自然。
但是,研究表明人類在表達時(沒有來源,不負責任),習慣於把具名對象作為語句中主語,放在前面;對應的,在閱讀時,如果將具名對象放在前頭,讀起來最自然。比如,我們說 「丁小明好想談一場戀愛」,而不是「一場戀愛好想被丁小明談」。
改變人的這種直覺反應挺難的。舉個例子:那些使用兩個等號(「==」)作相等判斷,並且整數值可以無痛轉換為布爾值的語言(典型如C, C++等 )中,總有人推薦我們這樣寫: 「 10 == a」;因為這樣寫可以避免不小心寫成「 a=10 」的問題。這些人還需不斷努力地耳提面命,因為人的習慣就是寫著「if (a == 10)」,腦海里想著 "如果 a 等於 10",而很少會這麼想「 如果 10 等於 a」,除非刻意訓練。
所以,寫成 test &> 1 test &< 5,也很好啊,因為同一個具名對象都作為主語,任何一個受過小學算術熏陶的人類都可以本能地進行抽公因式,然後在心裡讀出 「test 大於 1 並且 小於5」。你讓我看著 「1 &< test test &<5 」,你知道罪惡有多大嗎?每一次我掃描到這樣的代碼,兩個眼球先是一個鬥雞兩邊往中間擠,定焦到test,再是一個散光,往兩邊擴。然後 我那連286電腦都 比不過主頻的大腦,還要做一次複雜計算,計算結果居然還只是「test 被 1 小,並且小於5」。那天我將它讀出來給對面那位數學系出身的小夥子,他也傻了好嗎?
當然,我們這麼喜歡先找對象,可能也是受「面向對象」這「萬惡」的教育 荼毒太長時間了的後果而已,都面向對象了,只要不閉著雙眼,總是會習慣於用眼睛去找對象。
插個吐槽。只要不像某些人寫什麼「betweenNotEqual(1,5)」就好了(這不是面向對象,這是面向對象並且跪下了)。在這樣一個小表達式下什麼功夫全是扯。
居然還有 「betweenOrEqualRight( )」……確信 看到那個 「right」不是先想一下哪邊是右邊嗎?最可氣的是我像這樣的強迫症,突然又有些擔心這裡的「Right」會不會有其它意義,感覺如果不去看看這函數的實現,簡單地認定它一定是在表達右邊,簡直難受得不行不行的。
請注意 「betweenOrEqualRight()」 和 「IsValid()」的區別。後者(在當前層面)把細節放棄,明確表意這裡說的就是有效無效。 前者沒有放棄細節,只是把細節換成用英語表達。事實上並不是英語(或漢語,俄語)就比符號表達一定可讀,把一個原來表意明確的符號(&> &< &>= &<=),換成英語單詞( 甚至 是莫名其妙的組合)來表達實際會出現更彆扭的情況(當然,也會有更舒服的時候),以Right為例,來來來,今天 我們討論一下,當前兩個參數時,我們是 Left / Right表達,還是用 First/Second ? 我們把某些事寫成一個函數,至少要兼顧三個作用(排名不分前後,也不分左右):1 讓使用者可以復用代碼,2 對使用者可以隱藏實現細節,3 對一組操作提供一個有更好表意的代號(由方法名稱、入參列表、出參類型組成的函數原型)。betweenOrEqualRight() 這個方法於三者中沒起到什麼作用。
問題中的「test = 2」,沒有具體含義,所以看不出來。舉個有業務含義的。假設寫一個小學入學程序,需要判斷兒童有沒有到法定的入學年齡 。那我們在一個複雜的流程中,讀到 age.IsValid(),或者 IsValidAge(age); 都能明確知道這是判斷年齡,至於如何判斷的細節,已經被下放到該函數中。這有它意義:避免我們在瀏覽較粗(較高層面)的邏輯時,被代碼中一堆細節(底層)邏輯給打亂。,把是你把 "小於或等於( &<= )某個數」,原生計算符號的使用,硬要改為 Or + Eaual + Right 。真的很多人喜歡讀這樣的硬譯嗎?
======差點忘了正事。
誘導,或先入為主就是壞事嗎? 當然不是,別說誘導,就算洗腦也只是工具,可以用來做好事。團隊里幾個人事先 就約定 統一 的風格。這樣每個人在遇到這樣的枝節時都 能不 因為事先的規則洗腦而做到不假思索,從而可以把重點放到更難的地方,就是一個好的誘導。
很有意思的問題.
其實你可以這樣寫:
x : Int
x = 2
輸入: x between (2, 5)
返回: False : Bool
輸入: x between [2, 5)
返回: True : Bool
這裡的基本想法就是, 用方括弧和圓括弧來表達區間的左右開閉情況, 這是大家在中學很熟悉的表示區間的方法.
前提是你要用Idris這樣的現代編程語言, 它允許你自己定義語法:
syntax [x] between "(" [a] "," [b] ")" = a &< x x &< b
syntax [x] between "[" [a] "," [b] ")" = a &<= x x &< b
syntax [x] between "[" [a] "," [b] "]" = a &<= x x &<= b
syntax [x] between "(" [a] "," [b] "]" = a &< x x &<= b
關於Idris的介紹可以看我的另一個回答: 羅宸:怎麼評價 Idris 語言?
然後, 關於 @Milo Yip 大大提到的對於否定形式的處理, 可以通過定義 "not between" 語法來解決:
syntax [x] not between "(" [a] "," [b] ")" = x &<= a || x &>= b
syntax [x] not between "[" [a] "," [b] ")" = x &< a || x &>= b
syntax [x] not between "[" [a] "," [b] "]" = x &< a || x &> b
syntax [x] not between "(" [a] "," [b] "]" = x &<= a || x &> b
個人覺得只要這樣:前面的條件常數小,後面的條件常數大,看起來是一個x軸上數字出現順序就足夠了。
代碼可閱讀性這事,沒必要太較真,這世界有很多比這更重要的事情。
另外,我寫代碼比較啰嗦,往往把和||兩側的條件也用圓括弧包起來,寧濫勿缺。
if((1 &< test) (test &< 5)) { ...}
我會寫成if(1 &< test test &< 5),並且大括弧換行
(1)一般在做比較的時候,習慣把變數寫前面,把常量寫後面,因為變數是你最關注的內容。
這樣書寫符合當前coder的思維。比如:
if(a &> 1 a &< 5)
if( a &< 1 || a &> 5 )
(2)即使if條件後面只有一個語句,也習慣把它包到大括弧裡面。比如
if(a==0){
console.log(a);
}
好處就是,後續如果有人往裡面再加語句,不會出bug。
比如:
if(a== 0)
console.log(a);
此時如果有人再添加代碼,而忘記補大括弧。
邏輯就錯了。
對於C++這個特例來說:
最大限度使用 &< 是最好的選擇
因為原則上,對於所有需要比較大小的對象,&< 是唯一一個必須重載的運算符,其他運算符都不是必須的。
所以不管是從閱讀上還是為了代碼的兼容性和可移植性,盡量只使用&<就可以了
你要是總是糾結這些細節,會有兩個後果:
1,你的代碼寫不完。
2,你的代碼別人看不懂。
如果這都能產生區別,說明你智力有問題。
犯下賤
(test &< -1 || test &> 5) ? alert("Is true") : alert("Is false");
這種情況怎麼寫都不是問題,因為邏輯上來說判斷太簡單,出問題的代碼是如下這種:
var type = $(#type).val();
var somevar;
if(type == 1)
{
somevar = "hi A",
}
else if(type == 2)
{
somevar = "my name is B",
}
else if(type == 3)
{
somevar = "this is C",
}
有100個type則出現100個if else的邏輯判斷,然而我讀過很多新手的代碼,不管是前台還是後台,基本上都是這樣寫。這裡稍微改進一下。
var type = $(#type).val();
var somevar;
switch (type) {
case 1:
somevar = "hi A",
break;
case 2:
somevar = "my name is B",
break;
case 3:
somevar = "this is C",
break;
default:
break;
}
現在好一點了,還是不夠理想。繼續改進。
var foo = new Array();
foo[1] = "hi A";
foo[2] = "my name is B";
foo[3] = "this is C";
var type = $(#type).val();
var somevar;
somevar = foo[type];
現在沒有邏輯判斷了,搞定!
這不就體現出python的優勢了么:if 1&
if(1 &< test test &< 5){
//如果1& .... } 我一般會寫注釋。。。
我偏向將
邏輯意義有「源」或「主動」含義的表達式,放在操作符左邊。「目標」或「被動」的放右邊。如下
If test &> 1 test &< 5test &> 1 test &< 5 不直觀,一眼看不出是什麼範圍
1 &< test test &< 5 兩個test太累贅
還是1 &< test &< 5最好,貌似語法不支持?
為了強迫症,還是這樣吧:
Range.open(1, 5).contains(test)
用Python,直接if -1&