「逃離伊甸園」的結局

這篇漫畫非常非常有意思,但看完以後去 Google 了一下,發現大家對這部的結局罵翻天…但我個人是很滿意這個收尾,看完後欲罷不能趕緊找這作者的其他作品來看。

以下嚴重劇透,沒看過這部的請自主避難(但我非常推薦去讀一下這部),謝謝。

Read More

Lisp 中的 Symbol 與 Atom 差別在哪

初學 Lisp 時一直搞不懂 atom 跟 symbol 到底差在哪…不對那個時候連 symbol 是三小都搞不清楚。不過不才在下最近突然理解了 Lisp 裡面的 Symbol 跟 Atom 的意義,所以來解釋一下。

此篇假設你已經理解 Lisp 中的 cons 與 list

atom

atom 這個詞本來的意思就是指不可分割的東西、最小的單位,而 Lisp 中,只有 cons (或者用其他語言使用者比較可以理解的詞,叫做 list) 是可以分割的。例如最基本的 operator 之一。

Read More

搞懂 Lexical scoping 與 Dynamic scoping 的差異與用途

「阿母啊!我終於搞懂 Lexical Scoping 是啥啦~!」

Lexical scoping 與 Dynamic scoping 我以前一直嘗試想要弄懂但卻一直搞不懂,就算一時看懂了也不知這到底在幹麻或能幹麻所以每次看完就忘記(用不到的東西都記不住的啦),但最近因為 Lisp 寫得比較熟悉了,開始狂用 functional programming 的一些技巧後才終於了解其中奧妙,尤其是 lexical scoping 的好用之處,以及為什麼王垠會幹譙 dynamic scoping。希望這篇筆記可以幫助到一些跟我一樣搞不清楚狀況的人搞懂並記住兩者差異,尤其是如何善用 lexical scoping 的特性做一些神奇的功能。

  • 採用 lexical scoping 的語言:JavaScript、Scheme、Common Lisp
  • 採用 dynamic scoping 的語言:Emacs Lisp(預設行為)、Lisp Machine Lisp。

關於 Emacs Lisp 的 Lexical Scoping

Emacs Lisp 在 Emacs 24.3 開始也支援 lexical scoping 了,然而它預設仍然是 dynamic scoping。如果需要使用 lexical scoping。必須在你寫的 el 檔案的第一行內加入這句咒語「-*- lexical-binding: t; -*-」,例如:

1
;;; hexo.el --- Major mode & tools for Hexo -*- lexical-binding: t; -*-

這句咒語的作用技術上來說,Emacs 的設計是:當 lexical-binding 這個 buffer local 變數的值是 non-nil 時,該 el 檔案/buffer 就會以 lexical scoping 去 interpret Emacs Lisp。而-*- lexical-binding: t; -*-的作用其實就是自動在你打開這個檔案、或者 interpreter 在 eval 這個檔案時自動幫你(setq-local lexical-binding t)而已。

要記住用身體記住最快,所以如果可以建議以下整個自己開個 Emacs 跑一遍。以下會拿 Emacs Lisp 當例子,而不是大家常用的 Scheme 或 JS。為什麼呢~~~因為 Emacs Lisp 是目前我所知道最詭異的語言,竟然同時存在 dynamic scoping 跟 lexical scoping 的執行方式……總而言之,寫 Emacs Lisp 你可以自己決定要用哪一種 scoping,這種情況拿來實驗 scoping 是非常容易理解的,因為你可以拿一樣的 code 放在不同的 scoping 下實際執行比較看看。

下面會大量用到 lambda。如果你不熟悉 Lisp 裡的 lambda ,請先讀過這篇Lisp 裡面的 Lambda 到底是什麼?

先從例子來談談 Dynamic Scoping

我們先用 Emacs 建立一個新檔案 test.el,注意行首不要加上 -*- lexical-binding: t; -*- ,這樣該檔案寫的 Emacs Lisp 都會是預設的 dynamic scoping。

首先,我們先寫出兩個非常簡單、功能完全相同的函數(只是一個有名字、一個是 lambda 匿名函數),這兩個函數都一樣接受 1 個參數 x,並回傳 (* x 3) 的值:

1
2
3
4
5
6
;; 匿名函數
(lambda (x) (* x 3))
;; 有名字的函數
(defun triple (x)
(* x 3))

Read More

淺談 Lisp 裡面的 Lambda

我初學 Emacs Lisp 時,一直搞不懂 Lisp 裡面的 lambda 到底是什麼東西。多年後才開竅,豁然開朗感覺真是很神奇。

以下會拿 Emacs Lisp 跟 Scheme 當例子。

匿名函數

簡單來說,Lisp 裡的 lambda 就是沒有名字的函數。精確的說,lambda 是 Lisp 中拿來表示「匿名函數」(anonymous function) 的方法

…這種說法誰聽得懂啦。那麼先來用大家在 Common Lisp / Emacs Lisp 中最熟悉的 defun 定義一個函數 double,它接受 x 一個參數,最後回傳 x * 2 的值:

1
2
3
4
5
6
7
8
9
;;;; Emacs Lisp / Common Lisp
(defun double (x)
(* x 2))
;; 來呼叫看看:
(double 7)
;; => 14
;;很簡單吧?

Read More

Emacs Lisp 中 Process 相關的玩意

這幾天在寫 hexo.el 遇到一些 Emacs Lisp 中 process 相關的處理方式,做個簡單的整理筆記(也順便試用 hexo.el )。不過有些因為目前我沒用過/用不到,所以也懶得去研究其中差異,不要打我。

Process

start-process (Async)

(start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS)

這是 Emacs Lisp 中最低階的 process 呼叫方法之一,他 stdout 輸出的 BUFFER (fundamental-mode) 連 ANSI color 都沒有(所以會看到一堆亂七八糟的 ANSI color 控制字元),要自己使用 set-process-filter 來自訂 Buffer 的 IO。

Read More