Wednesday, July 16, 2025

Luarocks 與 Neovim

最近我遇到了一個挑戰:

> 如果使用 luarocks 安裝了 lua-cbor 的話,neovim 裡寫的 lua script 可以使用 lua-cbor 嗎?

答案是:預設不行,要做一些調整。

由於我的 luarocks 也是用 homebrew 去安裝的,而預設的 luarocks 它依賴的 lua interpreter 跟 neovim 預設依賴的 lua interpreter 不同。此外,neovim 的 package path 也很可能找不到 luarocks 的安裝 path 。

解法:
1. 重新安裝 luarocks ,下載 tar 包、重新編譯、安裝,讓它一定會依賴於 neovim 預設依賴的 lua interpreter ,即 luajit 
2. 設定 neovim 內部的 path ,使它可以讀得到 luarocks 的 module/library paths

< 重新安裝 luarocks 的指令 >
1. brew install luajit
2. wget https://luarocks.org/releases/luarocks-3.12.0.tar.gz
3. tar zxvf; cd luarocks-3.12.0
4. mkdir ~/.luarocks-luajit
5. ./configure \
  --with-lua=$(brew --prefix luajit) \
  --with-lua-include=$(brew --prefix luajit)/include/luajit-2.1 \
  --lua-suffix=jit \
  --prefix=$HOME/.luarocks-luajit
6. make && make install


注意:luarocks 的版本很重要,因為 luajit 有 65536 的限制。如果不是特定的 luarocks 版本,就會遇上這個錯誤:"Error: main function has more than 65536 constants"。參考連結


< 設定 neovim 內部的 path >
1. 在 lua 資料夾下生成一個檔案  luarocks.lua
2. 貼上以下的內容:

```
local function add_luarocks_paths()

  local luarocks_path = "/Users/laurencechen/.luarocks-luajit/share/lua/5.1/?.lua;/Users/laurencechen/.luarocks-luajit/share/lua/5.1/?/init.lua"

  local luarocks_cpath = "/Users/laurencechen/.luarocks-luajit/lib/lua/5.1/?.so"

  package.path = package.path .. ";" .. luarocks_path

  package.cpath = package.cpath .. ";" .. luarocks_cpath

end

return {add_luarocks_paths = add_luarocks_paths}

```
3. 在 init.vim 裡增加一行 lua require("luarocks").add_luarocks_paths()

Sunday, December 22, 2024

neil --- 用來輔助編輯 deps.edn 檔的 CLI 工具

 neil 主要就四種常用的用法:

  1. 尋找函式庫  neil dep search clojure
  2. 新增函式庫  neil dep add org.clojure/clojure
  3. 新增 Clojure 專案 neil new app dev.replware/myproject
  4. 新增一些好用的輔助功能,比方說:test, nrepl, build (用來生成 uberjar) 等。
    neil add nrepl

其中,第一與第二種用法算是最常用的,因為 Clojure 的開發過程之中,就是會不停地尋找、新增 library 。而第三種用法裡,常用的有三種形式:

  • neil new app [web application 專案名稱]
  • neil new lib [library 專案名稱]
  • neil new scratch [免洗專案名稱]

Tuesday, December 10, 2024

使用 compojure 時,需要特別注意的一個 helper - wrap-route

compojure 在決定接下來要使用哪一個 route 是單純地一個一個逐步比對,這個單純的作法多數時候沒有問題,但是一旦當某個 route 的 middleware 會有副作用的時候,這個作法就會出問題。

所幸,compojure 後來提供了一個 wrap-route 恰好可以處理這種情況。

HoneySQL 的 format

HoneySQL format 的 default 輸出是給 JDBC 處理的,所以當想讓它輸出給 SQL CLI 時,就要使用參數。

  • 如果是使用 1.0 版本, format 的時候需要直接輸出可以被 SQL CLI 接受的字串形式,要使用 (format sql-hmap :parameterizer :none)
  • 如果是使用 2.0 版本, format 的時候需要直接輸出可以被 SQL CLI 接受的字串形式,要使用 (format sql-hmap {:inline true})

Tuesday, December 3, 2024

如何使用 assert ,它跟 exception 不一樣喔!

參考連結

有兩個很常見的 Exception handling 不良風格

1. 濫用 :pre 和 :post 來做檢查,而不是使用 spec 或 malli

2. catch Throwable

```

(try

(assert false)

(catch Throwable e

"Barfoo"))

```

理由是類似的:

(1) Error => 程式有 bug ,設計時不考慮 catch 它。這種可以用 assert 。
(2) Exception => 程式沒有 bug 但是執行的時候遇到異常,設計時可以考慮 catch 它。

註:

(a) 用 : pre 和 : post 的話,會丟出 Error ,但是一般的格式錯誤是 Exception
(b) catch Throwable 的話,會 catch 到 Error ,但是我們只應該 catch Exception ,不應該 catch Error 。

Protocol 與 SPI (service provider interface)

最近才搞懂的東西:「在什麼樣的 context 之下,應該考慮使用 Protocol ?」

為什麼在用了 Clojure 這麼多年之後才搞懂,應該是因為我過去寫程式的時間裡,幾乎沒有在寫 Java 。

我在 Clojure 官方論壇找到了答案

答案是:Protocol 最適合用於做為 SPI (service provider interface)

protocol functions are better as SPI to hook in implementations than in API as functions consumers call directly. It is often helpful to wrap protocol methods with a normal function that can supply additional logic if needed around the call into the protocol.

如何畫出 Datomic 的 schema diagram ?

與 SQL 相比,Datomic 這方面的工具比較少。並沒有像 dbdiagram 這種工具

不過,有一個算是簡單好用的 workaround 方法:

1. 將 schema 搭配 chatGPT prompt 

> 將以下文本的 Datomic schema 的簡易表示法,轉換成 mermaid 的 ER diagram 表示法

2. 轉換完成之後,貼到 Mermaid Live Editor 來繪圖。

3. 做微調,因為有時候會判斷錯。