Pergunta

Depois de fazer isso através das partes principais de um livro Lisp introdutório, eu ainda não conseguia entender o que o (quote) operador especial (ou equivalente ') função faz, no entanto, esta tem sido em todo código Lisp que eu já vi.

O que ele faz?

Foi útil?

Solução

Resposta curta Bypass as regras de avaliação padrão e fazer não avaliar a expressão (símbolo ou s-exp), passando-o junto com a função exatamente como digitado.

Long Resposta: O padrão Regra Avaliação

Quando um regular (eu vou chegar a isso mais tarde) função é chamada, todos os argumentos passados ??para ele são avaliados. Isto significa que você pode escrever o seguinte:

(* (+ a 2)
   3)

que por sua vez avalia (+ a 2), avaliando a e 2. O valor do símbolo a é procurado no conjunto de ligação variável atual, em seguida, substituído. Say a está ligado ao valor 3:

(let ((a 3))
  (* (+ a 2)
     3))

Teríamos (+ 3 2), + é então invocado em 3 e 2 rendendo 5. Nossa forma original está agora (* 5 3) produzindo 15.

Explique quote já!

Tudo bem. Como visto acima, são avaliados todos os argumentos para uma função, por isso, se você gostaria de passar o símbolo a e não o seu valor, você não quer para avaliá-lo. símbolos Lisp pode dobrar tanto como os seus valores, e marcadores onde em outros idiomas teria usado cordas, tais como chaves para tabelas de hash.

Este é o lugar onde quote entra. Digamos que você queira alocações de recursos enredo de um aplicativo Python, mas sim fazer a plotagem em Lisp. Ter o seu Python aplicativo fazer algo como isto:

print("'(")
while allocating:
    if random.random() > 0.5:
        print(f"(allocate {random.randint(0, 20)})")
    else:
        print(f"(free {random.randint(0, 20)})")
    ...
print(")")

Dando-lhe a saída parecido com isto (um pouco prettyfied):

'((allocate 3)
  (allocate 7)
  (free 14)
  (allocate 19)
  ...)

Lembre-se que eu disse sobre quote ( "tick") fazendo com que a regra padrão não aplicar? Boa. O que, de outro modo acontecer é que os valores de allocate e free são olhou para cima, e nós não queremos isso. Em nossa Lisp, queremos fazer:

(dolist (entry allocation-log)
  (case (first entry)
    (allocate (plot-allocation (second entry)))
    (free (plot-free (second entry)))))

Para os dados dada acima, a seguinte seqüência de chamadas de função teria sido feito:

(plot-allocation 3)
(plot-allocation 7)
(plot-free 14)
(plot-allocation 19)

Mas What About list?

Bem, às vezes você do quer avaliar os argumentos. Digamos que você tenha uma função bacana manipular um número e uma string e retornar uma lista dos resultantes ... coisas. Vamos fazer uma falsa partida:

