Common lisp expressão idiomática - existe uma maneira melhor?
-
09-06-2019 - |
Pergunta
Dou por mim a fazer esse tipo de coisa o tempo todo.Eu estive a considerar escrever uma macro/função para fazer este tipo de coisa mais fácil, mas ocorre-me que eu sou provavelmente a reinventar a roda.
Existe uma função existente que vai me deixar realizar esse mesmo tipo de coisa de uma forma mais concisa?
(defun remove-low-words (word-list)
"Return a list with words of insufficient score removed."
(let ((result nil))
(dolist (word word-list)
(when (good-enough-score-p word) (push word result)))
result))
Solução
Existem vários construído-em maneiras de fazer isso.Uma forma seria:
(remove-if-not 'good-enough-score-p word-list)
E outra:
(loop for word in word-list
when (good-enough-score-p word)
collect word)
E ainda outra:
(mapcan (lambda (word)
(when (good-enough-score-p word)
(list word)))
word-list)
Etc...Há também SÉRIE e Iterar.O Iterar versão é idêntico ao CICLO versão, mas a SÉRIE versão é interessante:
(collect (choose-if 'good-enough-score-p (scan word-list))))
Então, sim, você está muito provavelmente a reinventar alguns roda.:-)
Outras dicas
A função que você deseja é remove-if-not
, que é interna.
(defun remove-low-words (word-list)
(remove-if-not #'good-enough-score-p word-list))
Se você sentir como você está re-inventar algo para fazer com as listas, provavelmente estão mesmo.Verifique o Hyperspec para ver.
Existem algumas maneiras que você pode fazer isso.Primeiro, e provavelmente o mais fácil, você pode fazê-lo de forma recursiva.
(defun remove-low-words (word-list)
(if (good-enough-score-p (car word-list))
(list word (remove-low-words (cdr word-list)))
(remove-low-words (cdr word-list))))
Você também pode fazê-lo com mapcar
e reduce
, onde o primeiro pode construir uma lista com a falta de elementos substituído por nil
e o último pode ser usado para filtrar o nil
.
Ou seria um bom candidato para um "filtro" macro ou função que recebe uma lista e retorna a lista filtrada por alguns predicado.