Alguém pode explicar o conceito de 'higiene' para mim (eu sou um esquema de programador)?

StackOverflow https://stackoverflow.com/questions/3010493

  •  26-09-2019
  •  | 
  •  

Pergunta

Então...Eu sou novo esquema de r6rs, e estou aprendendo macros.Alguém pode me explicar o que se entende por 'higiene'?

Obrigado antecipadamente.

Foi útil?

Solução

A higiene é frequentemente usado no contexto de macros.Um higiênicos de macro não use nomes de variáveis que podem interferir com o código em expansão.Aqui está um exemplo.Vamos dizer que queremos definir o or de forma especial, com uma macro.Intuitivamente,

(or a b c ... d) iria expandir-se para algo como (let ((tmp a)) (if tmp a (or b c ... d))).(Estou omitindo o vazio (or) caso, por simplicidade.)

Agora, se o nome tmp na verdade, foi adicionado no código como no exemplo acima esboçado expansão, não seria higiênico, e ruim porque podem interferir com a outra variável com o mesmo nome.Dizer, queríamos avaliar

(let ((tmp 1)) (or #f tmp))

Usando o nosso intuitivo de expansão, este viria a ser

(let ((tmp 1)) (let ((tmp #f)) (if tmp (or tmp)))

O tmp a partir do macro sombras mais exterior tmp, e , assim, o resultado é #f em vez de 1.

Agora, se a macro foi higiênico (e, em Esquema, ele automaticamente é o caso, quando usar syntax-rules) e, em seguida, em vez de usar o nome tmp para a expansão, você deve usar um símbolo que é a garantia de não aparecer em nenhum outro lugar no código.Você pode usar gensym em Common Lisp.

Paul Graham Em Lisp tem material avançado em macros.

Outras dicas

Se você imaginar que uma macro é simplesmente expandiu-se para o lugar onde ele é usado, então você pode imaginar que, se você usar uma variável a no macro, deve existir já ser uma variável a definido o local onde a macro é usada.

Este é não o a que você quiser!

Um macro sistema em que algo como isto não pode acontecer, é chamado higiene.

Existem várias maneiras de lidar com este problema.Uma forma é simplesmente usar muito longo, muito enigmático, imprevisível nomes de variáveis em suas macros.

Um pouco mais refinado versão de que este é o gensym a abordagem utilizada por alguns outros sistemas de macro:em vez de você, o programador chegando com muito, muito, muito enigmático, imprevisível nome da variável, você pode chamar a gensym função que gera muito, muito, muito enigmático, imprevisível e único nome de variável para você.

E como eu disse, em um higiênicos de macro do sistema, tais conflitos não pode acontecer em primeiro lugar. Como para fazer um macro, o sistema higiênico é uma questão interessante em si mesmo, e o Regime de comunidade passou várias décadas sobre esta questão, e eles continuam chegando melhores e melhores formas de o fazer.

Eu estou tão feliz de saber que esta linguagem está sendo usada ainda!Higiene código é o código que, quando injetada (através de uma macro) não causar conflitos com as variáveis existentes.

Há muitas boas informações na Wikipedia sobre isso: http://en.wikipedia.org/wiki/Hygienic_macro

Aqui está o que eu encontrei. Explicar o que isso significa é outra questão!

http://www.r6rs.org/final/html/r6rs-lib/r6rs-lib-zh-1.html#node_toc_node_sec_12.1

Macros Código de transformação: eles pegam um pouco de código e o transformam em outra coisa. Como parte dessa transformação, eles podem cercar esse código com mais código. Se o código original faz referência a uma variável a, e o código que é adicionado em torno dele define uma nova versão de a, então o código original não funcionará como o esperado, porque estará acessando o errado a: E se

(myfunc a)

é o código original, que espera a ser um número inteiro, e a macro leva X e transforma para

(let ((a nil)) X)

Então a macro funcionará bem para

(myfunc b)

mas (myfunc a) será transformado em

(let ((a nil)) (myfunc a))

o que não vai funcionar porque myfunc será aplicado a nil Em vez de o número inteiro que está esperando.

Uma macro higiênica evita esse problema da variável incorreta sendo acessada (e um problema semelhante ao contrário), garantindo que os nomes utilizados sejam únicos.

Wikipedia tem uma boa explicação de Macros higiênicos.

Além de todas as coisas mencionadas, há uma outra coisa importante para planejar as macros higiênicas, que seguem do escopo lexical.

Diga que temos:

(syntax-rules () ((_ a b) (+ a b)))

Como parte de uma macro, certamente ele inserirá o +, também o inserirá quando já houver um A + lá, mas depois outro símbolo que tem o mesmo significado que +. Liga os símbolos ao valor que eles tinham no ambiente lexical em que o syntax-rules Mentiras, não onde é aplicado, somos lexicamente escoposos, afinal. Provavelmente, ele inserirá um símbolo completamente novo lá, mas que está globalmente ligado ao mesmo significado que + está no local em que a macro é definida. Isso é mais útil quando usamos uma construção como:

(let ((+ *))
  ; piece of code that is transformed
)

O escritor, ou usuário da macro, não precisa ser ocupado para garantir que seu uso corra bem.

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