4

のように、複数の値を(単純な)ベクトルに連結する関数が必要です(concatenate )。ただし、連結とは異なり、ベクトルまたはシーケンスではない引数を処理できる必要があります。

つまり、次のように機能するはずです。

(concat #(1 2) 3) => #(1 2 3)
(concat 1 2 3) => #(1 2 3)
(concat 1 #(2 3 4)) => #(1 2 3 4)
(concat #(1 2) 2 #(3 4 5)) => #(1 2 3 4 5)

これどうやってするの?私はそれを可能にするいくつかの些細なlisp構造を忘れたと思います。

私の知る限り、連結ではそれができません。そして、マクロでそれを作る方法がよくわかりません(,@結果のlisp形式にリストを挿入する構造がありますが、この場合、非シーケンスとシーケンスを区別する方法がよくわかりません)。

4

3 に答える 3

5

reduce他の回答のアプローチは、時間的に2次式です。

線形ソリューションは次のとおりです。

(defun my-concatenate (type &rest args)
  (apply #'concatenate type
         (mapcar (lambda (a) (if (typep a 'sequence) a (list a)))
                 args)))
于 2013-02-17T18:14:13.293 に答える
3

シーケンスの長さを計算できるので、結果のシーケンスを割り当ててから、要素をそこにコピーできます。

(defun concat (type &rest items)
  (let* ((len (loop for e in items
                    if (typep e 'sequence)
                    sum (length e)
                    else sum 1))
         (seq (make-sequence type len)))
    (loop with pos = 0
          for e in items
          if (typep e 'sequence)
          do (progn
               (setf (subseq seq pos) e)
               (incf pos (length e)))
          else
          do (progn
               (setf (elt seq pos) e)
               (incf pos)))
    seq))


CL-USER 17 > (concat 'string "abc" #\1 "def" #\2)
"abc1def2"

上記はベクトルに適しています。リストのバージョンは演習として残されています。

于 2013-02-17T19:16:00.000 に答える
1
defun my-concatenate (type &rest vectors)
  (reduce (lambda (a b)
            (concatenate
             type 
             (if (typep a 'sequence) a (list a))
             (if (typep b 'sequence) b (list b))))
          vectors))

reduce引数を少し変更して使用でき#'concatenateます。引数の1つがシーケンスでない場合は、それをリストに変換するだけです(連結は、単純なベクトルとリストの混合引数でも機能します)。

CL-USER> (my-concatenate 'list #(1 2 3) 3 #(3 5))
   (1 2 3 3 3 5)

CL-USER> (my-concatenate 'simple-vector #(1 2 3) 3 #(3 5))
   #(1 2 3 3 3 5)

CL-USER> (my-concatenate 'simple-vector 1 #(2 3) (list 4 5))
   #(1 2 3 4 5)

編集:まあ、あなたはおそらく他の答えを受け入れるべきです。

于 2013-02-17T17:42:32.123 に答える