Tuesday, February 16, 2021

從 leiningen 換成 deps.edn

Clojure 的官方出了自己的 build tool 。老實說,我一直都覺得,比起 leiningen 來得沒有那麼容易上手。經過一些調整之後,總算是覺得還可以啦,就是多學一些東西嘛。主要有幾個需要調整的地方:

  • 如何生成新的 project ?
  • 如何產生 nREPL 的開發環境?
  • 如何在專案的資料夾之下做 grep 

第一個問題,我的解法是安裝 clj-new 這個 alias 。裝完之後,就可以用下列的指令來生成 project

clojure -X:new :name myname/myapp ;; 生成專案
cd myapp
clojure -M -m myname.myapp      ;; 啟動


第二個問題,我的解法是設定對應的 alias 。網路上我找到相對完整豐富的範例是 practicalli/clojure-deps-edn

第三個問題:我用 ack-grep 時,常常都會掃瞄一堆暫存檔,妨礙我取得關鍵的資訊。於是,我設定了 ack-grep 的 config ,直接設定不搜尋這些暫存檔。我的 .ackrc 如下

# Tips:
# using ack to show only the clojure files for further processing
# ack -f --clojure
#

--ignore-dir=resources
--ignore-dir=.shadow-cljs
--ignore-dir=.cpcache

減少不必要的 reflection

在 Clojure 與 Java 的交界處,會產生大量的 reflection 。這種時候,可以用 type hints 來減少不必要的 reflection 。有效的作法是開啟一個特定的變數,將它的值改成 true ,然後 Clojure compiler 就會產生 reflection warning ,讓我們可以在開發的時候,很清楚明確地知道「哪些地方產生了 reflection」,於是就可以針對這些地方,去加上 type hint 。

這個重要的變數是 *warn-on-reflection*

Clojure 程式開發的依賴注入

Clojure 的世界裡,常用的依賴注入 (dependency injection) 手法主要有五種:

  • 依賴注入應用於函數 (function) 
  • 依賴注入應用於命名空間 (namespace)
  • 依賴注入應用於攔截器 (interceptor)
  • 依賴注入應用於網站處理器 (web handler)
  • 依賴注入應用於 Java program 的物件工廠 (factory)

這五種手法都頗為重要:

  • 第一種非常的常見,可以算是基本的要求。
  • 第二種,在使用 REPL workflow 就會應用到,Luminus 搭配的 mount 就是例子。
  • 第三種可以提高程式碼的可讀性、可預測性。因為條件限制 (constraints) 多,可讀性就變好。通常是將 web handler 之後會依賴的 component 透過攔截器注入到 request 裡。
  • 第四種可以看成是第三種的變型:在生成 web handler 的時候,注入依賴。
  • 第五種則應用於 Clojure/Java interoperation 。當要利用 java library 的時候,有時候既有的 java library 有預留可以注入的 factory pattern 。這時候,如果覺得既有的 java library 不夠好用,想做一些微調整的話,就可以考慮使用 Clojure 的關鍵字 reify 去生成新的 factory 來給 java library 使用。於是,Clojure wrapper 包覆的 java library 就是有微調過的版本。

Mac 筆電的快捷鍵整理

由於新工作的資安規定,硬碟要加密,我決定全心全意地來改用 Mac book 。研究了一陣子之後,發現還真的滿多需要且值得記憶的:

1. 截圖類

cmd + shift + 3 --- screen shot 
cmd + shift + 4 --- screen shot with area
cmd + shift + 5 --- screen record 

2. Finder 類

cmd + <up>     --- 往上移一層資料夾
cmd + [           --- 回到前一個資料夾  // 同時也適用於 browser 
cmd + alt + L   --- 到「下載資料夾」    // 同時也適用於 browser

3. 文字編輯器

cmd + <left>      --- 移動到行首
cmd + <right>    --- 移動到行尾
cmd + <up>       --- 移動到文章首
cmd + <down>   --- 移動到文章尾
cmd + shift + T   --- 切換 .txt 與 .rtf  (存檔的格式)
cmd + T             --- 顯示字型
cmd + shift + C   --- 顯示色碼
cmd + V                  --- 貼上 with formatting
cmd + alt + shift + V --- 貼上 without formatting


4. 一般應用程式

cmd + <Comma>    --- 偏好設定
cmd + Q                --- 關閉應用程式


5. 移動類

fn + <up>      ---   Page Up
fn + <down>  ---   Page Down 
fn + <left>     ---   Home
fn + <right>   ---   End


6. 其它

cmd + <Space>       ---  Spotlight search
cmd + shift + ESC   --- 強制關閉應用程式
cmd + ctrl + Q        --- lock screen

Sunday, November 22, 2020

研究 Monad 的心得

學了 Clojure 再來學 monad ,彷彿像是學了英文之後,再來學日文。表達同樣的語意,但是,用不同的方式表達。

一 monad 用來幹嘛?

monad 用來夾帶 context 。什麼是 context ?基本的概念有點像是,本來是「值」語意,加上了 context 就變成了「向量」語意。


二 如何定義 monad

定義一個 monad 就是要定義兩個 operations
(1) unit 或是稱之為 return 。
     這個 op 接受一個 value ,傳回被 monad 修飾過的 value (monadic value)

(2) combine 或是稱之為 bind。
     這個 op 接受一個 monadic value 和一個可以接受 ordinary value 的函數。這個 op 的作用就是組合上述兩者,於是就可以得到一個可以處理 monadic value 的新函數。

三 常見的 monad 所處理的問題集合

(1) Maybe monad 
     在 Clojure 的世界裡,比較好的 modeling 沒有值的方式,並不是使用 nil 。 而是使用 vector 或是 hashmap 來 modeling 真實世界的 entity 。如果用 vector 或是 hashmap 來做 modeling 的話,有時候根本不用判定 nil ,也就是 Maybe monad 完全不需要。

(2) List monad
     處理 mapcat 可以處理的問題。

(3) Reader monad
      處理 dependency injection 可以處理的問題。 

Sunday, November 15, 2020

Some database-related quotes

* SQLite is not a replacement for PostgreSQL. SQLite is a replacement for fopen()


* We should call NoSQL databases as Postmodern Databases because they are:

  1. Absence of objective truth

  2. Queries return opinions rather than facts


* NoSQL databases that only have weak consistency are enforcing a broadly applied premature optimization on the entire system.

Tuesday, September 8, 2020

npm lockfile

話說,長久以來,我在開發 nodejs/javascript 的 project ,都有一個問題。到底需不需要把 package-lock.json 放進 source control 裡?

總是感覺需要,但是常常 npm install 的時候,這個  package-lock.json  就會大改。讓我覺得也滿困擾的。總覺得好像並沒有真的 lock 下來?

原來我少學了一個指令 npm ci

npm ci 的功能,就是可以嚴格地依賴 package-lock.json 來安裝套件。如果真的需要昇級才能裝的話,它就會丟出 error 。