Pergunta
Estou aprendendo Esquema R5RS no momento (a partir PocketScheme) e eu acho que eu poderia usar uma função que é construído em algumas variantes do esquema, mas não todos: Anexar
Em outras palavras -. Destrutiva mudança de uma lista ??p>
Eu não estou muito interessado no código real como uma resposta, tanto quanto a compreensão do processo pelo qual se poderia passar uma lista como uma função (ou um vector ou string) e, em seguida, transformar-lo.
exemplo:
(define (append! lst var)
(cons (lst var))
)
Quando eu uso a abordagem como acima, eu tenho que fazer algo como (define list (append! foo (bar))
que eu gostaria de algo mais genérico.
Solução
Mutation, embora permitida, é fortemente desencorajada no esquema. PLT mesmo fui tão longe para set-car!
remover e set-cdr!
(embora eles "substituído"-los com set-mcar!
e set-mcdr!
). No entanto, uma especificação para append!
apareceu em SRFI-1 . Este append!
é um pouco diferente do seu. No SRFI, a implementação pode , mas não é necessário para modificar as células contras para acrescentar as listas.
Se você quiser ter um append!
que é garantida para alterar a estrutura da lista que está sendo anexado ao, você provavelmente vai ter que escrevê-lo sozinho. Não é difícil:
(define (my-append! a b)
(if (null? (cdr a))
(set-cdr! a b)
(my-append! (cdr a) b)))
Para manter a definição simples, não há nenhuma verificação de erro aqui, mas é claro que você vai precisar para passar em uma lista de comprimento pelo menos 1 como a
, e (de preferência) uma lista (de qualquer comprimento) como b
. O a
razão deve ser de pelo menos comprimento 1 é porque você não pode set-cdr!
em uma lista vazia.
Uma vez que você estiver interessado em como isso funciona, eu vou ver se consigo explicar. Basicamente, o que nós queremos fazer é ir para baixo na lista a
até chegarmos ao último par cons
, que é (<last element> . null)
. Então, nós primeiro ver se a
já é o último elemento na lista, verificando null
na cdr
. Se for, nós usamos set-cdr!
para configurá-lo para a lista que estamos anexando, e estamos a fazer. Se não, temos que chamar my-append!
na cdr
de a
. Cada vez que fazemos isso que nos aproximamos do final do a
. Uma vez que esta é uma operação de mutação, que não vai retornar nada, por isso não precisa se preocupar sobre a formação de nossa lista modificado como o valor de retorno.
Outras dicas
Melhor tarde do que nunca para colocar em um par de 2-3 centavos sobre este tema ...
(1) Não há nada de errado com o uso dos procedimentos destrutivas no Esquema enquanto há uma referência única para o stucture ser modificado. Assim, por exemplo, a construção de uma grande lista de forma eficiente, fragmentada através de uma única referência - e, quando completa, fazer que a lista (agora presumivelmente não-to-be-modificado) conhecido e referido a partir de várias referências
.(2) Eu acho que APPEND! deve se comportar como APPEND, somente (potencialmente) destrutivamente. E assim APPEND! deve esperar qualquer número de listas como argumentos. Cada lista, mas o último seria presumivelmente SET-CDR! 'D para a próxima.
(3) A definição acima de APPEND! é essencialmente NCONC de Mac Lisp e Common Lisp. (E outros lisps).