Aula 13

Prolog interativo

Numeros em Prolog

A coisa mais importante é que expressões matematicas só são calculadas em 2 contextos

X*4/Y > Z**2
X is Y+2

is calcula o valor do lado direito e unifica com o lado esquerdo.

Expressões podem não dar certo em tempo de execução pois algumas variáveis podem não ter valor no momento da execução

Isso vai dar um erro

Y is X+2, X = 2

Isso vai dar algo estranho:

X = 4, Y = X+2

NAO use o = numa expressão matemática.

Isso é equivalente:

X = 2
X is 2

comparações

A > B
A >= B

A =< B

A =:= B  igualdade aritimetica 
A =\= B

Listas

Heterogeneas, entre [ ]

[1, 2, [5,6], abobora, [] ]

Pattern matching:

[Cabeca|Resto] 
[]

[X|R] nao casa com a lista vazia

[1,2,3] = [X|R]
X = 1, R = [2,3]

Exemplo

tam([],0).
tam([_|R],N) :- tam(R,NN), N is NN+1.
tam(L,N) = tamx(L,N,0).
tamx([],N,Acc) :- Acc=N.
tamx([X|R],N,Acc) :- AA is Acc+1, tamx(R,N,AA).

nesta ultima regra o prolog indica singleton variable X . Isso é um warning que a variavel X aparece só uma vez, e isso pode ser um erro com consequencias graves na hora de rocar ou nao ser nada serio como no caso acima.

Modo

quando vc programa tam vc assume que vc recebe a lista (+) e vai devolver o tamanho dela (-)

tam modo (+-)

Erros

Nao da para somar 1 numa variavels (N)

tam([],0).
tam([_|R],N) :- tam(R,N), N is N+1.  <- erro

tam([_|R],N) :- tam(R,NN), N = NN+1.  <- correto

N is N+1 nunca da certo! Ou N nao tem valor, e a expressão da um erro, ou N tem valor e o lado esquerdo não unifica com o lado esquerdo

Não da para passar expressões como parametros do predicado.

tamx([X|R],N,Acc) :- tamx(R,N,Acc+1).   <- erro

tamx([X|R],N,Acc) :-  AA is Acc+1, tamx(R,N,AA).  <- correto

Lembre-se expressões matematicas NAO sao avaliadas em passagem de parametros.

Exemplo2

Soma dos elementos de uma lista soma(+LISTA,-SOMA)

soma([],S) :- S=0.
soma(X|R],S) :- soma(R,SS), S is SS+X.

ou

soma([], 0). 
soma(X|R],S) :- soma(R,SS), S is SS+X.

exemplo3

soma dos números pares de uma lista somapares(+LISTA,-SOMA)

somapares([], 0).
somapares([X|R], SP) :- X mod 2 =:= 0, somapares(R,SS),
                        SP is SS+X.
somapares([X|R], SP) :- somapares(R,SS), SP=SS.

se X é par , ele executa a 2a regra. Se X é impar, o primeiro predicado da 2a regra falha, e o prolog executa a 3a regra.

Nao precisamos de IF/ELSE. A 2a regra testa para a condição X mod 2 =:= 0 e contém o THEN. A 3a regra contem o ELSE.

Outra versão

somapares([],0).
somapares([X|R], SP) :- X mod 2 =:= 0, somapares(R,SS),
                        SP is SS+X.
somapares([_|R], SP) :- somapares(R,SP).

Outra versão

somapares([], 0).
somapares([X|R], SP) :- somapares(R,SS),
            (X mod 2 =:= 0 , SP is SS+X 
         ;   SP=SS).

Predicados das aulas passadas

irmao(X,Y)

voce programou isso com o modo ++. Voce assumiu que voce tinha X e Y e escreveu a relação entre elas. Voce nao assumiu que eu dei o X e voce precisava descobrir o Y, ou ao contrário.

Mas voce escreveu o predicado no modo ++ mas aqueles predicados funcionam em outros modos!.

Exercícios

Da aula 1 e 2 e haskell - use acumuladores quando necessario.

o append(+,+, -)

append([],A,A).
append([X|R],A,AA) :- append(R,A,RR), AA = [X|RR].

ou 

append([],A,A).
append([X|R], A, [X|RR]) :- append(R,A,RR).
intercala1([1,2,3], [4,5,6,7,8], X).
 X =  [1,4,2,5,3,6]
intercala2([1,2,3], [4,5,6,7,8], Y),
 Y =   [1,4,2,5,3,6,7,8]
shiftr([1,2,3,4],X)
 X = [4,1,2,3]