Archive for December, 2008

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脚本。

Update: 2009-08

由于g.cn页面修改,此脚本已过期,这里是目前在用的版本