Sequências
lists e vectors (e, portanto strings) são sequências.
Note: veja também a página sobre strings.
Muitas das funções de sequência utilizam palavras-chave como argumentos. Todos os argumentos podem ser são opcionais, e se especificados, podem aparecer em qualquer ordem.
Atente-se ao argumento :teste
. O seu padrão é eql
(para strings use :equal
).
Para o argumento :key
deve-se passar nil, ou uma função com um argumento.
Essa função key é usada como umo filtro pelo qual os elementos da
sequência são visualizados. Por exemplo:
(find x y :key 'car)
é similar a (assoc* x y)
, ela busca por um elemento na lista em que
o car seja igual a x, oa invés de um elemento que seja igual a x.
Se :key
for omitido ou nil, o filtro será efetivamente a funçãp identidade.
Exemplo com uma alist:
(defparameter my-alist (list (cons 'foo "foo")
(cons 'bar "bar")))
;; => ((FOO . "foo") (BAR . "bar"))
(find 'bar my-alist)
;; => NIL
(find 'bar my-alist :key 'car)
;; => (BAR . "bar")
Para algo mais, use um lambda
que receba um parâmetro.
(find 'bar my-alist :key (lambda (it) (car it)))
Nota: cl21 possui short lambdas:
(find 'bar my-alist :key ^(car %))
(find 'bar my-alist :key (lm (it) (car it)))
Predicados: every, some,...
every, notevery (teste, sequência)
: retornam nil ou t, respectivamente,
no momento em que um teste ou qualquer conjunto de elementos correspondentes
a elementos de sequências retorne nil.
(defparameter foo '(1 2 3))
(every #'evenp foo)
;; => NIL
(some #'evenp foo)
;; => T
com uma lista de strings:
(defparameter str '("foo" "bar" "team"))
(every #'stringp str)
;; => T
(some #'(lambda (it) (= 3 (length it))) str)
;; => T
(some ^(= 3 (length %)) str) ;; in CL21
;; => T
some
, notany
(teste, sequência): retorna o valor do teste ou nil.
mismatch
(sequence-a, sequence-b): Retorna a posição em sequênce-a
onde sequence-a sequence-b deixam de ser iguais. Retorna nil se as duas
sequências forem iguais. Outros parâmetros: :from-end bool
, :start1
, :end[1,2]
.
Functions
Veja também as funções de sequência definidas em (em inglês)
Alexandria:
starts-with
, ends-with
, ends-with-subseq
, length=
, emptyp
,…
length (sequence)
member (elt, sequence)
Retorna o tail de sequence
a partir do primeiro elemento que satisfaça eql
.
Aceita :test
, :test-not
, :key
(funções ou símbolos).
(member 2 '(1 2 3))
;; (2 3)
elt (sequence, index) - encontra a partir de index
Cuidado, neste caso a sequência vem primeiro.
count (foo sequence)
Retorna o número de elementos em sequence que dão match em foo.
Parâmetros adicionais: :from-end
, :start
, :end
.
Veja também count-if
, count-not
(test-function sequence).
subseq (sequence start, [end])
É passível de "setf", mas funciona apenas se a nova sequência tiver o mesmo tamanho que a sequência a ser substituída.
sort, stable-sort (sequence, test [, key function])
Esta função é destrutiva, então você é de bom tom copiar a sequência antes da ordenação:
(sort (copy-seq seq) :test #'string<)
find, position (foo, sequence) - obter index
além de find-if
, find-if-not
, position-if
, position-if-not
(teste sequência).
Veja também os parâmetros :key
, :test
.
(find 20 '(10 20 30))
;; 20
(position 20 '(10 20 30))
;; 1
search (sequence-a, sequence-b)
Procura por uma subsequência em sequence-b que correspondente a sequence-a.
Retorna a posição da subsequência correspondente ou NIL. Possui os parâmetros
from-end
, end1/2
entre outros.
substitute, nsubstitute[if,if-not]
sort, stable-sort, merge
replace (sequence-a, sequence-b)
Substitui os elmentos de sequence-a pelos elementos de sequence-b.
remove, delete (foo sequence)
Faz uma cópia de sequence sem elementos que dêem match em foo. Possui os parâmetros
:start/end,
:keye
:count`.
delete
faz o mesmo, pórem, dependendo do contexto ela pode destruir a sequência
original no processo.
(remove "foo" '("foo" "bar" "foo") :test 'equal)
;; => ("bar")
Veja também remove-if[-not]
a seguir.
mapping (map, mapcar, remove-if[-not],...)
Se você já está familiarizado com map e filter em outras linguagens,
provavelmete o que você procura é mapcar
. Mas ele funciona apenas em listas,
então para iterar em vetores e produzir tanto um vetor quanto uma lista, use (map 'list function vector)
.
mapcar também aceita múltiplas listas com &rest more-seqs
. O mapeamento termina
no momento em que a menor sequência chega ao fim.
Nota: map
do cl21 é um mapcar
para listas e vetores.
map
recebe o tipo de saída desejado como o primeiro argumento ('list
, 'vector
, ou 'string
):
(defparameter foo '(1 2 3))
(map 'list (lambda (it) (* 10 it)) foo)
Filter, aqui, é chamado de remove-if-not
.
Flatten a list (Alexandria)
Com
Alexandria,
temor a função flatten
.
Criando listas com variáveis
Este é um dos usos de backquote
:
(defparameter *var* "bar")
;; First try:
'("foo" *var* "baz") ;; sem backquote
;; => ("foo" *VAR* "baz") ;; errado
Segunda tentaiva, usando backquote interpolation.
`("foo" ,*var* "baz") ;; com backquote, vírgula
;; => ("foo" "bar" "baz") ;; correto
O backquote avisa que nós vamos fazer a interpolação e a vírgula repassa o valor da variável.
Se a nossa variável é uma lista:
(defparameter *var* '("bar" "baz"))
;; First try:
`("foo" ,*var*)
;; => ("foo" ("bar" "baz")) ;; uma nested list
`("foo" ,@*var*) ;; backquote, comma-@ to
;; => ("foo" "bar" "baz")
E. Weitz avisa que "objetos gerados desta forma muito provavelmete da mesma estrutura (ver Receita 2-7)".
Comparando listas
É possível usar funções de set.