Prolog permite definir predicados. QQ 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 definit 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 :- Cond,!,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 variavel 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
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 (?)