2017-09-24 78 views
0

我的名單「直」的列表:爲什麼終端停止響應輸入命令,我寫了什麼?

(setq straight '(
     ("Arad"    366) 
     ("Bucharest"   0) 
     ("Craiova"   160) 
     ("Dobreta"   242) 
     ("Eforie"   161) 
     ("Fagaras"   176) 
     ("Giurgiu"   77) 
     ("Hirsova"   151)  
     ("Iasi"    226) 
     ("Lugoj"   244) 
     ("Mehadia"   241) 
     ("Neamt"   234) 
     ("Oradea"   380) 
     ("Pitesti"   100) 
     ("Rimnicu Vilcea" 193) 
     ("Sibiu"   253) 
     ("Timisoara"  329) 
     ("Urziceni"   80) 
     ("Vaslui"   199) 
     ("Zerind"   374))) 

而且我有一個列表("Pitesti" 101)。我試圖通過「直接」搜索並找到與「皮特什蒂」相對應的價值。但是,當我運行我的功能,終端停止響應輸入命令,並沒有迴應我寫的任何東西。這裏的功能:

(defun her (node) 
    (setq s straight) 
    (setq c '()) 
    (loop while (not (eq (car node) 
         (caar s))) 
     do (setq s (cdr s))) 
    (setq c (append node (car (cdar s))))) 
+1

由於它看起來像一個無限循環,你可能想要停止它... –

回答

2

首先,你的直接問題:eq意味着對象的身份。我想你會給這個函數提供城市名稱的單例列表,所以當你比較(eq (car node) (caar s))時,你會比較兩個字符串。只要這兩個字符串不是同一個對象(如果這兩個字符串都是從同一個編譯—這兩個字符中讀取的,這在這裏看起來不太可能),這將是錯誤的。相反,您應該使用string=

因爲你比較不會返回true,則循環將繼續設置sstraight尾巴,但要注意的nilcdr再次nil:這不會終止。

因此,用string=替換eq可能會解決您的緊急問題。但是,還有更多問題。

如果您傳遞的字符串實際上並不存在於straight中,會發生什麼情況?然後再次,它永遠不會終止。一個更好的辦法來做到這一點循環:

(loop :for pair :in straight 
     :when (string= (car node) (car pair)) 
     :do (return pair)) 

for - in結構將在列表的最後終止,所以你會得到nil如果字符串丟失。 Loop有另一種構建找到的東西:thereis

(loop :for pair :in straight 
     :thereis (when (string= (car node) (car pair)) pair)) 

發現的說起,爲什麼不使用find代替loop

(find (car node) straight 
     :test #'string= 
     :key #'first) 

由於使用列表的列表簡單的關聯結構是相當普遍(「關聯名單」或「alist」),這裏有專門的表格:

(assoc (car node) straight 
     :test #'string=) 

最後,一個令人矚目的普遍問題是:你自始至終都是免費的(最有可能是未綁定的)變量。不要這樣做。努力寫出引用透明的功能。建立與let等本地綁定。當你有一個結果,只需返回它,不要設置一些全局變量。