Tradicionalmente, em Prolog, strings são uma lista de caracteres e caracteres são inteiros pequenos.
A = `abc efg 123`.
Implementação é um problema. SWI modificou o Prolog para que strings sejam um tipo básico (mas que pode ser convertido para listas).
manual do swiprolog para strings
A = "abc efg 123".
Entre "
é o tipo novo com predicados para processar esse tipo
string_concat
split_string
sub_string
Ha na verdade 2 representações de caracteres
codes
são os inteiros pequenos
chars
são simbolos cujo nome é apenas a letra
string_codes("abc efg 123",B).
string_chars("abc efg 123",B).
Leitura de baixo nivel (por caracter) manual
Leitura de termos de prolog completos (terminados por ponto). read
read(X).
SWI prolog tem um predicado read_string
que le strings (internos do SWIProlog).
writef
e format
Builtin predicates (ja predefinidos) https://www.swi-prolog.org/pldoc/man?section=builtin
vs
Bibliotecas https://eu.swi-prolog.org/pldoc/man?section=libpl
vs
Pacotes https://www.swi-prolog.org/pack/list
http://chiselapp.com/user/ttmrichter/repository/gng/doc/trunk/output/tutorials/swiplmodtut.html
Não há uma biblioteca padrão para todas as implementações de prolog.
:- use_module(library(lists)).
útil sort
e a ordem total @<
Prolog permite definir predicados. Qualquer linguagem permite definir funções. Mas é possível definir novos operadores e novos commandos?
sintaxe: f(x,y)
versus x + y
operadores são normalmente infixos (alguns prefixos -
, +
). Posfixos? ++
em C
operadores tem prioridades/precedencia x + y * z
operadores tem associatividade x+y+z
? = (x+y)+z
left, ou x+(y+z)
right.
Operadores aritméticos são normalmente left associative
2^3^4
é right associative = 2^(3^4)
= 2^{3^4}
prolog: comando op
https://www.swi-prolog.org/pldoc/man?predicate=op/3 permite definir predicados e functor como operadodes, definir o tipo (infixo, prefixo, posfixo, e a associatividade).
:- op(200,xfy,pai).
joao pai antonio. em vez de pai(joao,antonio)
antonio pai maria.
dynamic pai/2
dynamic é um operador prefixo (de 1 argumento).
outras linguagens permitem definir operadores (infixos)
R (nao sei se da para definir prioridade)
haskell (em haskell funções binarias automaticamente definem uma versão infixa mas haskell permite definir operadores diretamente =>>
).
alem de uma sintaxe diferente, comandos podem ter uma semântica diferente
ifelse(cond, then, else)
nao pode ser uma função tradicional!
ifelse(5>9, 1/0, 99)
deve dar 99 e não erro, mas se ifelse é uma função todos seus argumentos são avaliados/rodados (como em qualquer função).
assim linguagens tradicionais não permitem definir coisas que se parecem com novos comandos (no sentido que não avaliam seus argumentos sempre)
haskell (e outras linguagens com lazy evaluation (R?) ) permitem! Nenhum argumento é avaliado!
prolog permite, pois não ha avaliação dos argumentos de um predicados conta(R,ACC+1)
não funciona!
:- op(1050,xfy,->).
Cond -> Then :- call(Cond),!,call(Then).
isso nao é 100% certo - ha uma discussão sutil em https://www.swi-prolog.org/pldoc/man?predicate=-%3E/2
Comandos tem uma versão mais forte que apenas avaliação não tradicional dos argumentos. Voce pode quere acesso as proprias expressoes dos parametros mas para isso expressoes precisam ser vistas como dados do programa - veremos isso em Lisp.
Lembre-se que o append
em linguagens que tem lista como tipos predefinidos, demora O(n) onde n é o tamanho da 1a lista
Mesmo em C, voce precisa percorrer a lista para chegar ao ultimo apontador (que aponta para NULL
) e troca-lo para apontar para a 2a lista.
Códigos iterativos ou recursivos que repetidamente chamam o append tem complexidade quadrática quando o problema poderia ser resolvido com complexidade linear.
reverte([],[]).
reverte([X|R],Y) :- reverte(R,RR), append(RR,[X],Y).
Diference list é a ideia de criar uma lista com uma variavel sem valor como ultimo elemento. Assim appendar a esta lista é setar essa variável para a nova lista
d(L,X) = [1,2,3|X]
difappend(d(L1,R1), d(L2,R2), RESPOSTA) :- R1 = L2,
RESPOSTA =d(L1,R2).
difappend([1,2,3|R1], [4,5,6|R2, [1,2,3,4,5,6|R2])
normalmente usa-se o functor -
infixo [1,2,3|R1] - R1
em vez de d
Usar o prolog para fazer analise sintática de textos cuja gramatica é representada por regras livres de contexto
-https://www2.cs.arizona.edu/~collberg/Teaching/372/2010/Handouts/Handout-26.pdf
Como quase tudo em prolog a representação da solução/gramatica é simples. A busca de uma solução pode ser exponencial.
https://en.wikipedia.org/wiki/Constraint_logic_programming
is
em prolog quebra as simetrias. Voce precisa ter o lado direito com todos os valores para calcular e unificar com o lado esquerdo
X is Y + 2.
se Y=4 então eu atribuo X = 6
mas seria interessante se sabendo que X = 6, o programa pudesse inferir que Y deve assumir o valor 4.
Ou seja, seria bom se X is Y+2
fosse uma relação matemática/aritmética e não uma instrução de computação.
se X e Y não tem valor, X=Y
indica que X e Y estão numa relação matemática, dado 1 eu consigo inferir (determinar) o outro.
Mas X \= Y
nao é a mesma coisa. Isso só vai dar certo se ambos tiverem valor e esses valores não forem iguais.
CLP estende o Prolog para raciocinar sobre desigualdade e sobre “algumas” operações matemática.
parece que CLP é especifico para dominios de valores das variáveis
booleano
finite domain
integer (?)
rational
reais
https://www.swi-prolog.org/pldoc/man?section=clpb
CLP usado em verificação - listas as restriçoes e vefica que há alguma solução.
CLP em otimização https://developers.google.com/optimization/cp