(defun mess-with (number string)
  '(value-of-number (1+ number) something-with-string (length string)))

Lisp> (mess-with 20 "foo")
(VALUE-OF-NUMBER (1+ NUMBER) SOMETHING-WITH-STRING (LENGTH STRING))

Hey! Isso não é o que queríamos. Queremos seletivamente avaliar alguns argumentos, e deixar os outros como símbolos. Tente # 2!

(defun mess-with (number string)
  (list 'value-of-number (1+ number) 'something-with-string (length string)))

Lisp> (mess-with 20 "foo")
(VALUE-OF-NUMBER 21 SOMETHING-WITH-STRING 3)

Não apenas quote, Mas backquote

Muito melhor! Aliás, este padrão é tão comum na (principalmente) macros, que há sintaxe especial para fazer exatamente isso. A crase:

(defun mess-with (number string)
  `(value-of-number ,(1+ number) something-with-string ,(length string)))

É como usar quote, mas com a opção de avaliar explicitamente alguns argumentos prefixando-os com vírgulas. O resultado é equivalente a usar list, mas se você é gerar código a partir de uma macro muitas vezes você só quer avaliar pequenas partes do código retornado, assim que a crase é mais adequado. Para listas mais curtas, list pode ser mais legível.

Ei, você esqueceu Sobre quote!

Então, onde é que isto deixa-nos? Ah, certo, o que quote realmente fazer? Ele simplesmente retorna seu argumento (s) unevaluated! Lembra o que eu disse no início sobre as funções regulares? Acontece que alguns operadores / funções precisam não avaliar os seus argumentos. Tal como se - você não gostaria que o ramo mais havendo a ser avaliadas se não foi tomada, certo? O chamado operadores especiais , juntamente com macros, o trabalho assim. operadores especiais também são o "axioma" da língua - conjunto mínimo de regras - sobre o qual você pode implementar o resto do Lisp, combinando-os juntos em maneiras diferentes.

Voltar para quote, no entanto:

Lisp> (quote spiffy-symbol)
SPIFFY-SYMBOL

Lisp> 'spiffy-symbol ; ' is just a shorthand ("reader macro"), as shown above
SPIFFY-SYMBOL

Comparar a (em aço-Bank Lisp comum):

Lisp> spiffy-symbol
debugger invoked on a UNBOUND-VARIABLE in thread #<THREAD "initial thread" RUNNING   {A69F6A9}>:
  The variable SPIFFY-SYMBOL is unbound.

Type HELP for debugger help, or (SB-EXT:QUIT) to exit from SBCL.

restarts (invokable by number or by possibly-abbreviated name):
  0: [ABORT] Exit debugger, returning to top level.

(SB-INT:SIMPLE-EVAL-IN-LEXENV SPIFFY-SYMBOL #<NULL-LEXENV>)
0] 

Devidonão há spiffy-symbol no escopo atual!

Resumindo

quote, backquote (com vírgula), e list são algumas das ferramentas que você usa para criar listas, que não são apenas listas de valores, mas como você visto pode ser usado como leve (sem necessidade de definir uma struct) dados estruturas!

Se você quiser saber mais, eu recomendo o livro de Peter Seibel Prático Lisp comum para uma abordagem prática para aprender Lisp , se você já está na programação em geral. Eventualmente em sua jornada Lisp, você vai começar a usar pacotes também. Guia do Idiot de Ron Garret para Common Lisp Pacotes vai lhe dar boa explicação desses.

Happy Hacker!

Outras dicas

Ele diz "não me avaliar". Por exemplo, se você quisesse usar uma lista como dados, e não como código, você iria colocar uma citação na frente dele. Por exemplo,

(print '(+ 3 4)) impressões "(+ 3 4)", enquanto impressões (print (+ 3 4)) "7"

Outras pessoas responderam a esta pergunta admiravelmente, e Matthias Benkard traz uma excelente aviso.

Não use QUOTE para criar listas que serão, posteriormente modificar. A especificação permite que o compilador para listas tratar citado como constantes. Muitas vezes, um compilador irá otimizar constantes através da criação de um único valor para eles na memória e, em seguida, fazer referência a esse único valor a partir de todos os locais onde a constante aparece. Em outras palavras, pode tratar a constante como uma variável global anônimo.

Isto pode causar problemas óbvios. Se você modificar uma constante, pode muito bem modificar outros usos da mesma constante no código completamente alheios. Por exemplo, você pode comparar algumas variáveis ??para '(1 1) em alguma função, e em uma função completamente diferente, iniciar uma lista com' (1 1) e, em seguida, adicionar mais coisas para ele. Após executar essas funções, você pode achar que a primeira função não coincide com as coisas corretamente mais, porque agora está tentando comparar a variável '(1 1 2 3 5 8 13), que é o que a segunda função retornado. Estas duas funções são completamente independentes, mas eles têm um efeito sobre o outro por causa do uso de constantes. Ainda mais louco efeitos ruins podem acontecer, como uma lista perfeitamente normal iteração looping repente infinito.

Use citação quando você precisa de uma lista constante, como para comparação. Use lista quando você estará modificando o resultado.

Uma resposta a esta pergunta diz que QUOTE “cria estruturas de dados da lista”. Isso não está certo. QUOTE é mais fundamental do que isso. Na verdade, CITAÇÕES é um operador trivial: Sua finalidade é evitar qualquer coisa aconteça em tudo. Em particular, ele não cria nada.

O que (citação X) diz é basicamente “não faça nada, apenas me dar X.” X não necessita de ser uma lista como em (CITAÇÕES (A B C)) ou um símbolo como em (foo citação). Pode ser qualquer objeto que seja. Na verdade, o resultado da avaliação da lista que é produzido por (LIST 'CITAÇÕES SOME-objeto) será sempre apenas retornar algum a objeto, seja ele qual for.

Agora, a razão que (QUOTE (A B C)) parece como se criou uma lista cujos elementos são A, B, e C é que essa lista é realmente o que ele retorna; mas no momento que o formulário de cotação é avaliada, a lista tem, em geral já existe há algum tempo (como um componente do formulário de cotação!), criadas tanto pelo carregador ou o leitor antes da execução do código.

Uma implicação disso que tende a viagem até novatos com bastante frequência é que é muito imprudente para modificar uma lista retornada por um formulário de cotação. Os dados retornados por citação é, para todos os efeitos, a ser considerado como parte do código que está sendo executado e deve, portanto, ser tratado como somente leitura!

A execução cotação impede ou avaliação de uma forma, transformando-o em vez em dados. Em geral, você pode executar os dados até então eval'ing-lo.

Citação cria estruturas de dados da lista, por exemplo, a seguir são equivalentes:

(quote a)
'a

Ele também pode ser usado para criar listas (ou árvores):

(quote (1 2 3))
'(1 2 3)

Você é provavelmente melhor fora de começar um livro introductary em Lisp, como Common Lisp Prático (que é disponível para leitura on-line).

Quando queremos passar um argumento em si em vez de passar o valor do argumento, em seguida, usamos cotação. Ele está principalmente relacionado com o procedimento de passagem durante a utilização listas, e pares de átomos que não estão disponíveis em C Programming Language (a maioria das pessoas começar a programar usando programação C, daí ficamos confusos) Este é o código em linguagem de programação Scheme que é um dialeto do Lisp e eu acho que você pode entender esse código.

(define atom?              ; defining a procedure atom?
  (lambda (x)              ; which as one argument x
(and (not (null? x)) (not(pair? x) )))) ; checks if the argument is atom or not
(atom? '(a b c)) ; since it is a list it is false #f

A última linha (átomo? 'Abc) está passando abc como é o procedimento para verificar se abc é um átomo ou não, mas quando você passa (átomo? Abc), em seguida, ele verifica o valor da abc e passses o valor a ele. Desde então, nós não forneceram qualquer valor a ele

Em Emacs Lisp:

O que pode ser citado?

Listas e símbolos.

Citando um número avaliada como o próprio número: '5 é o mesmo que 5.

O que acontece quando você cita listas?

Por exemplo:

'(one two) avalia a

(list 'one 'two) que avalia a

(list (intern "one") (intern ("two"))).

(intern "one") cria um símbolo chamado "um" e as armazena em um hash-map "central", assim quando você diz 'one então o símbolo chamado "one" será procurado em que hash mapa central.

Mas o que é um símbolo?

Por exemplo, em OO-línguas (Java / JavaScript / Python) um símbolo pode ser representado como um objeto que tem um campo name, que é o nome do símbolo, como "one" acima, e dados e / ou código pode ser associado com que este objeto.

Assim, um símbolo em Python pode ser implementada como:

class Symbol:
   def __init__(self,name,code,value):
       self.name=name
       self.code=code
       self.value=value

Em Emacs Lisp por exemplo, um símbolo pode ter 1) dados associados com ele e (ao mesmo tempo - para o mesmo símbolo) 2) código associado com ele - dependendo do contexto, tanto os dados ou o código é chamado .

Por exemplo, em Elisp:

(progn
  (fset 'add '+ )
  (set 'add 2)
  (add add add)
)

avalia a 4.

Como avalia (add add add) como:

(add add add)
(+ add add)
(+ 2 add)
(+ 2 2)
4

Assim, por exemplo, usando a classe Symbol definimos em Python acima, esta add elisp-Símbolo poderia ser escrito em Python como Symbol("add",(lambda x,y: x+y),2).

Muitos agradecimentos para pessoas em #emacs IRC para explicar símbolos e citações para mim.

Citar retorna a representação interna de seus argumentos. Depois de arar através de maneira muitas explicações do que Citação não fazer, que é quando a luz-bulbo continuou. Se o REPL não converter nomes de função para maiúsculas quando citei-los, não poderia ter me dei conta.

Então. funções Lisp comuns converter seus argumentos em uma representação interna, avaliar os argumentos, e aplicar a função. Quote converte seus argumentos para uma representação interna, e retorna apenas isso. Tecnicamente é correto dizer que a citação diz: "não avaliar", mas quando eu estava tentando entender o que ele fez, me dizendo o que ele não faz foi frustrante. Meu torradeira não avaliar funções Lisp qualquer um; mas isso não é como você explicar o que uma torradeira faz.

Anoter resposta curta:

meios quote sem avaliá-lo, e backquote é citação, mas a licença portas traseiras .

Um bom referrence:

Manual Emacs Lisp Referência deixar muito claro

9.3 Citando

A citação forma especial retorna seu único argumento, como está escrito, sem avaliação. Isso fornece uma maneira de incluir símbolos constantes e listas, que não são objetos de auto-avaliação, em um programa. (Não é necessário citar a auto-avaliação de objetos, tais como números, strings e vetores.)

forma especial: Citação objeto

This special form returns object, without evaluating it. 

Como citações são usadas muitas vezes em programas, Lisp fornece uma sintaxe leitura conveniente para ele. Um caractere de apóstrofo ( ‘'’), seguido por um objeto Lisp (na sintaxe leitura) expande a uma lista cujo primeiro elemento é citação e, cujo segundo elemento é o objeto. Assim, a sintaxe leitura 'x é uma abreviatura para (citação x).

Aqui estão alguns exemplos de expressões que o uso Citação:

(quote (+ 1 2))
     ⇒ (+ 1 2)

(quote foo)
     ⇒ foo

'foo
     ⇒ foo

''foo
     ⇒ (quote foo)

'(quote foo)
     ⇒ (quote foo)

9.4 crase

crase construções permitir-lhe citar uma lista, mas avaliar seletivamente elementos dessa lista. No caso mais simples, é idêntica à cotação de forma especial (descrito na seção anterior, ver Citando). Por exemplo, estas duas formas de produzir resultados idênticos:

`(a list of (+ 2 3) elements)
     ⇒ (a list of (+ 2 3) elements)

'(a list of (+ 2 3) elements)
     ⇒ (a list of (+ 2 3) elements)

O marcador especial ‘’ dentro do argumento para backquote indica um valor que não é constante. O avaliador Emacs Lisp avalia o argumento de ‘’ e coloca o valor na estrutura de lista:

`(a list of ,(+ 2 3) elements)
     ⇒ (a list of 5 elements)

Substituição com ‘’ é permitida em níveis mais profundos da estrutura lista também. Por exemplo:

`(1 2 (3 ,(+ 4 5)))
     ⇒ (1 2 (3 9))

Você também pode emendar um valor avaliado na lista resultante, utilizando o marcador especial ‘@’. Os elementos da lista emendados se tornar elementos ao mesmo nível que os outros elementos da lista resultante. O código equivalente sem usar ‘`’é muitas vezes ilegível. Aqui estão alguns exemplos:

(setq some-list '(2 3))
     ⇒ (2 3)

(cons 1 (append some-list '(4) some-list))
     ⇒ (1 2 3 4 2 3)

`(1 ,@some-list 4 ,@some-list)
     ⇒ (1 2 3 4 2 3)
Code is data and data is code.  There is no clear distinction between them.

Esta é uma afirmação clássica qualquer programador Lisp sabe.

Quando você cita um código, este código será de dados.

1 ]=> '(+ 2 3 4)
;Value: (+ 2 3 4)

1 ]=> (+ 2 3 4)
;Value: 9

Quando você cita um código, o resultado será de dados que representam esse código. Então, quando você quer trabalhar com dados que representam um programa que você citar esse programa. Isso também é válido para expressões atômicas, não só para listas:

1 ]=> 'code
;Value: code

1 ]=> '10
;Value: 10

1 ]=> '"ok"
;Value: "ok"

1 ]=> code
;Unbound variable: code

Supondo que você deseja criar uma linguagem de programação incorporado em lisp - você vai trabalhar com programas que são citados no esquema (como '(+ 2 3)) e que são interpretados como código na linguagem que você cria, dando programas de uma interpretação semântica. Neste caso, você precisará usar citação para manter os dados, caso contrário ele será avaliado em linguagem externa.

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