在Wiki里关于语法糖的一些历史介绍: 语法糖(Syntactic sugar),是由Peter J. Landin(和图灵一样的天才人物,是他最先发现了Lambda演算,由此而创立了函数式编程) 创造的一个词语,它意指那些没有给计算机语言添加新功能,而只是对人类来说更“甜蜜“的语法。语法糖往往给程序员提供了更实用的 编码方式,有益于更好的编码风格,更易读。不过其并没有给语言添加什么新东西。 Wiki里提到,在C语言里用a[n]表示*(a+n),用a[n][m]表示*(*(a+n)+m),也是语法糖。 实际上从面向过程到面向对象也是一种语法糖,C语言可以通过它的指针、类型转换,结构实现面向对象的编程风格, 但是C++更进一步的推广了这种风格,更好用了。 按照Wiki的理解,只有计算机硬件指令才不算语法糖,而其他一切利用编译器、汇编器将代码抽象,和自然语言更相近的手段都算语法糖。[/color] 现在我们介绍一下 Haskell 中的语法糖,[color=Blue]如有错误,请指正,改之[/color] [color=Red]1.缩进[/color] Haskell 也像 C 语言一样可以用大括号 '{}' 和分号 ';' 来构造程序块,但这样的写法会造成程序难以阅读,为了解决这个问题,Haskell 引入了缩进。 注意 Haskell 的缩进不同于 Python 的缩进。在 Python 中,tab/空格 是语法,而 Haskell 中 tab/空格 是定义良好的语法糖,最终会被转换成 括号和分号的程序块的语法。 使用缩进的结构有:let,where,case of,... ? (其他的就不了解了)。在它们之后的缩进都可以转换为括号和分号的程序块语法。 [color=Red]2.Section[/color] Section 最终会转换为 lambda 函数 例:
(+2) => /x -> x+2 (*2) => /x -> x*2 [color=Red]3.List[/color] List 的最终转换如下: [1, 2, 3, 4] => 1:2:3:4:[] [1..10] => enumFromTo 1 10 [1, 3..10] => enumFromThenTo 1 3 10 [1..] => enumFrom 1 [1, 3..] => enumFromThen 1 3 Prelude> :t enumFrom enumFrom :: (Enum a) => a -> [a] Prelude> :t enumFromTo enumFromTo :: (Enum a) => a -> a -> [a] Prelude> :t enumFromThen enumFromThen :: (Enum a) => a -> a -> [a] Prelude> :t enumFromThenTo enumFromThenTo :: (Enum a) => a -> a -> a -> [a] Prelude> enumFromTo 1 10 [1,2,3,4,5,6,7,8,9,10] Prelude> enumFromThenTo 1 3 10 [1,3,5,7,9] Prelude> enumFrom 1 [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20 ... ... 15732,15733,15Interrupted. [color=Red]4.String[/color] String 其实也是 List,之所以把它单独列出来,是因为 String 和 List 写法不一样,前者被双引号括住,而后者被中括号括住 String 的最终转换如下: "abcde" => 'a':'b':'c':'d':'e':[] [color=Red]5.List Comprehensions[/color] List Comprehensions 等同于 map, filter 函数,但比 map, filter 函数更直观。 List Comprehensions 的最终转换如下: [ x | x <- aList , f x] => let ok x = if f x then [x] else [] in concatMap ok aList Prelude> :t concatMap concatMap :: (a -> ) -> [a] -> [color=Red]6.do[/color] do 也是语法糖,但现在对 monad 还完全不了解,就不说了,如果以后有机会再补上。 [color=Red]7. infix/prefix[/color] 引用 Magicloud 的原话 1 + 2 等效于 (+) 1 2 take 1 [0, 1] 等效于 1 `take` [0, 1] 无论是 (+) 还是 `take`,其目的是代码的美观易读,对于程序逻辑没有丝毫影响。 [color=Red]8. Named Fields[/color] data Configuration = Configuration { username :: String, localhost :: String, remotehost :: String, isguest :: Bool, issuperuser :: Bool, currentdir :: String, homedir :: String, timeconnected :: Integer } 会转换为: data Configuration = Configuration String -- user name String -- local host String -- remote host Bool -- is guest? Bool -- is super user? String -- current directory String -- home directory Integer -- time connected deriving (Eq, Show) username :: Configuration -> String userName (Configuration un _ _ _ _ _ _ _) = un localhost :: Configuration -> String localHost (Configuration _ lh _ _ _ _ _ _) = lh remoteHost :: Configuration -> String remoteHost (Configuration _ _ rh _ _ _ _ _) = rh isGuest :: Configuration -> Bool isGuest (Configuration _ _ _ ig _ _ _ _) = ig ... hostData (Configuration {localhost=lh,remotehost=rh}) = (lh,rh) 会转换为: hostData (Configuration _ lh rh _ _ _ _ _) = (lh,rh) initCFG' = Configuration { username="nobody", localhost="nowhere", remotehost="nowhere", isguest=False, issuperuser=False, currentdir="/", homedir="/", timeconnected=0 } 会转换为: initCFG = Configuration "nobody" "nowhere" "nowhere" False False "/" "/" 0 [color=Blue]还有几个没有提到的,请参阅回帖[/color][ 本帖最后由 izhier 于 2009-4-19 14:29 编辑 ]嗯,刚才看了楼上 roy_hu 兄的回复, 觉得用 guard 比用 if 更合适一些, 因为列表同时也是 MonadPlus 的实例。[ 本帖最后由 flw 于 2009-4-9 12:57 编辑 ]
http://www.chinaunix.net/jh/142/1425290.html