雖然又是個簡單的例子,但是牽扯東西很多,先來談談 LISP,LISP 是個古老的語言 (噢,又說了一次),他是 LIST PROCESSOR 的縮寫,LIST 是什麼 ? LIST 直翻成串列,簡單講,就是將一串東西 (資料) 串起來,現實中可能馬上浮現日本的麻糬,魚丸...,等等,但 LISP 的資料更像烤肉串,上面可能有小香腸、青椒、培根等等美食 (不同種類資料),而香腸+大蒜也是這一串食物中的一小串,OK,簡單講,LISP 主要將不同型態的資料串接形成一串 (一筆資料),你也許會說,我記得 C 好像也可以,我要說的是,那個年代,這可是革命性的概念。
那要這種混和形式的資料幹什麼呢 ? 講到 LISP 又得再提到一樣東西 A.I. ,你的腦袋中是否又浮起一個小男孩的畫面,當初開發 LISP 主要就是要處理人工智慧的問題,這時要處理的就不只是數字、文字而已,而是要處理現實世界各式各項的資訊,幾十年過去了,LISP 不再是主流語言,甚至於在 A.I. 領域中也不在獨尊,而因為 Autodesk 選擇開發語言一個決定,讓一個搞土木的竟然也跟 LISP 發生關係,再回頭看,用 LISP 處理電腦輔助設計問題,又何嘗不是另一個意外。
好吧!來看看串列的資料長的什麼樣子,假設有個串列,裡面有三個資料,"A" "B" "C" 三個字元形成一個串列就叫 CHAR
(setq CHAR '("A" "B" "C"))
讓它執行 (例如在 AUTOCAD VLIDE 中的主控台),傳回
("A" "B" "C")
又如何,很像一維矩陣啊
記不記得 LISP 的一項特徵 S 表示式 (S-expression),例如 1 + 2 就寫成 (+ 1 2),事實上這個格式跟串列 (資料) 是同一型式,LISP 靠此達成程式碼跟資料格式統一。
換句話說,如果把 (+ 1 2),視為一個串列,第一個元素 + 就是函數名稱,第二個元素 1、第三個元素 2 就是輸入參數;程式在運作時,只要參數沒取完,就一值執行(累加),所以在 LISP 中 1 + 2 + 3 + 4 + 5 不是寫成
(+ 1 (+ 2 (+ 3 (+ 4 5))))
而是
(+ 1 2 3 4 5)
反而比傳統方式節省字元空間 (雖然不重要)
另外一個特色就是,傳入函數的變數是什麼形式,不就是變數嗎? LISP 可以將函數當變數傳入函數,到這裡,你應該已經頭昏腦脹了?先停下來,來看看今天的主題 (是的),這才是這篇文章要講的,在視窗對話盒中有一個元件叫 popup_list (例如我的程式集中 型鋼剖面程式內型鋼型號選取)
這些元件中有預設的選項,按下它後便可選取預設的項目,那麼程式怎麼知道預設的項目是哪些呢?當然是要程式中給的,怎們給?
(setq CHAR '("A" "B" "C"))
(start_list "popup_list_char")
(mapcar 'add_list CHAR)
(end_list)
第三行 (mpacar) 就是一個例子,這個函數第一個變數 add_list 就是一個函數 (注意在這裡是用 ',不是用括號),他將一個個項目加到 "popup_list_char" 中,但是 CHAR 中有三個項目,別的語言要怎麼做,首先要知道 CHAR 中有幾個元素,再來個迴圈執行 add_list,但是在 LISP 中就這一行,很多高手出手時就喜歡用這個函數,看的人一時間天旋地轉,日月無光。
再舉個例子,有個串列(setq A '(1 2 3 4 )),想要將每個元素加一,LISP 執行就
(mapcar '1+ A) A 變成 (2 3 4 5)
一行搞定 ,(mapcar) 就是將 A 這個串列中每一個元素 1 2 3 4 ,去執行 1+ 這個函數,這算是最淺顯的例子,再講下去我就要露出馬腳了,LISP 程式名稱來由也算名符其實,最後附上這個例子程式碼。
(PS 要知道使用者選那個選項,使用
(get_tile "popup_list_char")
傳回 "0" 第一項,"1" 第二項,以此類推)
//---------------------- Popup_list.lst
(defun C:Popup_list( / dcl_ID)
; 載入對話盒
(setq dcl_ID (load_dialog "Popup_list.dcl"))
(if( not (new_dialog "Popuplist" dcl_ID))
(progn
(alert "PopuList 對話盒無法載入!")
(exit)
)
)
(setq CHAR '("A" "B" "C"))
(start_list "popup_list_char")
(mapcar 'add_list CHAR)
(end_list)
; 按下 "確定" 時離開
(action_tile "accept" "(done_dialog 1)")
; 啟動對話盒
(start_dialog)
(unload_dialog dcl_ID)
(gc)
)
//---------------------- Popup_list.dcl
Popuplist : dialog {
key = "popuplist";
label = "Example" ;
spacer_1;
:popup_list {
key = "popup_list_char";
label = "字元:";
width = 20;
}
spacer_1;
ok_cancel;
}