440 likes | 544 Views
Tipo dos termos. Predicados de sistema para tipos integer( X ) ¬ X é um inteiro atom( X ) ¬ X é um átomo atomic( X ) ¬ X é um inteiro ou um átomo. % aplana( Xs, Ys ) ¬ Ys é uma lista com os elementos de Xs (fechada) aplana( Xs, Ys ) ¬ aplana( Xs, [], Ys ).
E N D
Tipo dos termos • Predicados de sistema para tipos • integer( X ) ¬ X é um inteiro • atom( X ) ¬ X é um átomo • atomic( X ) ¬ X é um inteiro ou um átomo % aplana( Xs, Ys ) ¬ Ys é uma lista com os elementos de Xs (fechada) aplana( Xs, Ys ) ¬ aplana( Xs, [], Ys ). aplana( [X|Xs], S, Ys ) ¬ lista( X ), aplana( X, [Xs| S], Ys ). aplana( [X|Xs], S, [X|Ys] ) ¬ atomic( X ), X \=[], aplana( Xs, S, Ys ). aplana( [], [X|S], Ys ) ¬ aplana( X, S, Ys ). aplana( [], [], [] ). lista( [X|Xs] ). • este programa aplana uma lista usando uma stack implementada como uma lista manipulada por unificação — a estrutura é construída top-down
Estrutura dos termos Predicados de manipulação da estrutura • functor( Termo, Functor, Aridade )¬ o functor principal de Termo é Functor com aridade Aridade • arg( N, Termo, Arg )¬ Arg é o Nésimo argumento de Termo • Termo =.. Lista¬ se a cabeça da lista contém o functor do termo e o resto da lista os seus argumentos • Nota: estes predicados são bidireccionais; functor e univ (=..) também constroem
Análise de subtermos % subtermo( Sub, Termo ) ¬ Sub é um subtermo do termo fechado Termo subtermo( Termo, Termo ). subtermo( Sub, Termo ) ¬ functor( Term, F, N ), N>0, subtermo( N, Sub, Termo ). subtermo( N, Sub, Termo ) ¬ N>1, N1 is N-1, subtermo( N1, Sub, Termo ). subtermo( N, Sub, Termo ) ¬ arg( N, Termo, Arg ), subtermo( Sub, Arg ). % subtermo( Sub, Termo ) ¬ Sub é um subtermo do termo fechado Termo subtermo( Termo, Termo ). subtermo( Sub, Termo ) ¬ Termo =.. [F|Args], subtermo_lista( Sub, Args ). subtermo_lista( Sub, [Arg|Args] ) ¬ subtermo( Sub, Arg ). subtermo_lista( Sub, [Arg|Args] ) ¬ subtermo_lista( Sub, Args ).
Predicados meta-lógicos • Predicados de tipo meta-lógicos • var( X ) ¬ X é uma variável • nonvar( X ) ¬ X não é uma variável • X == Y ¬ X e Y são o mesmo termo (a mesma variável, etc...) • X \== Y ¬ X e Y não são o mesmo termo soma( X, Y, Z ) ¬ nonvar( X ), nonvar( Y ), Z is X+Y. soma( X, Y, Z ) ¬ nonvar( X ), nonvar( Z ), Y is Z-X. soma( X, Y, Z ) ¬ nonvar( Y ), nonvar( Z ), X is Z-Y.
Predicados meta-lógicos • estes predicados são meta-lógicos porque referir-se ao nome de uma variável está fora da lógica de primeira ordem • não se pode representar este predicado com uma tabela de todos os seus factos (são em número infinito) • interesse: • permitir implementar predicados bidireccionais à custa de predicados de sistema (unidireccionais) • escolher a melhor ordem para os golos, conforme a instanciação dos argumentos (em especial para garantir o correcto funcionamento da negação e dos predicados de sistema) • para evitar instanciações indesejadas nos predicados de análise de termos
Termos fechados % fechado( Termo ) ¬ Termo está completamente instanciado fechado( Termo ) ¬ nonvar( Termo ), atomic( Termo ). fechado( Termo ) ¬ nonvar( Termo ), functor( Termo, F, N ), N>0, fechado( N, Termo ). fechado( N, Termo ) ¬ N>0, arg( N, Termo, Arg ), fechado( Arg ), N1 is N-1, fechado( N1, Termo ). fechado( 0, Termo )
Entrada/saída • predicados extra-lógicos — produzem efeitos laterais, para além de sucederem, normalmente só uma vez, i.e. em retrocesso falham • nível do termo • read( X ) — lê um termo do canal de entrada (até um ponto final) e unifica-o com X, sucedendo ou falhando em conformidade • write( X ) — escreve o termo X no canal de saída • 'Isto é um átomo que inclui espaços' • "Isto " é uma notação ao jeito das strings, equivalente à lista de inteiros [73, 115, 116, 111, 32] que contém os códigos ASCII dos caracteres na string • name( X, Y ) — converte o nome de constante X para a cadeia de caracteres Y correspondente e vice-versa • display( X ) — escreve o termo X em notação prefixa
Entrada/saída • nível do carácter • put( N ) — coloca o carácter de código ASCII N no canal de saída • get0( N ) — N é o código ASCII do carácter seguinte no canal de entrada • get( N ) — N é o código ASCII do carácter não branco seguinte no canal de entrada caracter( C ) ¬ 97 =< C, C=< 122. % minúsculas caracter( C ) ¬ 65 =< C, C=< 90. % maiúsculas caracter( 95 ). % underscore separador( 32 ). % espaço terminador( 46 ). % ponto
Lista de palavras le_lista_palavras( Ws ) ¬ get( C ), le_lista_palavras( C, Ws ). le_lista_palavras( C, [W | Ws] ) ¬ caracter( C ), le_palavra( C, W, C1 ), le_lista_palavras( C1, Ws ). le_lista_palavras( C, Ws ) ¬ separador( C ), get( C1 ), le_lista_palavras( C1, Ws ). le_lista_palavras( C, [] ) ¬ terminador( C ). le_palavra( C, W, C1 ) ¬ caracteres( C, Cs, C1 ), name( W, Cs ). caracteres( C, [C|Cs], C0 ) ¬ caracter( C ), !, get0( C1 ), caracteres( C1, Cs, C0 ). caracteres( C, [], C ) ¬ not caracter( C ).
Ficheiros • inicialmente, há um canal aberto para entrada e para saída chamado user e que está ligado ao terminal • entrada • see( F ) — abre um canal de leitura para o ficheiro F e torna-o corrente • se já estiver aberto, limita-se a pôr o canal como corrente • todas as leituras são do canal corrente • seeing( F ) — F é unificado com o nome do ficheiro no canal de entrada corrente • seen — fecha o canal de entrada corrente
Ficheiros • saída • tell( F ) — semelhante a see( F ), mas para escrita • a linha de texto só é enviada para o canal quando ocorrer um fim de linha (nl) • telling( F ) — como seeing( F ) • told — fecha o canal de saída corrente
Acesso ao programa • listing, listing( Pred ) — escreve no écran as cláusulas do programa, ou só do predicado • clause( Head, Body ) — percorre, em retrocesso, as cláusulas do programa que unificam com Head, o qual tem que estar instanciado • assert( Clausula ) —adiciona a cláusula no fim da definição do respectivo predicado • definição do predicado member/2 • assert( member( X, [X|Xs] ) ). • assert( (member( X, [Y|Xs] ) ¬ member( X, Xs )) ). • asserta( Clausula ) — adiciona no princípio
Acesso ao programa • retract( Clausula ) — elimina a primeira cláusula que unifica com Clausula • forma de copiar termos, criando variáveis novas • copy( X, Y ) ¬ assert( $tmp( X ) ), retract( $tmp( Y ) ). • consult( F ) — lê o programa no ficheiro F, fazendo o assert das cláusulas e executando as directivas que encontrar (¬ G ) • reconsult( F ) — semelhante a consult mas faz primeiro retract a todos os predicados para os quais vai fazer assert (substitui, em vez de adicionar)
Funções de memorização • pode-se usar a capacidade de manipular o programa para gravar resultados de computações parciais, para reutilização em fases subsequentes • ideia geral: uma pilha de altura N passa-se para B passando a pilha de altura N-1 para o poste auxiliar C, o disco N para B e a pilha de C para B; esta segunda passagem é igual à primeira, a menos de instanciações, e pode ser resolvida pelo lema entretanto memorizado [efeito lateral para além da Programação em Lógica] — bottom-up • testa_hanoi só instancia os Postes no fim para gravar soluções gerais nos lemas
Torres de Hanoi % hanoi( N, A, B, C, Moves ) ¬ Moves é a sequência de passos para transferir N discos do poste A para o B usando C, segundo as regras do puzzle Torre de Hanoi hanoi( 1, A, B, C, [A to B] ). hanoi( N, A, B, C, Moves ) ¬ N>1, N1 is N-1, lema( hanoi(N1,A,C,B,Ms1) ), hanoi( N1,C,B,A,Ms2 ), append( Ms1, [A to B|Ms2], Moves ), lema( P ) ¬ P, asserta((P¬!)). testa_hanoi( N, Postes, Passos ) ¬ hanoi( N, A, B, C, Passos ), Postes=[A, B, C].
Operadores • forma standard de ler e escrever os termos é com o functor seguido dos respectivos argumentos entre parênteses • certas expressões ficam mais legíveis usando operadores: 5 + 3 versus '+'( 5, 3 ) • comando: op( Precedencia, Tipo, Op ) • Precedência de 1 a 1200 • ',' tem precedência 1000; logo, operadores que possam aparecer como argumentos devem ter precedência inferior a 1000 ou ficar entre parênteses, que corresponde a precedência 0: assert( (a ¬ b) ) • Tipo pretende desambiguar expressões definindo o tipo de associatividade e a posição (infixo: xfx, xfy, yfx; prefixo: fx, fy; posfixo: xf, yf)
Operadores X + Y + Z (X + Y) + Z yfx X +( Y + Z) xfy • f - operador • argumentos x: têm que ter precedência inferior a f • argumentos y: têm que ter precedência superior a f • legal? • op(1000, xfy, ',') a, b, c • op(500, yfx, [(+),(-)]) • op(500, fx, [(+),(-)]) - 5 + 3
Ciclos interactivos • os programas interactivos baseiam-se no processamento de efeitos laterais (leituras ou escritas, asserts, etc.) eco ¬ read( X ), eco( X ). eco( X ) ¬ eof( X ), !. eco( X ) ¬ write( X ), nl, read( Y ), !, eco( Y ). eof( end_of_file ). • se estiver a ler do teclado, basta escrever end_of_file; se o canal de entrada for um ficheiro, é esse o termo que aparece ao chegar ao fim (não esquecer que os termos terminam com um '.')
Interpertador de comandos • exemplo de uma shell para executar comandos (termina com o comando fim): shell ¬ shell_prompt, read( Golo ), shell( Golo ). shell( fim ) ¬ !. shell( Golo ) ¬ ground( Golo ), !, resolve_instanciado( Golo ), shell. shell( Golo ) ¬ resolve( Golo ), shell. resolve( Golo ) ¬ Golo, write( Golo ), nl, fail. resolve( Golo ) ¬ write( 'Nao ha mais.' ), nl. resolve_instanciado( Golo ) ¬ Golo, write( 'Sim.' ), nl. resolve_instanciado( Golo ) ¬ write( 'Nao.' ), nl. shell_prompt ¬ write( 'Comando> ' ).
Ciclos baseados em falha • os ciclos anteriores são baseados em recursão na cauda (enrolam sempre) • sucedem e portanto instanciam variáveis • se não forem bem optimizados ocupam muito a stack em computações longas • se só interessam os efeitos laterais e há problemas de espaço, usar um ciclo repeat-fail (a computação oscila entre o repeat e o fail) eco ¬ repeat, read( X ), eco( X ), !. eco( X ) ¬ eof( X ), !. eco( X ) ¬ write( X ), nl, fail. eof( end_of_file ).
Consultar • Comentários • repeat sucede sempre; implementável como • repeat. • repeat ¬ repeat. • predicado interior ao ciclo (eco/1, ciclo/0) falha sempre, excepto na cláusula de saída • cut na cláusula com repeat para evitar ciclo infinito em retrocesso de fora do ciclo • como consultar um ficheiro consult( Ficheiro ) ¬ see( Ficheiro ), ciclo, seen. ciclo ¬ repeat, read( Clausula ), processa( Clausula ), !. processa( end_of_file ) ¬ !. processa( Clausula ) ¬ assert( Clausula ), fail.
Não determinismo • geração e teste é um método geral que aproveita muitas vezes o funcionamento bidireccional dos predicados • intersecta( Xs, Ys ) ¬ member( X, Xs ), member( X, Ys ). • implementações tendem a ser ineficientes se a geração não for dirigida; para obviar a isso imbrica-se o teste na geração solucao( X ) ¬ gera( X ), testa( X ).
Problema das raínhas % rainhas( N, Rainhas ) ¬ Rainhas é uma lista com a posição em cada coluna que resolve o problema rainhas( N, Rs ) ¬ gama( 1, N, Ns ), rainhas( Ns, [], Qs ). rainhas( NaoRs, JaRs, Rs ) ¬ selecciona( R, NaoRs, NaoRs1 ), not ataca(R, JaRs ), rainhas( NaoRs1, [R, JaRs, Rs] ). rainhas( [], Rs, Rs ). gama( M, N, [M|Ns] ) ¬ M<N, M1 is M+1, gama( M1, N, Ns ). gama( N, N, [N] ). select( X, [X|Xs], Xs ). select( X, [Y|Ys], [Y|Zs] ) ¬ select( X, Ys, Zs ). ataca( X, Xs ) ¬ ataca( X, 1, Xs ). ataca( X, N, [Y|Ys] ¬ X is Y+N; X is Y-N. ataca( X, N, [Y|Ys] ) ¬ N1 is N+1, ataca( X, N1, Ys ).
Conjuntos de soluções • obter todos os filhos de um dado pai • solução com acumulador filhos( X, Fs ) ¬ filhos( X, [], Fs ). filhos( X, A, Fs ) ¬ pai( X, F ), not member( F, A ), !, filhos( X, [F|A], Fs ). filhos( X, Fs, Fs ). • defeitos • ineficiência — cada solução recomeça no início da árvore de pesquisa • falta de generalidade — instanciação progressiva reduz número de soluções • implementação com conjuntos — ideia semelhante à das funções de memorização • só percorre a árvore de pesquisa uma vez e não instancia as variáveis porque tem um ciclo com falha logo após o assert • criar cláusulas (e depois destruí-las) é inerentemente pesado
Predicados de conjuntos bagof( Termo, Golo, Intancias )¬ Instancias é o multiconjunto de todas as instâncias de Termo para as quais o Golo é satisfeito (inclui repetidos) setof( Termo, Golo, Intancias )¬ semelhante, mas sem valores repetidos e ordenado filhos( X, Filhos ) ¬ setof( Y, pai(X,Y), Filhos ) • chamada: filhos( terach, Fs ) • resposta: Fs= [haran, nachor, abraao] • chamada: filhos( X, Fs ) • respostas: • X= terach Fs= [haran, nachor, abraao] ; • X= haran Fs= [lot, milcah, yiscah]; • X= abraao Fs= [isaac]; • X= isaac Fs= [jacob]
Quantificação existencial • se se pretender todos os filhos independentemente dos pais, é necessário quantificar existencialmente o pai para este não aparecer na solução (evitando a partição) • setof( Y, X^pai(X,Y), Filhos ) • resp.: [haran, nachor, abraao, lot, milcah, yiscah, isaac, jacob] • o que dá? setof( Pai-Filhos, setof( X, pai(Pai,X), Filhos ), Ys ) • resp.: [terach-[haran, nachor, abraao], haran-[lot, milcah, yiscah], abraao-[isaac], isaac-[jacob]]
Outras técnicas • número de soluções de G: setof( X, G, Ys ), length( Ys, NSol) • pesquisa em profundidade: regra de computação normal do Prolog • pesquisa em largura: para cada nó, obter o conjunto dos que lhe estão directamente ligados e processá-los antes de descer para o nível inferior
Predicados de segunda ordem • mapa( Xs, P, Ys ) ¬ Ys é a lista dos resultados da aplicação de P a cada X • definição de segunda ordem • mapa( [X|Xs], P, [Y|Ys] ) ¬ • P( X, Y ), mapa( Xs, P, Ys ). • mapa( [], P, [] ). • implementação em Prolog • mapa( [X|Xs], P, [Y|Ys] ) ¬ • aplica( P, X, Y ), mapa( Xs, P, Ys ). • mapa( [], P, [] ). • aplica( P, X, Y ) ¬ G =.. [P,X,Y], G.
Listas de diferença • ideia: representar sequências de elementos como diferenças entre pares de listas • 1,2,3 pode ser a diferença entre • [1,2,3,4,5] e [4,5] ou • [1,2,3,8] e [8] ou • [1,2,3] e [] ou • [1,2,3|Xs] e Xs • para realçar o facto de se tratar de uma mesma estrutura, pode-se usar um operador para representar as listas de diferença Xhead/Xtail ou dois argumentos separados • vantagem: eficiência, faz a concatenação em tempo constante e não linear no 1º arg
Exemplo de listas de diferença • • • • • • • • • • • • • • • • • • • Xs Xs/Ys • • • • • • • • • • • • • • Ys Ys/Zs • • • • • • • Zs Xs/Zs • % append_ld( As, Bs, Cs ) ¬ a lista de diferença Cs é o resultado de concatenar as listas de diferença compatíveis As e Bs • append_ld( Xs/Ys, Ys/Zs, Xs/Zs). • chamada: append_ld( [a,b,c|Ls]/Ls, [1,2]/[], Ks ) • resultado: Ls=[1,2] Ks= [a,b,c,1,2]/[] • generalização do conceito de acumulador • aplana( xs, Ys ) ¬ aplana_ld( Xs, Ys/[] ). • aplana_ld( [X|Xs], Ys/Zs ) ¬ aplana_ld( X, Ys/Ys1 ), aplana_ld( Xs, Ys1/Zs). • aplana_ld( X, [X|Xs]/Xs ) ¬ atomic( X ), X \= []. • aplana_ld( [], Xs/Xs ).
Estruturas incompletas % ve( Chave, Dicionario, Valor ) ¬ Dicionario contém Valor indexado por Chave ( Dicionário é constituído por pares (Chave, Valor) ) ve( Chave, [(Chave,Valor)|Dic], Valor ). ve( Chave, [(Chave1,Valor1) | Dic ], Valor ) ¬ Chave \= Chave1, ve( Chave, Dic, Valor ). • uso do dicionário ( implementado com lista, mas podia ser árvore binária, ...) • ve( fatima, [(ana,1611),(joao,4245)|Dic],1812) sucede e instancia o dicionário mais um pouco • ve( joao, [(ana,1611),(joao,4245), (fatima,1812)|Dic], X ) sucede com X=4245
Meta-interpretadores % resolve( Golo ) ¬ Golo é verdade relativamente ao programa em causa • interpretador trivial (e pouco útil... embora usado no exemplo da shell) resolve( G ) ¬ G. • interpretador de três linhas resolve( true ). % true resolve( (A,B) ) ¬ resolve( A ), resolve( B ). % conjunção resolve( A ) ¬ clause( A, B ), resolve( B ). % redução Meta-interpretador — interpretador de uma linguagem escrito na própria linguagem.
Meta-interpretadores especiais • granularidade do metainterpretador de 3 linhas é suficiente para resolver problemas interessantes, sem tornar o sistema demasiado lento; permite controlar a ordem de execução dos golos ou registar um traço da execução % resolve( G, Arvore ) ¬ Arvore contem uma árvore de prova de G resolve( true, true ). resolve( (A,B), (ProvaA, ProvaB ) ¬ resolve( A, ProvaA ), resolve( B, ProvaB ). resolve( A, true ) ¬ sistema( A ), A. % tabela para sistema/1 resolve( A, (A Prova) ) ¬ clause( A, B ), resolve( B, Prova ).
Janelas de texto • wcreate(janTexto,text,`Janelinha`,200,125,400,225,0). • cria uma janela de topo • wedtsel((janTexto,1), 0, 30000 ). • selecciona texto no controlo 1 da janTexto • wedtsel((janTexto,1), Ini, Fim ). • Interroga sobre quais os limite de uma seleccao • wedttxt((janTexto,1), Dados ). • le o texto seleccionado • wedttxt((janTexto,1), `Olare meu` ). • escreve no texto seleccionado • wclose( janTexto ). • fecha a janela • wedtlin( (janTexto,1), 100, IniLinha, FimLinha ). • indica os offsets de inicio e fim de linha para um offset dado; so wedtsel altera a seleccao
Mais interface Windows • wcount( (janTexto,1), Caract, Palavras, Linhas ). • conta • wedtfnd( (janTexto,1), 0, 30000, `Goal`, Ini, Fim ). • offsets da palavra em pesquisa • wdict( D ). • devolve uma lista com os nomes das janelas de topo • msgbox( 'Prologochi', 'Tenho fome.', 48, Codigo ). • dialogo com um estilo indicando numero de botoes, cada qual correspondendo a um codigo de retorno • dirbox( 'Ficheiros', 'Escolha um:', '*.doc', Fich ). • ficheiro • chdir( Corrente ). • muda de directorio corrente • exec('notepad.exe',' ',_). • executa um programa externo
Construção de janelas • wcreate( janGeral, dialog, `Dialogo`, 200, 125, 400, 225, 16'90c80000 ). • cria um janela de dialogo de topo • wcreate( (janGeral,1), button, `Pois`, 10, 150, 80, 32, 16'50010000 ). • cria um botao na janela • wcreate( janGeral, dialog, `Dialogo`, 200, 125, 400, 225, 16'80c80000 ). • cria um janela invisivel de dialogo de topo • wshow( janGeral, 1 ), wfocus((janGeral,1)). • mostra (1), esconde (0), iconifica (2), maximiza (3) e foca • wcreate(janBotoes,user,`Botoes`, 200,125,400,225,0 ). • cria um janela user - faz parte do MDI (Multiple Document Interface), janela do LPA-Prolog; um diálogo é autónomo • wcreate( (janBotoes,1), button, `Pois`, 10, 150, 80, 32, 16'50010000 ). • cria um botao na janela
Botões • wcreate( (janBotoes,2), button, `Nao da`, 100, 150, 80, 32, 16'50010003 ). • checkBox • wcreate( (janBotoes,3), button, `Esta`, 190, 150, 80, 32, 16'50010009 ). • radioButton • wcreate( (janBotoes,4), button, `Aquela`, 280, 150, 80, 32, 16'50010009 ). • cria um botao na janela • wenable( (janBotoes,2), 1 ). • activa/desactiva controlo • wbtnsel( (janBotoes,3), Est ). • interroga/poe o estado de botoes • wcreate( (janBotoes,5), edit, `Notas`, 10, 200, 80, 64, 16'50810005 ). • cria uma caixa de texto na janela
Caixas de texto e listas • wedtsel( (janBotoes,5), 30, 40 ), wedttxt( (janBotoes,5), `Novo texto aqui! ` ). • selecciona e altera texto • wtext( (janBotoes,5), T ). • le (ou escreve, se T instanciado) o conteudo da janela • wcreate( (janBotoes,6), listbox, ` `, 10,125,80,64, 16'50a10002 ). • cria uma lista • wlbxadd( (janBotoes,6), -1, `Amarelo` ). • adiciona elementos a lista na posicao default • wlbxadd( (janBotoes,6), -1, `Vermelho` ). • wlbxadd( (janBotoes,6), -1, `Verde` ). • wlbxsel( (janBotoes,6), 2, 1 ). • selecciona o elemento 3 como activo • wlbxget( (janBotoes,6), 1, T ). • consulta o 2 elemento da lista
Menús • wmcreate( menu1 ). • cria um menu. • wmnuadd( menu1, -1, `&Sopas`, 1000). • acrescenta uma linha Sopas no fim com codigo 1000 • wmnuadd( menu1, -1, `&Pratos`, 1001). • wmnuadd( menu1, -1, `&Sobre`, 1002). • wmnuadd( 0, 3, `Menu`, menu1). • adiciona menu ao menu geral da aplicacao • wmnusel(menu1,0,1). • poe marca na primeira opcao do menu • wmdict( D ). • devolve a lista de menus activos • wmnudel(0,3). • retira a entrada do menu1 na barra do WIN-Prolog (menu 0) • wmclose( menu1 ). • elimina menu, depois de ter sido retirado de onde quer que seja usado
Mensagens • Arquitectura geral • interacção com Windows baseada em eventos que interrompem o Prolog, são processados e retomam o golo interrompido • só alguns eventos do Windows chegam ao Prolog (menus, diálogos, …) • processamento • recepção da mensagem pelo LPA-Prolog • anzol: ‘?MESSAGE?’(Window, Message, Data, Goal), apanha todas as mensagens em bruto, excepto as usadas internamente nos menus Edit e Windows • separação em classes e processamento de parâmetros • interrupção do programa, desactivação das interrupções, chamada de um processador da mensagem (handler) • anzol: ‘?FIND?’/4, ‘?TIMER?’/3 • reactivação das interrupções, retoma do golo interrompido
Processadores de mensagens • Esquema dos anzóis '?CLASS?'(Window, Message, Data, Goal):- !, ..., wflag(1), Goal. '?CLASS?'(Window, Message, Data, Goal):- class_hook(Window, Message, Data, Goal). • CLASS é uma das classes existentes • se existir o anzol, é chamado, senão chama-se directamente class_hook/3 • Window é o controlo antes do que chamou o anzol • o anzol pode processar alguns casos e deixar os outros para a rotina geral • não esquecer de reactivar as interrupções (wflag(1)) e de chamar o golo interrompido
Mensagens predefinidas '?FIND?'(Window, msg_fbfndnxt, Goal):- !, fndbox(``, 1), wflag(1), Goal. '?FIND?'(Window, Message, Goal):- find_hook(Window, Message, Goal). • Ignora as mensagens Find Next '?CHANGE?'(Window, msg_cbclose, Goal):- !, msgbox('Mensagem','A janela vai fechar!',0,_), chgbox(``,``, -1), wflag(1), Goal. '?CHANGE?'(Window, Message, Goal):- change_hook(Window, Message, Goal). • Processa as mensagens Close
Ciclo com Timer go( S ):- T is S*4660, abolish(intervalo/1), assert(intervalo(T)), timer( 1, T), repeat, write('Diga'), read(X), processa(X). processa( fim ):- !, timer( 1, 0). processa( X ):- write(X), nl, fail. '?TIMER?'(Timer, Inter, Goal):- msgbox('Aviso', 'Timer em accao', 0, _), wflag(1), intervalo(T), timer( Timer, T), Goal.
Gráficos • wcreate( (janBotoes,7), grafix, ` `, 100,125,80,64, 16'50800000 ). • cria um grafico • wgfx( (janBotoes, 7), [brsh(128,0,0,0), elip(10,10,70,54)]). • sequencia de operacoes