話說前一陣子 Scala 社群裡面在吵 Scala 這個程式語言到底簡單還是難,剛好這幾天在看程式時發現這個讓人想大喊 WTF,然後投稿到 The Daily WTF 上的 Java 函式,所以就拿它來開刀了……
原本的 Java Code 長的像下面這樣:
public static String isNotBig5(String ori) { char[] c = ori.toCharArray(); char[] c1 = new char[1]; StringBuffer sb = new StringBuffer(); for (int i = 0; i < c.length; i++) { c1[0] = c[i]; //System.out.println(c1[0]+" "+(int)c1[0]); // String onechar = ""; try { onechar = new String( (new String(c1)).getBytes() , "Big5"); } catch (Exception e) {} if (onechar.equals("?") && (int)c[i] != 63) { // ?是正常的"?" sb.append("&#"); sb.append(Integer.toString(c1[0])); sb.append(";"); } else { sb.append(c1[0]); } } return sb.toString(); }
因為這段程式實在醜到一種極緻,完全違反了所有 Clean Code 的原則。老實說,雖然一開始我知道這個函式是幹啥用的,但我完全無法理解這個函式到底在搞什麼鬼(看那和實際用途差了十萬八千里的函式名稱),而且它完全無法在非 Windows 的作業系統上正常使用。
最後,經過一連串的實驗,我終於看出來這個函式的演算法了(雖然他的實作是有問題的),其實這個演算法很簡單:
- 針對字串裡的每一個字元,做下列的動作
- 檢查該字元是不是在 Big5 可以表示的範圍內
- 如果是,將該字元轉成字串,例如從 'A' 到 "A"
- 如果不是,將該字元轉成 XML 字元參引,例如 '喆' 轉成 "喆"
- 將上一個步驟所產生出來的所有字串,合併(連接)成單一字串。
所以,為了讓我自己往後好過一點,我用 Scala 照著同樣的演算法幹出了另一個版本,不完美,但我想應該至少清楚很多,以下就是 Scala 版的程式碼,其中 normalizeString 的角色就是原來 Java 版中的 isNotBig5():
def normalizeString (string: String) = string.flatMap(escapeNonBig5Character _) def escapeNonBig5Character (character: Char): String = { def isNotBig5 (character: Char) = character.toString.getBytes("Big5")(0) == '?' && character != '?' // 不是 Big5 的字元就轉成字元參引 // 不然的話維持原樣 isNotBig5(character) match { case true => "&#%d;" format(character.toInt) case false => character.toString } } def example () { val content = "我是陶喆\n我是游鍚堃\n這是測試" println (normalizeString(content)) }
如果你是從 Java 背景來的,那麼注意下面幾點應該就可以看懂這個程式:
- String#flatMap 是指針對字串裡的每一個字元,套用一個將字元轉成字串的函式(所以這時計算出的東西會是 Array of String),最後再將此 Array of String 合併成單一的字串。
- escapeNonBig5Character 會將字元轉成字串,規則如下:
- 如果該字元可以在 Big5 編碼下表示,就維持原樣,但轉成字串,也就是從 'A' 轉到 "A"
- 如果該字元無法以 Big5 編碼表示,那就將該字元轉成 &#XXXXXX; 的格式
- 判斷字元可否在 Big5 下表示的方式:
- 例用 String#getBytes("BIG5") 將其轉碼到 BIG5,如果他本來不是問號,卻變成問號(解析不能),那這個字就無法用 Big5 來表示。
老實講,是很簡單的轉換法,但上面那段看了就想大喊 WTF 的程式碼,我不知道為什麼能把這麼簡單的東西給搞到這麼複雜……
至於 Scala 到底難不難?!我想這真的很難說,如果你不知道什麼是 High order function (flatMap 就是一個例子),那麼 Scala 版的可能你也覺得不好懂,但相對的,我每次在寫 Scala 時都覺得真的很像在『用嘴巴寫程式』。
仔細對照一下,你會發現 Scala 的版本非常接近於一開始我們針對 Java 版的演算法所做的『描述』,所以,快點把 Java 給丟了唄(大誤)!
BTW,到目前為止我最認同的是這句話:I don't expect a car to be built by average people, but by people with proper engineering background.
畢竟當你讓一個專業的來的時候,Scala 難不難根本不是個問題……
回響