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

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.

Foi útil?

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).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top