#SQL

很多习惯C/Java/C# 等主流命令式语言的程序员很难理解函数式语言(Haskell,Clojure,F#)等,“不使用变量,不使用循环” 的理念。 是否理解为什么不用变量不用循环还是其次, 其实主要心理障碍是, “不用变量和循环,怎么能写代码?” 因为他们生活在充满变量充满循环的世界里。 其实,靠精心设计的函子,是很容易清晰地处理大部份场景的, 可能很多程序员一直没意识到,他们其实已经掌握了一门不用变量不用循环的语言: SQL: 依赖 select (相当于函数式的 map) where (相当于函数式的filter) order by (相当于函数式的sorted) …. 这组简单算子, 在不需要循环不需要变量的情况下,简单而干净地解决了很多问题,比如看看 select sum(a/b) from t where c=0 这种简单清晰的表达,用命令式: var result = 0; for(var i=0; i<t.length;i++){ if (t[i].c == 0){ result = result + t[i].a / t[i].b ; } } return result; 虽然代码不难写,但是核心逻辑 (挑选c是0的,把它们的 a/b 累加)被循环结构的噪音所干扰, 可读性远低于那句SQL 对应的函数式语言代码: F# 等 t |> List.filter (fun i -> i.c = 0) |> (fun i -> i.a / i.b) |> List.reduce (+) 虽然就这个简单例子,代码量并不比前面少, 但是数据流程非常清晰: filter 出c是0的, 然后 分别计算 a/b, 最后 + 起来。 简洁版的(clojure等) (reduce + (map #(/ (a %) (b %)) (filter #(= 0 (c %)) t)) 虽然简洁,但可读性欠佳。 SQL 靠极少的几个原语就可以实现各种复杂的数据操作, 那么手段比SQL 多十倍以上的函数式语言, 当然可以在不需要显式借助变量和循环的情况下完成几乎所有操作。 为什么说几乎? 因为确实存在极少数情况下, 很难组合出来,解决方案是: SQL: 游标 (其实就是指针+循环) F#: 虽然不推荐,还是可以变量和循环的 Clojure: 递归 Haskell: 硬杠, 我就不变量,麻烦就麻烦,终归可以曲线解决