學習軌道
/
Common Lisp
Common Lisp
/
練習
/
萊斯莉的長串陣列
萊斯莉的長串陣列

萊斯莉的長串陣列

學習練習

簡介

陣列

我們使用的程式語言叫做 Lisp,這個名字是 LIST Processing 的縮寫,所以你可能會猜想這門語言具備處理項目陣列的能力。沒錯,你說對了!

雖然 Common Lisp 有陣列以外的其他資料結構,但陣列依然被大量使用。

在 Common Lisp 中,陣列是一連串的項目。它也被稱為 cons(大多是基於歷史因素)。這些項目本身不一定要是相同的型別。例如,你可以有一個包含1、two、"III"的陣列。

建立陣列

你可以直接輸入像這樣帶引號的陣列:'(1 two "III"),這樣就會建立並求值一個陣列(它會求值成 (1 two "III"))。

還有兩個用來建立陣列的主要函式:list 和 cons。

list 接受零個或多個引數,並求值成一個用這些值建立起來的陣列:

(list 1 'two "III") ; => (1 two "III")

cons 接受兩個項目,並建立一個陣列,把第一個項目當作它的 car(陣列的開頭),第二個項目當作它的 cdr(陣列的其餘部分):

(cons 1 2)            ; => (1 . 2) ;; (a list without `nil` as its `cdr` is printed in this way)
(cons 1 nil)          ; => (1)
(cons 1 (cons 2 nil)) ; => (1 2)

函式 car 和 cdr 可以用來存取陣列的 car 和 cdr。

(first 和 rest 是 car 和 cdr 的同義詞,運作方式完全相同。)

長度與隨機存取

陣列的長度可以用 length 取得。空陣列的長度是零。

任意項目都可以用 nth 存取(請注意,陣列的索引從 0 開始)。

要求超出陣列長度的索引,並_不_算錯誤。它會求值成 nil:

(nth 23 '(short list)) ; => nil

還有幾個用來存取陣列開頭項目的輔助方法:first、second、third,一路到 tenth。很方便吧?

合併陣列

兩個或多個陣列可以用 append 合併:

(append '(a b c) '(1 2 3)) ; => (A B C 1 2 3)
(append '(a b c) '())     ; => (A B C)

傳給 append 的每個引數都必須是陣列。

說明

Lisp 外星人 Leslie 需要去買點東西。有一份購物清單是很重要的,要能往裡面加東西,也要能從裡面拿掉東西。

當然,單純的紙筆對 Lisp 外星人來說是不夠的。「List」幾乎就是「Lisp」這個字的全部了!一定得寫些函式來幫忙記錄要買的東西。

你能幫 Leslie 記錄這份購物清單嗎?

1. 建立新清單

首先,Leslie 需要建立一個空的清單。一個叫做new-list的函式正好適合這件事。

(new-list) ; => ()

喔不……Leslie 心裡已經有幾樣想買的東西了,所以他們需要一個函式,接受三個項目(還好 Leslie 只會建立包含三個項目的清單,不多也不少!),並用這些東西建立一份新的購物清單。寫一個list-of-things函式,接受三個項目並回傳包含它們的清單。

(list-of-things 'bread 'milk 'butter) ; => '(bread milk butter)

2. 把東西加進清單。

去商店之前,Leslie 會先翻翻儲藏室,看看自己需要什麼。幫他們寫一個add-to-list函式,把項目加到清單的開頭。

(add-to-list 'butter '(bread)) ; => '(butter bread)

3. 清單上的下一樣(幾樣)東西是什麼?

購物時,Leslie 想知道接下來要找什麼。他們也喜歡先偷看清單,看看第二個、第三個,甚至是第 23 個項目(他們的幸運數字)。

  • first-thing會求值為清單上的第一樣東西
  • second-thing會求值為第二樣東西
  • third-thing會求值為第三樣東西
  • twenty-third-thing會求值為第二十三樣東西
(first-thing '(bread butter milk)) ; => 'bread
(second-thing '(bread butter milk)) ; => 'butter
(third-thing '(bread butter milk)) ; => 'milk

4. 從清單移除東西

Leslie 想找出清單上的第一個項目,並把它從架上拿下來。幫他們寫一個remove-first-item函式,它會求值為輸入清單中除了第一個項目以外的所有項目。

(remove-first-item '(bread butter milk)) ; => '(butter milk)

5. 用較小的清單拼出較大的清單

Leslie 發現自己不小心做了兩份購物清單,而不是一份!寫一個list-append函式,回傳一個清單,其中包含第一個清單的元素,後面接著第二個清單的元素。

(list-append '(bread salt) '(butter milk)) ; => '(bread salt butter milk)

6. 還要多久?

Leslie 開始擔心這趟購物會花上好一陣子。這份清單上到底有幾樣東西?寫一個just-how-long函式,告訴他們清單有多長。

(just-how-long '(bread milk butter salt)) ; => 4
透過 GitHub 編輯 連結會在新視窗或分頁中開啟
Common Lisp Exercism

準備好開始 萊斯莉的長串陣列 了嗎?

註冊 Exercism,透過 27 個概念92 個練習 和真人引導來學習並精通 Common Lisp,全部免費。