Common Lisp: A função Remover, como ele é usado?
-
21-08-2019 - |
Pergunta
Eu tenho uma consulta request-uri na forma de "/ node / 143" (apenas um exemplo do formato).
Eu quero tirar a primeira barra da corda, eu olhei para a função Remover e teve uma tentativa. Eu simplesmente não consigo fazê-lo funcionar (estou usando SBCL no Linux).
Eu configurei o pedido-URI usando este código.
(setq request-uri "/node/143")
Quando eu verificar a variável eu tenho esta retornado.
request-uri
"/node/143"
Agora tente remover a primeira barra (neste momento é apenas alguma coisa para ver como a função é usada adequadamente).
(remove "/" request-uri)
"/node/143"
(remove '/ request-uri)
"/node/143"
Eu até tentei fornecer uma lista ??p>
(remove '("/") request-uri)
"/node/143"
(remove '('/) request-uri)
"/node/143"
Apesar de cordas são vetores de caracteres Eu pensei que de alguma forma talvez a seqüência inteira pode ser colocado em uma célula e eu tentei remover a coisa toda, ainda não sorte.
(remove "/node/143" request-uri)
"/node/143"
(remove '/node143 request-uri)
"/node/143"
Então, eu estou em uma perda agora, essa função aparentemente simples tem realmente me iludiu, pensei eu segui a documentação ao pé da letra, mas nada está funcionando.
Alguém pode lançar alguma luz sobre o que está acontecendo aqui?
Graças.
Editar:. Eu encontrei a resposta à minha pergunta, o que levantou uma outra questão
Para remover um elemento da corda que eu usei
(remove #\/ request-uri)
E sobre toda uma série
`(remove #\node request-uri`)
Só funciona para o primeiro caractere e lança um erro, ea seguinte tudo não fazer nada.
(remove "node" request-uri)
(remove 'node request-uri)
(remove ?\node request-uri)
(remove #\node request-uri)
(remove '("node") request-uri)
Eu não tenho certeza de que outra forma ele deve ser abordado aqui.
Solução
Aprenda a ler o Common Lisp HyperSpec .
Seqüências , Arrays (vetores unidimensionais de caracteres) e, assim, Cordas . Isto significa que a maioria dessas funções são aplicáveis.
Vamos olhar REMOVE . CLHS dá esta assinatura:
remove item sequence &key from-end test test-not start end count key
=> result-sequence
Strings são sequências de caracteres. Assim, uma chamada para remover seria:
(remove #\/ "/foo/")
ou (por exemplo)
(remove #\/ "/foo/" :start 2)
Lembre-se: # \ a é um personagem. # \ Nó é nenhum personagem. Ilegal. Uma string é "/ foo /".
O item para remover de uma corda tem que ser um personagem. Nada mais. Por quê? Como o teste é pelo EQL padrão e EQL compara o caractere na seqüência com o seu argumento item. Também fundamental é pela identidade padrão e não alterar os itens.
E se o seu argumento é uma string? Bem, então você tem que fazer mais:
(remove "/" "/abc/" :key #'string :test #'equal)
Isto olha cada personagem da seqüência e torna-lo em uma corda. A seqüência de caracteres, em seguida, serão comparados com seu artigo "/" usando a função EQUAL. Isso funciona também. O custo é de que ele precisa para gerar uma seqüência de cada caráter de "/ abc /", cada corda é um objeto novo.
Outra maneira de fazer isso é:
(remove "/" "/abc/" :test (lambda (a b) (eql (aref a 0) b)))
Acima recupera o primeiro caractere "/" em cada teste e compara-o com a personagem da string "/ abc /". Mais uma vez o custo é que ele precisa para obter o personagem cinco vezes (neste exemplo).
Portanto, a melhor maneira de escrevê-lo se o seu objeto original vem como uma string:
(remove (aref "/" 0) "/abc/")
Acima temos a personagem da string "/" uma vez e depois remover compara esse personagem com o teste EQL padrão com cada caractere na string - ele retorna uma nova seqüência daqueles personagens que não são EQL a # / <. / p>
O que você espera? \ Foo para ser? Em Common Lisp este é o símbolo |? Foo |.
Além disso (remover "foo" "afoob") não funciona desde que uma string ( "foo" aqui) não é um elemento de uma cadeia. Lembre-se, os personagens são elementos de cordas. Lembre-se também que as cordas com um item como "/" ainda são cordas e não um personagem. Assim, "/" e # / são de tipo diferente. O primeiro é uma string eo segundo é um personagem.
subseq extrai uma sequência a partir de uma sequência. Isso significa que também extrai uma seqüência de outra string:
(subseq "0123456" 1 5)
where 1 is the start and 5 is the end index.
CONCATENATE acrescenta seqüências. Isso significa que ele também anexa strings.
(concatenate 'string "abc" "123")
returns a new string with the strings "abc" and "123" appended.
Para remover partes de uma seqüência de ver também as funções String-Trim, String-LEFT-Trim e STRING-RIGHT-Trim.
Assim, como em uma outra resposta para remover substrings de uma string, você precisa escrever algum código para extrair algumas cordas e então concatenar os.
pesquisa Pesquisas para strings em strings.
Outras dicas
Para remover uma substring inteira, você terá que fazer uma nova função, por exemplo:.
(defun remove-string (rem-string full-string &key from-end (test #'eql) test-not (start1 0) end1 (start2 0) end2 key) "returns full-string with rem-string removed" (let ((subst-point (search rem-string full-string :from-end from-end :test test :test-not test-not :start1 start1 :end1 end1 :start2 start2 :end2 end2 :key key))) (if subst-point (concatenate 'string (subseq full-string 0 subst-point) (subseq full-string (+ subst-point (length rem-string)))) full-string)))
Este é apenas um ponto de partida. Eu replicado todas as opções para a pesquisa, mas acho que algumas opções não fazem sentido neste contexto. Pelo menos isso funciona:
(remove-string "node" "this is a node or not")
Para casos mais elaborados, talvez você deve dar uma olhada em cl-ppcre, uma biblioteca regex.
Explicação:
(remove "node" request-uri)
(remove 'node request-uri)
(remove ?\node request-uri)
(remove #\node request-uri)
(remove '("node") request-uri)
Estes são (respectivamente): uma corda, um (citado) símbolo, um (avaliado) símbolo, um literal de caracteres malformada, e uma lista contendo uma string. remove um objecto a partir de um objecto de sequcia-, e um cadeia não é uma sequência de qualquer uma dessas coisas.
Se você quiser apenas para remover parte da cadeia de caracteres, subseq pode fazer o truque:
(let ((uri "/node/143"))
(when (string= (subseq uri 0 6) "/node/")
(format t "user wants node ~D" (parse-integer (subseq uri 6)))))
Para que as coisas mais complexas, você provavelmente vai querer uma biblioteca como cl-ppcre e / ou split-sequência. (Se você estiver usando Hunchentoot, você já tem o ex-carregado.)
Esta falha porque "/" é uma string, não um personagem.
(remove "/" request-uri)
"/node/143"
Se quiser que o personagem, você precisa usar # / ou seja, o caractere de barra.
(remove #\/ request-uri)
"node143"
Mas como você pode ver, ele vai remover todas barras. De acordo com a página doc é ligada, retire leva uma palavra-chave param chamado: contagem, que diz quantos itens para remover. Então, você poderia fazer isso.
(remove #\/ request-uri :count 1)
"node/143"
Espero que isso ajude.
:: EDIT ::
Não é? /, É # /. Graças Douglas!