iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 4
1
Software Development

Emacs 來寫程式系列 第 4

[Emacs-4] Emacs Lisp 簡介 - 2

Emacs Lisp 簡介

函數

  • 定義函數也是使用 List,習慣上第一列會帶文字說明,例如
(defun say-hello ()
    "Say Hello to the whole world. "
    (message "Hello World"))
  • 帶參數的函數,參數是一個清單,可以字串,數字...
(defun say-hello (greeting)
  "Say GREETING to user, and kee message."
  (message greeting)
  )
(say-hello "Hello World")

(defun my/sum (num1 num2)
  "Sum of two integer NUM1 and NUM2 and return integer."
  (+ num1 num2)
  )
(my/sum 1 3)
  • Elisp 的函數是 Call by Value,意思是當函數進行前,會先把參數求值,如果參數是一個函數,會一直 recursive 往下先求值,所以
(my/sum (my/sum 3 4) (my/sum (my/sum 5 6) 7))

會先計算 (my/sum 5 6),再計算 (my/sum 11 7) ...

函數當成參數

  • Elisp 其實是相當先進的語言,函數可以當成參數代入另一個函數,例如
(defun times-3 (x) (* x 3))
(defun times-4 (x) (* x 4))
(defun multiples (multi-func max-num)
	(dotimes (x max-num)
		(print (format "%d: %d" x (funcall multi-func x))))
	)

(multiples #'times-3 10)
(multiples #'times-4 10)
  • 定義兩個函數 times-3times-4
  • (dotimes x max-num)for (x = 0; x < max-num; x++) 的意思
  • 至於 #'quote function 的意思,前面提到, Elisp 函數會先求參數值,quotequote function 就是要告訴 Elisp 不要求值,直接代入函數裡,例如 (funcall 'times-3 8) 就會等於 24
  • 執行結果如圖 function argument

區域變數

  • 前面介紹過全域變數,但我們知道使用全域變數要十分小心,因此如果可以的話,請盡量使用區域變數,而 Elisp 的區域變數可以使用 let 來定義
(let ((max 10))
  (dotimes (x max)
    (print (format "%d" x))))

會印出 0 ... 9

匿名及高階函數

  • 匿名也就是 lambda 函數,這在 Elisp 上非常常見,用來當作是一次性的函數,例如
(lambda (x) (* x x x))
((lambda (x) (* x x x)) 5)
  • Elisp 也有 Map 的高階函數,例如
(mapcar* 'times-3 (4 5 6))

結果會是 (12 15 18)

程式流程控制

條件

  • Elisp 的 ifcondcond 就如同一般程式語言的 switch case
;;
;; if statement
;;
(defun odd-or-even (x)
	(if (= 0 (% x 2))
		"even"
		"odd"))

(odd-or-even 3)
(odd-or-even 4)

;;
;; condition, or switch case
;;
(defun pick-word (n)
	(cond
	 ((= n 1) "gold")
	 ((= n 2) "silver")
	 ((= n 3) "bronz")
	 (t "winner")))

(pick-word 3)
(pick-word 33)

迴圈

  • 可以用 loop 或者之前看到的 dotimes
;;
;; for-loop
;;
(loop for x from 1 to 10
			do (print x))

;;
;; dotimes
;;
(dotimes (y 12)
	(print y))

遞迴

;;
;; recursive
;;
(defun factorial (n)
	(if (< n 1)
	1
	(* n (factorial (- n 1)))))

(factorial 3)
(factorial 10)

如果你想直接看影片跟著練習,歡迎收看

Elisp

相關簡報請看 我的部落格


上一篇
[Emacs-3] Emacs Lisp 簡介 - 1
下一篇
[Emacs-5] 套件管理及基本設定
系列文
Emacs 來寫程式30

尚未有邦友留言

立即登入留言