Entendendo o elisp idiom (valores booleanos x argumentos citados)?

7

Eu tenho algumas perguntas básicas sobre o elisp.

Costumo ver algo como

(search-forward "something" nil 'noerror)

E às vezes vejo algo como

(search-forward "something" nil :noerror)

Qual é a diferença e devo preferir um formulário ao outro?

Tanto quanto eu entendo tudo, mas a lista vazia é avaliada como verdadeira em um contexto booleano. Mas como vem o seguinte:

Quando o termo de pesquisa "alguma coisa" não existe no buffer, o ponto salta para o final do buffer quando 'noerroré usado em vez de t. Quando té usado, o ponto permanece onde está.

Primeiro caso:

(search-forward "something" nil 'noerror);; 1.Evaluate this

;; end of buffer 2.point jumps here

Segundo caso:

(search-forward "something" nil t);; 1.Evaluate this, 2. Point stays here

;; end of buffer
clemera
fonte
11
FWIW: Quando todos os não- nilvalores são tratados da mesma forma pela função especificada, passo no meu código um símbolo com o mesmo nome ou semelhante ao nome do parâmetro usado na descrição da função e normalmente em maiúsculas. Isso serve como um lembrete para mim, quando leio o código. Por exemplo (search-forward "abc" nil 'NOERROR). É mais útil para argumentos opcionais que raramente são usados.
Tirou

Respostas:

12

Os valores booleanos no elisp funcionam da seguinte maneira:

  • nile ()(que, como você observou, são a mesma coisa) são falsas
  • Absolutamente qualquer outra coisa é verdadeira.

O tsímbolo existe como um valor 'puro' de true (quando não há benefício em usar outro valor), mas a maioria das funções tentará retornar algo que poderia ser útil, sempre que possível.

Veja também C-hig (elisp) nil and t RET

Quando se trata de usar argumentos de palavra-chave ou outros símbolos como um não- nilvalor quando o código única se preocupa nilou não nil, é realmente apenas uma questão de preferência pessoal. Não há diferença em termos de execução.

Uma vez perguntei a mesma coisa e fui informado de que a abordagem de argumento de palavra-chave é um método Lisp-ish mais comum.

(Eu mesmo decidi usar argumentos de palavra-chave, em parte para destacar a sintaxe e em parte porque os diferencia melhor dos símbolos de variável e função).

Quanto à sua exemplo específico, a função faz diferenciar entre vários não- nilvalores, e que o comportamento é coberto pela sua docstring:

O terceiro argumento opcional, se t, significa que, se falhar, basta retornar nil(sem erro). Se não nile não t, vá para o limite de pesquisa e retorno nil.

Em geral, você notará que as doutrinas tendem a se referir a "não nulo" em vez de "verdadeiro" ou "t". Se você vir "t", é bem provável que seja um caso especial.

phils
fonte
Obrigado, isso esclareceu para mim! Portanto, tudo menos nada é verdadeiro, mas t como "puro" é diferente disso.
Clemera
2
Bem, ainda é apenas um símbolo (ainda que auto-citado, como nilé). Por "puro", apenas quero dizer que existe especificamente para ser um valor que significa "verdadeiro", porque às vezes é isso que você deseja. Outros não- nilvalores ainda são tão "verdadeiros" quanto tsão.
Phill #
14

Alguma referência histórica é devido.

O Emacs Lisp empresta muitas coisas do Common Lisp, mas a semelhança é apenas superficial. O símbolo de dois pontos no Common Lisp é um qualificador de espaço para nome. Os nomes de símbolos canônicos têm duas partes: o nome do pacote e o nome do símbolo nesse pacote; portanto, por exemplo, cl-user:aproposé um símbolo definido no pacote cl-user. Há também um pacote de palavras-chave especial importado automaticamente pelo Common Lisp quando é iniciado. Este pacote é usado para se comunicar entre outros pacotes (para que, se os pacotes precisem enviar informações simbólicas entre si, eles não discutirão sobre quem deve declará-las). Como você deve ter adivinhado, os símbolos desse pacote são escritos com os dois pontos principais.

O Emacs Lisp não tem um conceito de pacotes, mas o cólon ainda é especial, pois instrui o leitor a interpretar a expressão como símbolo de autoavaliação (ou seja, é uma variável cujo valor é essa variável). Existem vários desses símbolos de autoavaliação incorporados: te nilsão exemplos que vou escrever mais adiante.

O apóstrofo também é emprestado do Common Lisp, onde é uma macro de leitor padrão (ou seja, é um código que o interpretador Lisp executa durante a leitura na fonte do programa). Ele se expande da seguinte forma:, 'x -> (quote x)onde (quote ...)é uma forma especial que impede o intérprete Lisp de avaliar o conteúdo da expressão interna. Emacs Lisp tem três built-in macros leitor: ', `e #, mas você não pode adicionar seu próprio. Os dois primeiros se expandem para (quote ...), no entanto, o segundo permite uma sintaxe especial para criar a expressão não avaliada. #expande para o (function ...)formulário, o que instrui o intérprete que o valor deve ser procurado no espaço de nomes da função.

Os símbolos no Emacs Lisp devem ser avaliados com algum valor (semelhante a variáveis ​​em outros idiomas), caso contrário, é um erro. No entanto, você pode impedir a avaliação usando o formulário de cotação.

Finalmente, a diferença entre:

(search-forward "something" nil 'noerror)

e

(search-forward "something" nil :noerror)

É que, no primeiro caso, você chamou search-forwardcom um símbolo sem valor, para o qual apenas o nome é conhecido, e no segundo caso, você chamou essa função com um símbolo cujo valor é esse próprio símbolo. Acontece que essa função não se importa com qual deles você usa.


Os tipos são uma importante ferramenta de programação para verificação automática de programas. O sistema de tipos Emacs Lisp é semelhante ao Common Lisp, pois seu tipo universal (escrito como t) é o tipo do qual todos os outros tipos são derivados. Por outro lado, nilé o tipo do qual nenhum tipo é derivado (o complemento de t). Isso é diferente de muitas linguagens de programação populares, que podem não ter um conceito de tipo universal ou ter um tipo booleano distinto.

Mais uma vez, infelizmente, o Emacs Lisp não copiou esta parte precisamente do Common Lisp, e a type-offunção fornece resultados confusos para te nil.

Emacs Lisp:

(type-of t) ; symbol

Lisp comum

(type-of t) ; BOOLEAN

Extensão comum do Emacs Lisp Lisp tem uma função cl-typepque pode, no entanto, ajudar a entender o relacionamento. Então, por exemplo

(cl-typep 'noerror t) ; t

ou seja, seja o que 'noerrorfor, é do tipo t.

wvxvw
fonte
Informações adicionais interessantes, obrigado!
Clemera
Explicação maravilhosa. Também aprendi algo sobre o Common Lisp. Obrigado.
GSL