2016-04-19 94 views
4

我試圖找出是否有這樣做的SUBLIS和Common Lisp中的混合物反引號,而不必寫我自己的一個簡單的方法。SUBLIS和拼接

定期SUBLIS會給我得到以下結果:(一般情況下,可以是任意複雜的樹,不只是一個簡單的列表)

CL> (sublis '((X . (1 2 3))) '(bar (foo X))) 
(BAR (FOO (1 2 3))) 

但我尋找到一個版本該拼接列表進入替代,如:

CL> (sublis1 '((X . (1 2 3))) '(bar (foo X))) 
(BAR (FOO 1 2 3)) 

就像它發生在反引號和逗號ATSIGN:

CL> (let ((x (list 1 2 3))) `(bar (foo ,@x))) 
(BAR (FOO 1 2 3)) 

回答

3
  1. 有沒有標準CL函數來做到這一點; (替代等人僅在序列樹工作,而不是; SUBST等人的樹工作,但僅替換一個固定新)。

  2. 不這樣做的唯一方法,是使用將做到這一點,或更多的圖書館。我只能想到一些模式匹配庫。

也許你可以查找一些代碼來實現你必須實現的同樣的事情,並且有一些運氣,找到並找到你想要的相同功能。但是老實說,找到一個模式匹配庫並學習如何使用它來做你想做的事,或者找到一個類似的程序來實現這個已經實現的功能,這讓我看起來更多的工作,以及比編程它更少的樂趣。甚至要求在stackoverflow看起來像寫作更多的工作!

(defun sublis1 (bindings tree) 
    (cond 
    ((null tree) tree) 
    ((atom tree) ;; a dotted list in the tree. 
    (cdr (assoc tree bindings))) 
    ((let ((entry (assoc (car tree) bindings))) 
     (when entry 
     (append (cdr entry) (sublis1 bindings (cdr tree)))))) 
    ((atom (car tree)) 
    (cons (car tree) 
      (sublis1 bindings (cdr tree)))) 
    (t 
    (cons (sublis1 bindings (car tree)) 
      (sublis1 bindings (cdr tree)))))) 

(sublis1 '((X . (1 2 3))) '(bar (foo X))) 
--> (bar (foo 1 2 3)) 
+0

每一段代碼可以有錯誤,如果存在一個核心功能來完成這項工作,這將是更好的使用它,而不是寫一個新的。這是問題的真正原因。我們都可以想出編寫函數sublis1的方法。 –

+0

沒錯,對不起,沒有說清楚:這個想法是不是索取sublis1'的'實現(我想象它不會是困難的),而是看是否有一個簡單的解決方案在那裏,戰鬥測試等不管怎麼說,感謝您的實施! –

4

據我所知,沒有標準的功能來做到這一點。 如果拼接變量始終是一個列表的末尾,你可以使用:test #'equal像這樣:

(sublis '(((x) . (1 2 3))) 
     '(bar (foo x)) 
     :test #'equal) 

=> (BAR (FOO 1 2 3)) 

爲別的結構的變化是sublis太難了。 這不是太難寫,不過,因爲這似乎當我在寫一個實施顯示了答案。

4

說到不重新發明輪子,你可以使用代碼沃克隨附Common Lisp實現,如果有的話。例如 在SBCL,一個簡單的替換,其中FOO是明確可以做如下:

(sb-walker:walk-form '(bar (foo X)) 
        nil 
        (lambda (form context env) 
         (declare (ignore context env)) 
         (if (equal form '(foo x)) 
          '(foo 1 2 3) 
         form))) 

在你的情況,但是,你要匹配X,不FOO。這是沒有太大的 困難,但讓我們使用模式匹配庫 OPTIMA來說明它是如何工作的:

(sb-walker:walk-form '(bar (foo X)) 
        nil 
        (lambda (form context env) 
         (declare (ignore context env)) 
         (optima:match form 
         ((list head 'x) (list head 1 2 3)) 
         (_ form)))) 

這裏不存在進入無限走的風險,因爲(foo 1 2 3) 無法比擬的第一條規則。但是,您可能需要提供 輔助值T以防止助手緩存到結果表單中。