Archive for December, 2008

胡先生豆腐

Tuesday, December 23rd, 2008

胡光煒哲嗣胡令暉在《回憶我的父親--胡小石》一文中寫道:“當今八十八歲的廚王胡長齡最近還在菜譜書上找到我父親解放前自己所創的一道菜的記載--‘胡先生豆腐’。”(《學苑奇峰--文史學家胡小石》,南京大學出版社2000年4月,ISBN 7-305-03512-2, 118頁)

不過,據2006年5月28日的《江南時報》8版所載,“胡先生豆腐”實為在胡光煒在南京馬祥興菜館就餐時常點的一道菜。此菜用雞肝、蝦仁、筍尖等鮮嫩配料烹制而成。因胡光煒大加贊譽,遂有此名。

[Haskell筆記]case語句

Tuesday, December 23rd, 2008

不知道你是否完成了練習13.2中的函數?是否覺得函數的定義過於冗長了?的確,這種情況用if/then來定義不是很方便。case語句更適合這類情況。

用case語句重寫的13.2中的函數:

myCase x =
    case x of
      0 -> 1
      1 -> 5
      2 -> 2
      _ -> -1

其中,_匹配所有情況。

case語句還有一種一段一段的寫法,比如,和上述函數等價的寫法:

myCase 0 = 1
myCase 1 = 5
myCase 2 = 2
myCase _ = -1

練習

14.1 如果將myCase改成以下定義,會出現什麽情況,為什麽?

myCase _ = -1
myCase 0 = 1
myCase 1 = 5
myCase 2 = 2

答案

13.1 輸入為5時,mySignum判斷5不小於0,故返回else if後面的語句,判斷5大於0, 故返回1。輸入為0時,mySignum判斷0不小於0,故返回else if後面的語句,判斷0不大於0, 故返回0。輸入為-1時,mySignum判斷-1小於0,故返回-1。

13.2

myCase x =
  if x == 0
    then 1
    else if x == 1
      then 5
      else if x == 2
        then 2
        else -1

git的index

Monday, December 22nd, 2008

一直是git commit -a的,也沒多想。嘗試hg後開始想為何git要這樣設計?發現自己忽略了git的一個重要的概念:index或者staging area。

兩篇談git的index的很有意思的文章:

Git's Killer Feature

Limbo: Why users are more error-prone with git than other VCSes

ssmtp連aliases也不支持

Sunday, December 21st, 2008

從這點上看,還是nullmailer方便些。雖然SMTP STARTTLS、 SMTP AUTH CRAM-MD5 之類的不支持。

cgit powerpc deb

Sunday, December 21st, 2008

Currently there is no cgit deb in the official Debian software repository. If you're using i386 or amd64, you get can the package from stbuehler's server. If you're using powerpc, I've complied a deb package for powerpc.

usermod is wired

Sunday, December 21st, 2008

-d, --home HOME_DIR
    The user's new login directory. If the -m option is given the contents of the current home directory will be moved to the new home directory, which is created if it does not already exist.

from the usermod manual.

I found out that usermod will not check whether the HOME_DIR exists or not. Thus if you run

usermod -d /home/not_created_yet_dir login

usermod won't create the new login directory.

Usermod will create it if you use the -m option, that is

usermod -d -m /home/not_created_yet_dir login

But the new home directory won't be created if the parent directory does not exist. For example,

usermod -d -m /home/not_exist_dir/new_home_dir login

This seems a bit wired, at least to me. Well, maybe I haven't understood the "do one thing" unix philosophy enough.

fcitx碼表設定

Sunday, December 21st, 2008

如果只用拼音,修改/.fcitx/config,“[输入法]”區塊下,設為“使用码表=0”。

如果只想用某些碼表(比如只用五筆,不用倉頡和二筆),修改/.fcitx/tables.conf,將不需要的碼表的部分去掉。

如果.fcitx沒有相應的配置文件,可以從/usr/share/fcitx/data/拷貝。(Debian下,其它OS可能使用不同目錄。)

[Haskell筆記]if語句

Sunday, December 21st, 2008

掌握了和Haskell文件打交道的方法後,我們可以處理一些比以前復雜的Haskell語句了。編程時常常需要對一個情況做出判斷,然後根據判斷的結果採取不同的做法。Haskell有if語句和case語句來對付。(從Haskell的觀點來說,根據判斷的結果返回不同的值。)

下面是一個判斷數字正負的函數:

mySignum x =
    if x < 0
      then -1
      else if x > 0
        then 1
        else 0

注意,縮進不要弄錯了。

把這個函數的定義寫進Varfun.hs中,載入Varfun.hs後就可以試驗這個函數了:

*Main> mySignum 5
1
*Main> mySignum 0
0
*Main> mySignum (5-10)
-1
*Main> mySignum (-1)
-1

對於if/then/else語句,Haskell會運算if語句後的條件,如果返回真值,就運算then語句,如果返回假值,則運算else語句。

練習

13.1 對於mySignum而言,輸入為5, 0, -1時,相應的輸出分別為1, 0, -1。試根據mySignum定義說明具體的運算過程。

