Dot notação no esquema

Eu sou um iniciante em programação Scheme. Eu sei que a notação de ponto em Scheme é usada para apresentar um par de símbolos, por exemplo '(a . b) .

O primeiro elemento pode ser um símbolo ou uma lista, não importa. Mas especialmente o segundo elemento deve ser um símbolo, se não for, pode ser uma lista, por exemplo, então não podemos criar um par com o procedimento de cons embutido.

Então é possível criar um par de 2 listas? Bem, eu estou pensando em uma solução é que a conversão de uma lista para símbolo, mas na verdade essas são duas coisas completamente diferentes -> impossível, como eu entendo.

Este é o código que eu escrevi:

 (define compare-attrs (lambda (attribute1 attribute2) (if (or (and (null? attribute1) (null? attribute2)) (and (not (null? attribute1)) (not (null? attribute2)))) (cons attribute1 attribute2) #f))) 

Em que attribute1 e attribute2 são 2 listas e minha saída é:

 attribute1 atrribute2 

Saída esperada: ‘(atributo1. Atributo2)

Por favor, explique isso. Agradeço antecipadamente!!!

EDIT: adicionando o uso da function compare-attrs

A function compare-attrs usada para extrair a parte que descreve os atributos das entidades e os cons para fazer um par, entidades definidas definidas abaixo:

 (entity e0 (prov:label "entity e0") (entity e1 (prov:location "London") 

Portanto, atributos dessas entidades são (prov:label "entity e0") e (prov:location "London") . Quando aplicar a function compare-attrs, porque esses atributos não são null , de modo que a saída que eu espero é

 `(prov:label "entity e0") . (prov:location "London")` 

Nota: isso é canibalizado de uma resposta ao intervalo recursivo em Lisp adiciona um período? , o que é realmente uma pergunta diferente. No entanto, a explicação de como os pares são impressos é a mesma. O resto da resposta é diferente.

Sua pergunta exibe um pouco de mal-entendido, mas acho que podemos esclarecer isso.

O primeiro [argumento a cons ] poderia ser um símbolo ou uma lista, não importa. Mas especialmente o segundo elemento deve ser um símbolo, se não for, pode ser uma lista, por exemplo, então não podemos criar um par com o procedimento de cons embutido.

Isso não está correto. Você pode chamar cons com qualquer argumento que você gosta, e você sempre receberá de volta um cons culo cujo car é o mesmo que o primeiro argumento para cons , e cujo cdr é o mesmo que o segundo argumento para cons . Ou seja, a única coisa importante sobre os cons é que ela satisfaz as equações

 (eq? a (car (cons ab)) (eq? b (cdr (cons ab)) 

Então é possível criar um par de 2 listas? Bem, eu estou pensando em uma solução é que a conversão de uma lista para símbolo, mas na verdade essas são duas coisas completamente diferentes -> impossível, como eu entendo.

É bem possível; Se você tem duas listas, por exemplo, list1 e list2 , você pode criar um par cujo car é list1 e cujo cdr é list2 apenas chamando (cons list1 list2) . Agora, acho que o problema que você está enfrentando é que você está esperando ver ( . ) como a saída, e você está vendo algo diferente. Para explicar por que isso acontece, precisamos entender como as listas são representadas em Lisps e como os pares são impressos.

Uma lista em Scheme é a lista vazia () (também conhecida como nil em alguns Lisps), ou uma célula cons cujo car (também conhecido como first ) é um elemento da lista e cujo cdr (também conhecido como rest ) é ou o resto da lista (ou seja, outra lista), ou um átomo que termina a lista. O terminador convencional é a lista vazia () ; listas terminadas por () são consideradas “listas adequadas”. As listas terminadas por qualquer outro átomo são chamadas de “listas impróprias”. A lista (1 2 3 4 5) contém os elementos 1, 2, 3, 4 e 5 e é finalizada por () . Você poderia construí-lo por

 (cons 1 (cons 2 (cons 3 (cons 4 (cons 5 ()))))) 

Agora, quando o sistema imprime uma célula cons, o caso geral é imprimi-lo por

 (car . cdr) 

Por exemplo, o resultado de (cons 1 2) é impresso como

 (1 . 2) 

Como as listas são construídas de células de cons, você também pode usar essa notação para listas:

 '(1 2 3 4 5) == '(1 . (2 . (3 . (4 . (5 . ()))))) 

Isso é meio desajeitado, então, a maioria dos lisps (tudo o que eu sei) tem um caso especial para imprimir células cons: se o cdr for uma lista (ou outra célula cons ou () ), então não imprima o arquivo . e não imprima os parênteses ao redor do cdr (o que, de outra forma, teria, já que é uma lista).

Agora podemos explicar porque o resultado de (cons list1 list2) não se parece ( . ) . Se você chamar cons com duas listas, você recebe de volta um par com o car e cdr esperados, mas não é impresso com o . notação. Por exemplo,

 (cons '(1 2 3) '(abc)) ;=> ((1 2 3) . (abc)) ; which is typically *printed* as ;=> ((1 2 3) abc) 

Mas, novamente, a representação impressa realmente não importa, desde que as seguintes equações sejam válidas:

 (eq? a (car (cons ab)) (eq? b (cdr (cons ab)) 

Com certeza:

 (car (cons '(1 2 3) '(abc))) ;=> (1 2 3) (cdr (cons '(1 2 3) '(abc))) ;=> (abc) 

No exemplo específico sobre o qual você está perguntando, considere o que acontece quando você liga

 (cons '(prov:label "entity e0") '(prov:location "London")) 

O resultado é, de fato,

 ((prov:label "entity e0") . (prov:location "London")) 

mas, por causa das regras de impressão, isso é impresso como

 ((prov:label "entity e0") prov:location "London") 

No entanto, você ainda pode obter os dois atributos usando car and cdr :

 (car '((prov:label "entity e0") prov:location "London")) ;=> (prov:label "entity e0") (cdr '((prov:label "entity e0") prov:location "London")) ;=> (prov:location "London") 

e isso é tudo que você realmente precisa para poder fazer mais tarde.

A notação de ponto no Scheme ou qualquer outro dialeto LISP para esse assunto é usada para criar um par pontilhado de quaisquer dois valores. Os valores podem ser símbolos, listas ou qualquer outra coisa. Realmente não importa qual valor é. Por exemplo:

 '(author . aaditmshah) => (author . aaditmshah) '((abc) . (def)) => ((abc) def) 

Como você pode ver se você criar um par pontilhado de duas listas, a primeira lista será adicionada à cabeça da segunda lista. Isso ocorre porque as listas no LISP são pares de pontos nesteds:

 '(a . (b . (c . ()))) => '(abc) 

Portanto, quando você escreve '((abc) . (def)) é como se você estivesse escrevendo o seguinte:

 '((abc) . (d . (e . (f . ())))) => '((abc) def) 

Isso é perfeitamente válido. Você ainda pode acessar ambas as listas individualmente usando car e cdr como faria normalmente:

 (car '((abc) . (def))) => (abc) (cdr '((abc) . (def))) => (def) 

Eu não tenho certeza do que sua function compare-attrs deve fazer. Sua ramificação if retorna uma célula cons enquanto sua ramificação else retorna um booleano. Para mim isso não faz absolutamente nenhum sentido. O tipo de retorno da function deve ser constante.

Talvez você não tenha redigido sua pergunta corretamente porque não tenho certeza de qual é o seu problema. Deixe-me saber se você ainda tem alguma dúvida.

Minha lembrança sobre a estruturação de dados no esquema é que você preferiria evitar um par de átomos pontilhados (isto é, (a . b) ), pois isso representa o resultado de se considerar dois átomos juntos. Se você olhar no The Little Schemer , página 3, você verá isto:


A lei dos cons

Os contras primitivos levam dois argumentos. O segundo argumento para os contras deve ser uma lista. O resultado é uma lista.


se você leu as outras respostas, sabe que isso não é verdade. Então, honestamente, a coisa a fazer com a estruturação de dados do Scheme, que é proscrita pelo SICP , é definir o layout da estrutura de dados em termos de listas e, em seguida, fazer pequenas funções para atuar como os acessadores.

Então, digamos que você queira ter uma tupla – você pode fazer com que pareça (ab) que é totalmente razoável. Então você poderia escrever estas funções:

 (define (make-tuple ab) (list ab)) (define (tuple-first tup) (car tup)) (define (tuple-second tup) (car (cdr tup))) (define (tuple? tup) (and (list? tup) (eq? 2 (length tup)))) 

que agora me dá funções de accessr e um construtor e eu sou ouro. Mas isso não quer dizer que esta é a única maneira de fazer isso. Você poderia ir em frente e usar pares também:

 (define (make-tuple ab) (cons ab)) (define (tuple-first tup) (car tup)) (define (tuple-second tup) (cdr tup)) (define (tuple? tup) (pair? tup)) 

Então, no seu código, você pode usar o construtor aqui para fazer a tupla que você quer.

Em geral, a function compare-attrs é estranha porque o nome não nos dá uma ideia do que você está tentando fazer. Eu estaria mais inclinado a escrever assim:

 (define (compare-attrs a1 a2) (or (and (null? a1) (null? a2)) (and (not (null? a1)) (not (null? a2))) )) (define (join-populated-attrs a1 a2) (if (compare-attrs a1 a2) (make-tuple a1 a2) '())) 

o que ainda é engraçado porque você está aceitando dois atributos nulos, mas isso provavelmente faz parte do seu domínio de todos os problemas.

Eu também devo dizer que se você quer que a saída apareça de uma maneira particular, você provavelmente deveria escrever print-tuple também.