Variáveis Compartilhadas e Anônimas em Prolog

filósofo
Agora que já sabemos fazer consultas básicas com variáveis, vamos explorar dois conceitos fundamentais: variáveis compartilhadas (que conectam diferentes partes de uma consulta) e a variável anônima (que ignora valores que não nos interessam). Entender esses dois tipos de variáveis é essencial para escrever consultas poderosas e elegantes em Prolog.

0. Revisão: variáveis em consultas

Como vimos no artigo anterior, variáveis em Prolog começam com letra maiúscula (ex: X, Pessoa, Filho) e representam valores desconhecidos que o sistema tenta descobrir através da unificação.

Atualise o arquivo familia.pl

Como atualizar:

      1. Edite familia.pl (Em SWI opção Edit)
      2. Salve as alterações (No arquivo pl opção Save buffer)
      3. Em SWI-Prolog dê “Reload modified files”
      4. Agora suas alterações serão percebidas no SWI

Mas o que acontece quando usamos a mesma variável em diferentes partes da consulta? E como podemos “ignorar” um valor que não nos interessa? É exatamente isso que vamos explorar agora!

1. Variáveis Compartilhadas: conectando objetivos

Uma variável compartilhada é uma variável que aparece em múltiplos objetivos (subconsultas) dentro de uma mesma consulta. Quando a mesma variável aparece em lugares diferentes, o Prolog exige que ela tenha o mesmo valor em todos os lugares.

🧩 Ideia central: Variáveis compartilhadas são a “cola” que conecta diferentes partes da sua consulta. Elas permitem que você expresse relações complexas como “X é pai de Y e Y é pai de Z” — onde Y é compartilhado entre os dois objetivos.

Exemplo clássico: “Quem é o avô de Enos?”

Para descobrir o avô de Enos, precisamos encontrar alguém que seja pai do pai de Enos. Em Prolog, isso se traduz em dois objetivos com uma variável compartilhada:

Aqui, a variável Y é compartilhada entre os dois objetivos. Ela representa o “pai de Enos” no primeiro objetivo e o “filho de X” no segundo. O Prolog precisa encontrar um valor para Y que satisfaça ambas as condições.

2. Como o Prolog resolve essa consulta (passo a passo)

Passo 1: O Prolog começa com o primeiro objetivo: pai(Y, enos). Ele procura na base de fatos por um pai cujo segundo argumento seja enos.
Passo 2: Com Y = seth, o Prolog agora tenta resolver o segundo objetivo: pai(X, seth). Ele procura por alguém que seja pai de Seth.
Passo 3: O Prolog unifica X = adão e apresenta a resposta.
💡 Observação importante: A ordem dos objetivos importa! Se escrevêssemos pai(X, Y), pai(Y, enos), o Prolog começaria procurando um pai X de Y (qualquer um), depois verificaria se Y é pai de Enos. O resultado seria o mesmo, mas a ordem pode afetar a eficiência.

3. Por que variáveis compartilhadas são importantes?

Variáveis compartilhadas são a base para construir consultas multi-objetivo em Prolog. Elas permitem:

  • Encadear relações: avô, bisavô, irmão, tio, etc.
  • Filtrar resultados: encontrar pessoas que satisfazem múltiplas condições.
  • Comparar valores: verificar se duas variáveis têm o mesmo valor.
  • Expressar restrições: “X é pai de Y E Y é pai de Z” → X é avô de Z.

Sem variáveis compartilhadas, cada objetivo seria independente e não poderíamos expressar relações entre eles.

4. A Variável Anônima (_): quando o valor não importa

Às vezes, queremos fazer uma pergunta onde um dos valores não nos interessa. Por exemplo: “Quem já foi pai (de alguém)?” — não importa quem é o filho, só queremos saber os pais.

Para isso, usamos a variável anônima, representada por um underscore (_). Ela diz ao Prolog: “Ignore este valor; não me importa qual é.”

✨ Características da variável anônima:
  • Começa com _ (ex: _, _Algo).
  • Cada ocorrência de _ é independente — duas ocorrências de _ não são compartilhadas.
  • Não gera respostas (o Prolog não mostra seu valor).
  • Não unifica com outras variáveis (cada _ é único).

Exemplo: “Quem já procriou?” (quem é pai de alguém)

