Code Apprentice

nix 的一點筆記

· [Jack Shih]

年假期間想說來整理一下以前寫的 nix-darwin 的設定。然後想說這次不要用 nix flake,但是也還是不想用 channel。沒想到一改下去就開始折騰。親身體會為何 flake 的接受度為什麼會很高。當慢慢開始偏離預設的路徑得時候就痛苦。於是乎就回去看了 nix language。這邊就簡單記錄一下這次學習到的一點心得,希望有緣人不要走這個冤望路。

.nix 檔案只放一個 nix-expression

沒錯,一個檔案只是一個 expression,可以想像就是一個 one-liner 的概念。對這次我來說可以說是很重要的啟發,畢竟會想要在 .nix 裡面做很多事情,的確可以,只要你有辦法寫成 one-line 就可以。

everything is attribute set

有點誇大,不過 attribute set 在 nix 中是很重要的東西,attribute set 可當作像 python 的 dict 或是 js 的 object,只是在語法上常跟其他語言搞混。

{}:{}

這是一個 function,參數是一個 attribute set ,回傳一個 attribute set。後面的 {} 並不是 code block。

至於兩個參數的 function 是這樣 x:y:{} ,是 curry 式的寫法。

早點了解相關語法跟縮寫會輕鬆很多,行走江湖會看到各種混用。表面上會看起來很複雜,其實不然。例如

{
  a = {
    b = c;
  }
}
{
  a.b = c;
}

這兩個是一樣的。

nix repl 是好朋友

以前沒有使用 repl 的習慣,雖然現在也是還沒習慣(個人還是覺得體驗不是很好),但對於這種一定要跑一遍才知道內容的語言來說。還是得用。

nix path 是獨立的 type

對於 nix 來說 path 是獨立的型別。也就是說 path 跟 string path 是完全不同的東西,也不相容。轉換的方式是用 /. + "/path"./. + "/path" 這種寫法。(path + string = path)

nix 的生態系

nix 語言本身並不複雜。困難的是了解生態系的 convention。這次過程中常在問自己一個問題:「寫成這樣怎麼知道能不能動」。結果答案大概就是:「對,你不知道。」官方文件上大概就是這個意思。除非你看原始碼,不然你不太會知道任何一個 function 到底是要餵怎麼樣的東西。這時候就只能靠 convention 了。這點越早知道越不會覺得很混亂。因為就是這樣。越早接受越不會作無謂的掙扎。

resource

我不確定跟過去有差,但這次看的確是文件好了許多。

  • nix.dev tutorials

    我覺得這個教學比看操作手冊容易多了。如果如果不知道 nix 能做些什麼。可以從 First steps 開始看。這邊會帶你走過幾個常見的情境。如果決定要開始用了,建議先把 Nix language basics 章節讀過一遍,章節會帶你走過大部分的語法,並且有實際的範例。一開始大概讀到這邊就好了。與其到處 google 不如先了解基本語法到底在做什麼。

結語

有了這些知識之後,快速把這個部落格用的 flake 改成傳統 nix 的寫法。不過在跑 hugo 的時候發現 hugo 已經更新到 v0.141.0 然後跳了一堆錯誤訊息。要是用 flake 就不會有這些問題。但沒關係,看個一下 flake.lock 的 hash commit,速速把 nixpkgs pin 在同樣的版本,然後就可以弄到當年的版本 (v0.120.4)。再次執行,一切正常,順便驗證了 reproducibility 的重要性,文章先出,之後有時間再來搞升級。