Procedimentos Pré-definidos em prolog comunicação Vários tipos de comunicação utilizador/programa: Comunicação básica (questão, em seguida, resposta em termos instanciações de variáveis). Comunicação (input) de dados sobre outras formas (quais?). Comunicação (output) de dados em qualquer formato. Comunicação (input e output) para ficheiro ou outro dispositivo que não seja o terminal. As implementações do PROLOG disponibilizam alguns procedimentos pré-definidos para tratar os diversos tipos comunicação. Programação Declarativa 1 Comunicação terminal user_in input streams user_out file_in 1 file_out 1 P file_in 2 file_out 2 output streams O programa pode utilizar vários ficheiros simultaneamente para leitura, designados por input streams ou para escrita, designados por output streams. Durante a execução de um programa em PROLOG são abertos, inicialmente, um ficheiro de leitura, designado por current input stream e um ficheiro de escrita, designado por current output stream. Programação Declarativa 2 Processamento de ficheiros de termos PROCEDIMENTO read O procedimento (de input) read faz a leitura de termos a partir do current input stream. O objectivo read(X). faz a leitura de um termo T (a introduzir após validar o objectivo) e, seguidamente, X é substituído por T, se X é uma variável; senão read(X) falha sem retrocesso. Exemplo ? read(X). ? read(atomo). ? read(X). |: termo. |: atomoX. |: Y. X = termo; no X = _G111 no yes Observação A introdução de um termo termina com um ponto. Programação Declarativa 3 Procedimentos Pré-Definidos em PROLOG PROCEDIMENTO write O procedimento (de output) write faz a escrita de termos no current output stream. O objectivo write(T). escreve o termo T na forma sintática utilizada para as instâncias das variáveis. Exemplo ? write(termo). ? write(X). ? write([a,b,c]). termo. _G117 [a,b,c] yes X = _G117; yes no Observação O procedimento write escreve um termo, no current output stream, independentemente da sua complexidade sintáctica. Programação Declarativa 4 PROCEDIMENTO tab O procedimento (de output) tab faz a inserção de espaços em branco no current output stream. O objectivo tab(N) introduz N espaços em branco no current output stream. Exemplos ? read(X),tab(10),write(X). |: [a,b,c]. [a,b,c] X = [a,b,c]; no ?- write(ola), tab(5), write(amigos). ola amigos Yes Programação Declarativa 5 PROCEDIMENTO nl O procedimento nl faz deslocar a escrita de termos, no current output stream, para o início da próxima linha. Exemplo ?write(ola),nl,write([a,b,c]). ola [a,b,c] yes Programação Declarativa 6 Exemplo cube :write('proximo numero: '), read(X), process(X). process(stop) :- !. process(N) :C is N * N * N, write('o cubo de '),write(N),write(' e '), write(C),nl,cube. Programação Declarativa ? cube. proximo numero: 5. o cubo de 5 e 125 proximo numero: 4. o cubo de 4 e 64 proximo numero: stop. yes 7 Manipulação de caracteres PROCEDIMENTO put O procedimento (de output) put escreve, no current output stream, um carácter codificado em ASCII. O objectivo put(C) escreve o carácter que corresponde ao código ASCII C. PROCEDIMENTO get O procedimento get0 faz a leitura, a partir do current input stream, de um carácter codificado em ASCII. No objectivo get0(C) C é instanciado com o código ASCII do carácter a ler. O procedimento get(C) não faz a leitura dos espaços em branco. Programação Declarativa 8 (De)Composição de átomos name(A,L) é verdadeiro se L é a sequência (representada por uma lista) dos códigos ASCII que correspondem aos caracteres que formam o átomo A. Exemplo getsentence(Wordlist) :- get0(Char), getrest(Char,Wordlist). getrest(46,[]) :- !. getrest(32,Wordlist) :- !, getsentence(Wordlist). getrest(Letter,[Word|Wordlist]) :- getletters(Letter,Letters,Nextchar), name(Word,Letters),getrest(Nextchar,Wordlist). getletters(46,[],46) :- !. getletters(32,[],32) :- !. getletters(Let,[Let|Letters],Nextchar) :get0(Char),getletters(Char,Letters,Nextchar). ? getsentence(W). |: Mary was pleased to see the robot fail. ['Mary','was','pleased','to','see','the','robot','fail'] yes Programação Declarativa 9 Leitura de programas Podemos comunicar os nossos programas ao PROLOG através dos predicados pré-definidos: consult e reconsult. PROCEDIMENTO consult O efeito da execução do objectivo ? consult(F) é disponibilizar todas as cláusulas no ficheiro F, na sessão actual do PROLOG, para serem utilizadas, posteriormente, na execução de objectivos introduzidos pelo utilizador. Se, na mesma sessão do PROLOG, outro ficheiro (e.g. G) é lido através da execução do objectivo ? consult(G), então é adicionado, ao fim do ficheiro actual, as cláusulas do (novo) ficheiro G. PROCEDIMENTO reconsult O efeito da execução do objectivo ? reconsult(F) é análogo à execução do objectivo ? consult(F), excepto que, todas as cláusulas do ficheiro F, que foram previamente definidas, são redefinidas pelas cláusulas na nova versão de F. Programação Declarativa 10 Verificar o tipo dos termos integer(X) é verdadeiro se X é um inteiro. var(X) é verdadeiro se X é uma variável não instanciada. nonvar(X) é verdadeiro se X é um termo, que não seja uma variável, ou X é uma variável instanciada. atom(X) é verdadeiro se X é um átomo. real(X) é verdadeiro se X é um real. atomic(X) é verdadeiro se X é um inteiro ou um átomo. Exemplo % count(A,L,N) onde N é o número de ocorrências do átomo A na lista L. count(_,[],0). count(A,[B|L],N) :- atom(B),A = B,!, count(A,L,N1), N is N1 + 1 ; count(A,L,N). Programação Declarativa 11 PROCEDIMENTO =.. T =.. L é verdadeiro se L é uma lista que contém o functor principal do termo T seguido dos seus argumentos. Exemplo enlarge(Fig,F,Fig1) :Fig =.. [Type|Parameters], multiplylist(Parameters,F,Parameters1), Fig1 =.. [Type|Parameters1]. multiplylist([],_,[]). multiplylist([X|L],F,[X1|L1]) :X1 is F * X,multiplylist(L,F,L1). ?- multiplylist([1,2,3],3,L). L = [3, 6, 9] Yes Programação Declarativa 12 PROCEDIMENTO functor functor(Term,F,N) é verdadeiro se F é o functor principal de Term e N a aridade de F. PROCEDIMENTO arg arg(N,Term,A) é verdadeiro se A é o N-ésimo argumento do termo Term (assumindo que os argumentos são numerados da esquerda para a direita). Programação Declarativa 13 Controlo de execução - o Corte ! O corte, denotado por !, elimina o retrocesso. fail é um objectivo que falha sempre. true é um objectivo que é sempre bem sucedido not(P) é tipo de negação que se comporta exactamente como se tivesse definido da seguinte forma: not(P) :- P,!,fail;true. call(P) invoca P. call(P) é bem sucedido se P é bem sucedido. repeat é um objectivo (não determinista) que é sempre bem sucedido. Exemplo dosquares :- repeat, read(X), (X = stop,! ; Y is X*X,write(Y),fail). Programação Declarativa 14 Controlo de execução - o Corte ! Adição de elementos sem duplicação adic(X,L,L1). Se x é membro de L então L=L1 senão L1 é L com a inserção de X na cabeça. adic(X,L,L):- membro(X,L),!,Adic(X,L,L1). Exemplos ?- adic(a,[b,c],L). Programação Declarativa 15 Controlo de execução - If-then-else ifThenElse(X,Y,Z). Pode ser simulado em Prolog por ifThenElse(X,Y,Z):- X,!,Y. ifThenElse(X,Y,Z)_- Z. Exemplo ?- ifThenElse(X,Y is Z+1,Y is 0). Programação Declarativa 16