O Prolog encontra todas as pessoas que aparecem como primeiro argumento de pai/2, independentemente de quem é o filho. O _ simplesmente “engole” o segundo argumento.

⚠️ Atenção: Cada ocorrência de _ é independente. Em pai(_, _), a primeira ocorrência ignora o pai e a segunda ignora o filho — a consulta pergunta “existe alguma relação pai/2?” e sempre retorna true.

5. Variável Anônima vs. Variável Nomeada: qual a diferença?

CaracterísticaVariável Nomeada (X, Y)Variável Anônima (_)
SintaxeComeça com maiúsculaComeça com _
CompartilhamentoO mesmo nome = mesma variável (compartilhada)Cada _ é independente
Aparece na respostaSim, o valor é mostradoNão, o valor é ignorado
Quando usarQuando o valor é importante ou precisa ser compartilhadoQuando o valor não importa ou você quer evitar respostas desnecessárias
Exemplopai(X, abel) → mostra quem é o paipai(_, abel) → pergunta “Abel tem pai?” (true/false)

Exemplo comparativo

6. Variável anônima com nome: _Algo

Você pode usar _ seguido de um nome (ex: _Filho) para indicar que o valor não importa, mas quer dar um nome descritivo para melhor legibilidade. O comportamento é o mesmo: a variável é anônima e não gera respostas.

Neste caso, _Filho é anônima (começa com _), mas o nome ajuda a entender que se trata do filho. O Prolog não mostrará o valor de _Filho.

7 Quando usar cada tipo de variável?

Use variável nomeada (compartilhada) quando:

  • Você precisa conectar diferentes partes da consulta.
  • O valor da variável é importante e você quer vê-lo na resposta.
  • Você quer comparar valores entre diferentes objetivos.

Use variável anônima (_) quando:

  • O valor não é relevante para a resposta (ex: “quem é pai de alguém?”).
  • Você quer evitar poluir a resposta com valores desnecessários.
  • Você está fazendo uma consulta de “existência” (true/false).
  • Quer melhorar a legibilidade sem gerar respostas extras.

Resumo:

  • Variáveis compartilhadas (mesmo nome em múltiplos objetivos) permitem encadear relações e expressar consultas complexas.
  • Variáveis anônimas (_) ignoram valores que não nos interessam, tornando as consultas mais limpas e eficientes.
  • Escolher o tipo certo de variável torna suas consultas mais expressivas e fáceis de entender.

Consultas em Prolog: Perguntando ao Mundo

filósofo
Agora que já temos nossa base de fatos (a árvore genealógica), chegou a hora de fazer perguntas. Em Prolog, as consultas são a forma de interagir com o conhecimento que declaramos. Elas podem ser simples (sim/não) ou abertas, usando variáveis para descobrir relações. Neste artigo, vamos explorar o poder das consultas e entender como o motor do Prolog encontra respostas.

1. O que são consultas?

Uma consulta (ou goal) é uma pergunta que fazemos ao sistema Prolog. O motor de inferência tenta provar que a consulta é verdadeira, usando os fatos e regras disponíveis. Se conseguir, responde true (ou mostra os valores das variáveis); se não, responde false.

As consultas são feitas no prompt ?- do SWI-Prolog e são interativas — diferentemente dos fatos, que ficam salvos em arquivos. Elas são o seu “modo de conversa” com o conhecimento.

💡 Analogia: Se os fatos são como as frases de um livro, as consultas são as perguntas que você faz a um especialista que leu o livro. O especialista (Prolog) consulta a memória e responde.

2. Consultas com fatos concretos: o veredito yes/no

O tipo mais simples de consulta é perguntar sobre um fato específico que já declaramos. Por exemplo, usando nossa árvore genealógica (vamos supor uma base bíblica simples):

Arquivo genealogia.pl:

No SWI-Prolog, carregamos o arquivo:

Agora, consultas diretas:

⚠️ Importante: O Prolog só conhece o que você declarou. Se um fato não existe na base, a resposta é false — não importa se “no mundo real” é verdade. Você precisa declarar tudo o que quer que o sistema conheça.

3. Variáveis: perguntas abertas com X, Y, Pessoa

O verdadeiro poder das consultas aparece quando usamos variáveis. Uma variável em Prolog (sempre começando com maiúscula) representa um valor desconhecido que o sistema tentará descobrir.

Exemplo: “Quem é o pai de Abel?”