13.2 寫一個函數,輸入分別為0、1、2時,相應的輸出為1、5、2,輸入為其它時,輸出-1。(Haskell中,==表示相等。)


答案

12.1 略。

[Haskell筆記]載入文件

Friday, December 19th, 2008

到目前為止,我們一直在GHCi下試驗Haskell代碼。這的確很方便,而且可以馬上看到結果。不過,有時候也有不方便的地方。比如,有時我們需要用到以前定義的函數,那就必須重新把這定義輸入一遍(GHCi不會記住以前的會話中的內容)。以後,隨著Haskell代碼的變長以及復雜化,所有代碼都在GHCi下輸入,會非常不方便。那麽,我們可不可把Haskell代碼保存在一個文件中呢?

當然可以。用你慣用的文本編輯器新建一個新文本文件,輸入以下內容:

areaCircle r = pi * r^2

注意:縮進在Haskell中是有意義的。小心有不必要的縮進出現。保存為Varfun.hs(hs為Haskell的縮寫)。

然後在GHCi下用load命令(:load或:l)載入文件:

Prelude> :load Varfun.hs
Compiling Main             ( Varfun.hs, interpreted )
Ok, modules loaded: Main.
*Main>

如果GHCi提示錯誤“Could not find module 'Varfun.hs'”,那可能是Varfun.hs文件不在當前目錄下。你可以使用:cd命令進入Varfun.hs所在的文件:

Prelude> :cd /home/weakish/haskell
Prelude> :load Varfun.hs
Compiling Main             ( Varfun.hs, interpreted )
Ok, modules loaded: Main.
*Main>

現在你可以直接使用Varfun.hs中定義的函數了:

*Main> areaCircle 5
78.53981633974483

注意我們直接在GHCi中輸入的Haskell代碼和寫在文件中的有些不一樣,最主要的,就是在文件中定義符號和函數時,不需要(不能)在前面加let了。

比如,直接在GHCi中輸入的

let x = 3
let y = 2
let areaCircle r = pi * r ^ 2

在文件中要寫成

x = 3
y = 2
area r = pi * r ^ 2

在文件中可以少寫很多let,方便多了。至於為何GHCi直接輸入時要加let,是有道理的,以後我們會解釋的。

這是最主要的區別。除此以外,還有兩個你不一定會遇到的小區別。

在GHCi中,如果我們直接輸入:

Prelude> let y = x * 2

GHCi會報錯:

<interactive>:1:8: Not in scope: `x'

因為GHCi不知道x代表什麽,或者說GHCi找不到x的定義。

所以,在GHCi中,我們必須先給出x的定義:

Prelude> let x = 3
Prelude> let y = x * 2

但是在文件中,兩種寫法都可以:

y = x * 2
x = 3
x = 3
y = x * 2

因為GHCi會閱讀整個文件。順序是無關緊要的。

在文件中,這樣的寫法是不能成立的:

r = 5
r = 2

r這個符號有兩個相矛盾的定義,顯然不能成立。(并不存在什麽後面的定義覆蓋前面的定義之類的規則,Haskell程序中語句的順序是無關緊要的。)

但在GHCi中,這樣是可以的:

Prelude> let r = 5
Prelude> r
5
Prelude> let r = 2
Prelude> r
2

為什麽可以?將在以後解釋。

練習:

12.1 將你在以前的練習中所寫的函數寫到一個文件中。在GHCi中載入這個文件,測試你寫的函數。


答案

11.1

  • 不成立。fst適用于tuple(pair),而[1,2]是list。
  • 不成立。cons只適用於list,不適用於tuple。
  • 不成立。cons只適用於list,不適用於tuple。
  • 成立。 你將得到[(2,4)]。
  • 不成立。(2,4)和(5,5)是兩個整數組成的tuple,而('a','b')是兩個字符組成的tuple,類型不同。
  • 成立。

查天气预报的简陋脚本

Friday, December 19th, 2008

利用g.cn查天气预报的简陋的Bash脚本。

#!/bin/bash

### Look up the wheather via g.cn.

city=$1

w3m -dump -no-cookie  http://www.google.cn/search?q=tq${city:-南京} |
sed -n "/°C/,/北京市专业气象台/p"|
awk '{if (NR%3==0){print $0} else {printf"%s ",$0}}' |
tr -s ' '

例子:

weakish@localhost:~$ tq 北京
5 / -7°C 当前:晴 北风3-4级
湿度:10% 今日 晴
 5 / -7°C 周六 白天小雪,夜间阴
 -1 / -8°C 周日 晴
 -7 / -13°C 周一 晴
 1 / -10°C 北京市专业气象台 12月19日17:00发布

默认查南京的。

weakish@localhost:~$ tq
14 / 5°C 当前:多云 西南风3-4级
湿度:45% 今日 多云
 14 / 5°C 周六 白天多云,夜间小雨
 13 / -1°C 周日 白天小雨,夜间多云
 7 / -7°C 周一 晴
 0 / -6°C 北京市专业气象台 12月19日17:00发布