我想寫一個函數,它添加了像這樣的括號:(parens'(a b c d e))returns(a(b(c(d(e)))))。我只是沒有看到這種模式。到目前爲止,我只是在每個元素周圍返回一個帶括號的列表。我似乎無法弄清楚如何使它看起來像那樣。Lisp函數,它以某種方式添加括號
(DEFUN PARENS (L)
(COND ((NULL L) NIL)
(T (CONS (LIST (CAR L)) (PARENS (CDR L))))))
我想寫一個函數,它添加了像這樣的括號:(parens'(a b c d e))returns(a(b(c(d(e)))))。我只是沒有看到這種模式。到目前爲止,我只是在每個元素周圍返回一個帶括號的列表。我似乎無法弄清楚如何使它看起來像那樣。Lisp函數,它以某種方式添加括號
(DEFUN PARENS (L)
(COND ((NULL L) NIL)
(T (CONS (LIST (CAR L)) (PARENS (CDR L))))))
列表中沒有括號。你從五個元素列表開始,(a b c d e)
,並獲取兩個元素列表(a (b (c (d (e)))))
。第一個元素是a
,第二個元素是另一個列表(b (c (d (e))))
。
它非常容易使用reduce
得到接近這樣:
CL-USER> (reduce 'list '(a b c d e) :from-end t)
(A (B (C (D E))))
你能想到的reduce
爲「注入」功能list
到(a b c d e)
生產
(list a (list b (list c (list d e))))
這幾乎什麼你要。你真的想要:
(list a (list b (list c (list d (list e)))))
你會如何生產?您可以遞減列表,並且對於每個子列表要返回(list x (recurse ys))
,但是ys
爲()
時例外。你不想遞歸到()
,因爲你不想要一個包含兩個元素的列表,你實際上什麼都不需要。所以訣竅是停止遞歸比您通常使用列表更早。因此:
(defun parens (l)
(cond
((endp l) '())
((endp (rest l)) l)
((list (first l) (parens (rest l)))))) ; *
CL-USER> (parens '(a b c d e))
(A (B (C (D (E)))))
CL-USER> (parens '(a b))
(A (B))
CL-USER> (parens '(a))
(A)
CL-USER> (parens '())
NIL
*省略最後一句話,在t
測試是故意的。如果在cond
子句中沒有形式表單,則返回測試的值。因此(list …)
既作爲測試形式也作爲價值形式。
我們實際上可以清理一點點。 ((endp l) '())
的情況可能是((endp l) l)
,因爲l
是空列表。但這意味着在第一和第二種情況下,我們都可以返回l
。我們可以在Common Lisp中調用(rest '())
並取回()
,所以(rest l)
將()
時l
是像(e)
和時l
是()
。這意味着我們可以使用:
(defun parens (l)
(cond
((endp (rest l)) l)
((list (first l) (parens (rest l))))))
如果我們只是有一個測試,雖然,我們還不如干脆用if
:
(defun parens (l)
(if (endp (rest l))
l
(list (first l) (parens (rest l)))))
實際上,你可以用reduce
和一些特殊的考慮做結束:
(defun unflatten (list)
(reduce #'list list
:from-end t
:end (1- (length list))
:initial-value (last list)))
注意last
返回最後ñ(默認爲1)ELEM名單經濟需求。