O que aconteceu? O Prolog procurou em todos os fatos pai/2 e encontrou pai(adao, abel). Ele então unificou a variável X com o átomo adao, e nos mostrou o resultado.

🧩 Unificação: É o processo de igualar uma consulta com um fato ou cabeça de regra, fazendo as substituições necessárias. Quando você pergunta pai(X, abel), o sistema diz: “Para provar isso, preciso encontrar um pai cujo segundo argumento seja abel; o primeiro argumento será o valor de X.” E encontra.

4. Múltiplas respostas: o ponto-e-vírgula (;) e o backtracking

E se houver mais de uma resposta? Exemplo: “Quem são os filhos de Adão?”

O mecanismo que permite isso é o backtracking: quando o Prolog encontra uma solução, ele a apresenta e “marca” o ponto onde parou. Se você pedir mais (;), ele volta atrás (desfaz a unificação) e procura outra solução.

⌨️ Como navegar pelas respostas:
  • Digite ; (ponto-e-vírgula) → mostra a próxima solução.
  • Digite Enter (ou .) → para e aceita a solução atual.
  • Digite a → mostra todas as soluções de uma vez (útil para muitas respostas).
  • Digite Espaço → também avança para a próxima (funciona como ; em algumas versões).

Exemplo com muitas respostas:

Se você digitar a após a primeira resposta, ele exibe todas de uma vez:

5. Explorando a árvore genealógica com consultas

🔹 Quem são os filhos de Adão?

🔹 Quem é o pai de Enos?

🔹 Quem são os netos de Adão?

Para isso, precisamos de uma consulta com duas variáveis e uma condição implícita: o pai do neto deve ser filho de Adão.

Explicação: a vírgula (,) significa “e” (conjunção lógica). O Prolog tenta satisfazer ambas as condições.

🧠 Interpretação: A consulta pai(adao, Filho), pai(Filho, Neto) é lida como: “Existe um Filho que é filho de Adão e, para esse mesmo Filho, existe um Neto que é filho dele?” Isso nos dá os netos.

🔹 Quem são os bisnetos de Adão?

Perceba como as variáveis A e B são usadas para encadear as relações.

6. Consultas vs. Fatos: qual a diferença?

Fatos (no arquivo .pl)Consultas (no prompt)
Declarações permanentes de verdade.Perguntas temporárias ao sistema.
Fazem parte da base de conhecimento.Não alteram a base de conhecimento.
Escritas com ponto final (.) e minúsculas.Podem ter variáveis (maiúsculas) e terminam com ponto final também.
Exemplo: pai(adao, caim).Exemplo: ?- pai(adao, X).
📌 Importante: Você não pode digitar fatos diretamente no prompt esperando que eles fiquem salvos. Eles valem apenas para aquela sessão, a menos que você use assert/1 (que veremos depois). Para fatos permanentes, sempre use arquivos .pl.

7. 📝 Exercícios práticos para você

Use a base genealógica que criamos (ou a sua própria) e responda:

  1. Quem são os filhos de Sete?
  2. Quem é o avô de Cainã?
  3. Quem são todos os descendentes diretos (filhos, netos, bisnetos) de Adão? (Dica: use múltiplas variáveis).
  4. Existe alguém que seja pai de mais de um filho? Quem?
  5. Quantos filhos Noé tem? (Se não tiver nenhum, a resposta será false).
  6. Crie uma consulta que liste todas as relações pai/2 em ordem alfabética pelo nome do pai. (Dica: use findall/3 ou apenas listing(pai).).

Anote suas respostas e confira no SWI-Prolog. Lembre-se de usar ; para ver todas as soluções!

8. Resumo e próximos passos

O que aprendemos:

  • Consultas são perguntas feitas ao sistema no prompt ?-.
  • Consultas concretas retornam true ou false.
  • Variáveis (maiúsculas) permitem perguntas abertas, como “quem é o pai de X?”
  • O backtracking (com ;) encontra múltiplas respostas.
  • A unificação é o mecanismo que liga variáveis a valores.
  • Consultas são interativas; fatos são permanentes e ficam em arquivos.

Com as consultas, você já pode explorar toda a sua base de fatos. No próximo artigo, vamos aprender a criar regras — que são como “fatos derivados” — para responder perguntas mais complexas, como “quem são os avós?” ou “quem são os irmãos?”, sem precisar declarar cada relação explicitamente.