UNIVERSIDADE ESTADUAL DE MARINGÁ DEPARTAMENTO DE INFORMÁTICA MESTRADO EM CIÊNCIA DA COMPUTAÇÃO Programação Funcional e Programação Lógica Uma Implementação Prática Trabalho apresentado à disciplina de Linguagem de Programação do curso de Mestrado em Ciência da Computação, da Universidade Estadual de Maringá. Docente: Profº Drº Sérgio Roberto Pereira da Silva Dorival José Batista Késsia Rita da Costa Marchi Roberto Pereira MARINGÁ, Dezembro de 2006. 2 Sumário Índice de Figuras ......................................................................................................... 3 Introdução ................................................................................................................... 6 Organização do Trabalho ........................................................................................... 6 1 - Definição do Problema ........................................................................................... 7 2 - PROLOG................................................................................................................ 8 2.1 - Conexão com Banco de Dados MySql ................................................................ 8 2.2 - Implementação. ................................................................................................... 9 2.2.3 - Questões pré-determinadas para a resolução do problema. ......................... 12 3 - Scheme.................................................................................................................. 21 3.1 - Conexão com Banco de Dados .......................................................................... 21 3.3 - Implementação .................................................................................................. 23 3.3.1 - Questões pré-determinadas para a resolução do problema. ......................... 25 4 - Conclusão ............................................................................................................. 35 5 – Referencias Bibliográficas................................................................................... 37 3 Índice de Figuras Figura 1 – Diagrama Entidade Relacionamento ................................................................................. 07 Figura 2 – Gerenciador de Fontes de Dados ...................................................................................... 08 Figura 3 – Configuração da Fonte de Dados do Sistema .................................................................... 09 Figura 4 – Fonte de Dados para Access ............................................................................................. 22 Figura 5 – Seleção de Fonte de Dados ............................................................................................... 23 4 Índice de Tabelas Tabela 1 – Conexão do Prolog ao BD Mysql ....................................................................................... 09 Tabela 2 – Predicado Conectado ......................................................................................................... 09 Tabela 3 – Predicado Departamento .................................................................................................... 10 Tabela 4 – Predicado Curso ................................................................................................................ 10 Tabela 5 – Predicado Professor ........................................................................................................... 10 Tabela 6 – Predicado Disciplina .......................................................................................................... 10 Tabela 7 – Predicado Turno ................................................................................................................ 10 Tabela 8 – Predicado Dia .................................................................................................................... 10 Tabela 9 – Predicado Horário.............................................................................................................. 10 Tabela 10 – Predicado Grupo de Pesquisa ........................................................................................... 10 Tabela 11 – Predicado Linha de Pesquisa ............................................................................................ 10 Tabela 12 – Predicado Aluno .............................................................................................................. 10 Tabela 13 – Predicado Projeto............................................................................................................. 10 Tabela 14 – Predicado Artigo.............................................................................................................. 12 Tabela 15 – Predicado Professor x Disciplina ...................................................................................... 12 Tabela 16 – Resposta – Professor x Disciplina .................................................................................... 12 Tabela 17 – Predicado Hora x Professor .............................................................................................. 13 Tabela 18 – Resposta – Hora x Professor ............................................................................................ 13 Tabela 19 – Resposta – Hora x Disciplina ........................................................................................... 14 Tabela 20 – Predicado Professor Pesquisador ...................................................................................... 14 Tabela 21 – Resposta – Professor Pesquisador..................................................................................... 15 Tabela 22 – Predicado Professor x Artigo ........................................................................................... 15 Tabela 23 – Resposta – Professor x Artigo .......................................................................................... 15 Tabela 24 – Resposta – Professor X Artigo Autoria ............................................................................. 16 Tabela 25 – Predicado Artigo.............................................................................................................. 17 Tabela 26 – Resposta Artigo Professor ................................................................................................ 18 Tabela 27 – Resposta Artigo Professor Autoria ................................................................................... 19 Tabela 28 – Predicado Professor x Departamento ............................................................................... 19 Tabela 29 – Resposta – Professor x Departamento............................................................................... 19 Tabela 30 – Predicado Professor x Curso ............................................................................................ 20 Tabela 31 – Resposta Professor x Curso .............................................................................................. 21 Tabela 32 – Predicado Professor x Projeto .......................................................................................... 21 Tabela 33 – Resposta Professor x Projeto ............................................................................................ 21 Tabela 34 – Função de conexão .......................................................................................................... 22 Tabela 35 – Alocação de 'Environment Handle' e um 'Connection Handle' ........................................... 22 Tabela 36 – Chamada externa ao drive ODBC .................................................................................... 23 Tabela 37 – Função União .................................................................................................................. 23 Tabela 38 – Função Pertence? ............................................................................................................. 24 Tabela 39 – Chamada e Execução do Script SQL ................................................................................ 24 Tabela 40 – Função HSTMT............................................................................................................... 24 Tabela 41 – Chamada e Execução do Script SQL ................................................................................ 24 Tabela 42 – Chamada e Execução do Script SQL – 1ª questão ............................................................. 25 Tabela 43 – Buffers e Indicadores – 1ª questão. ................................................................................... 25 Tabela 44 – Chamada da função cônsul e o resultado – 1ª questão. ..................................................... 26 Tabela 45 – Buffer, indicadores e rotinas de execução – 2ª questão. .................................................... 26 Tabela 46 – Chamada da função cônsul e o resultado – 2ª questão. ..................................................... 27 Tabela 47 – Chamada e Execução do Script SQL – 3ª questão ............................................................. 27 Tabela 48 – Buffers e Indicadores – 3ª questão. ................................................................................... 28 Tabela 49 – Chamada da função cônsul e o resultado de professor – 3ª questão.................................... 28 Tabela 50– Buffer, indicadores e rotinas de execução – 4ª questão. ..................................................... 29 Tabela 51 – Chamada da função cônsul e o resultado – 4ª questão. ..................................................... 30 Tabela 52 – Buffer, indicadores e rotinas de execução – 5ª questão. .................................................... 30 Tabela 53– Chamada da função cônsul e o resultado – 5ª questão. ....................................................... 31 Tabela 54 – Buffer, indicadores e rotinas de execução – 6ª questão. .................................................... 31 Tabela 55– Chamada da função cônsul e o resultado – 6ª questão. ...................................................... 32 Tabela 56 – Buffer, indicadores e rotinas de execução – 7ª questão. .................................................... 32 Tabela 57– Chamada da função cônsul e o resultado – 7ª questão. ....................................................... 33 5 Tabela 58 – Buffer, indicadores e rotinas de execução – 8ª questão. ..................................................... 34 Tabela 59– Chamada da função cônsul e o resultado – 8ª questão. ....................................................... 34 6 Introdução Neste trabalho realizaremos uma abordagem sobre Programação Lógica e sobre Programação Funcional. A programação em lógica se desenvolveu no início dos anos 70, para atender alguns trabalhos sobre prova de teoremas. No decorrer de sua evolução, manteve-se seu formalismo simples e poderoso, sendo igualmente eficiente tanto para a representação do conhecimento, quanto como ferramenta para programação. No contexto da Programação Lógica, a primeira linguagem de programação que surgiu foi o PROLOG, uma linguagem orientada ao processamento simbólico que representa uma implementação da lógica como linguagem de programação. O PROLOG e o maior exemplo de linguagem de programação lógica, e será discutido neste trabalho. Já a Programação Funcional foi desenvolvida principalmente a partir do final dos anos 50. É um paradigma de programação que trata a computação como uma avaliação de funções matemáticas, que pode ou não, apresentar parâmetros bem como um simples valor de retorno, que são os valores de entrada e o resultado da função, respectivamente. A primeira linguagem representante da programação funcional foi o LISP, responsável pela introdução da maioria das características encontradas hoje nas linguagens de programação funcional. O Scheme representou uma tentativa de melhorar e simplificar o LISP, e será a linguagem utilizada para demonstrar o desenvolvimento de um programa utilizando programação funcional. A realização deste trabalho visa demonstrar a utilização da programação lógica e da programação funcional, aplicadas a um mesmo domínio de problema. Busca-se analisar as implementações realizadas e as formas de desenvolvê-las, para que seja possível identificar claramente as diferenças existentes entre as abordagens utilizadas. Organização do Trabalho No item 1 apresenta-se a definição do problema que será abordado, uma breve descrição do domínio e das questões que serão consideradas no desenvolver do trabalho. No item 2, realiza-se a especificação das implementações realizadas com a linguagem lógica PROLOG, uma breve descrição da mesma e alguns outros pontos importantes para o contexto do trabalho. O item 3 abrange as implementações realizadas com a linguagem funcional Scheme, demonstrando alguns blocos de código e os resultados gerados pelos mesmos. No item 4, apresentam-se as conclusões obtidas pela realização das implementações realizadas. 7 1 - Definição do Problema Com o intuito de estabelecer métricas para comparação entre paradigmas de linguagens de programação lógica e funcional, utilizamos como domínio do problema, um departamento que precisa realizar a consulta de diversas informações referentes pesquisas, professores, disciplinas, carga horária, entre outros. Para tal, definimos um esquema em Banco de Dados representado no Diagrama de Entidade e Relacionamento (figura 1), utilizando o Sistema de Gerenciamento MySql e Microsoft Access. As implementações realizadas em PROLOG, apresentaram êxito tanto com o banco de dados MySql, quanto com o gerenciador Access. Os acessos a dados realizados pela linguagem Scheme foram compatíveis somente com o Access, devido a conflitos na conexão com o banco de dados MySql. Assim sendo, o mesmo não será considerado para a analise do problema com a linguagem Scheme, mas trabalha normalmente com as implementações realizadas em PROLOG descritas neste trabalho. Figura 1 – Diagrama Entidade Relacionamento As implementações desenvolvidas nas linguagens PROLOG e Scheme, possuem como objetivo encontrar uma resposta para as seguintes perguntas: 1. 2. 3. 4. 5. 6. 7. 8. Em quais horários um professor ministra aula? Qual é o horário de uma disciplina? Quais professores são pesquisadores? Quais artigos um professor já escreveu? Quais artigos um professor já publicou? Em qual departamento um professor trabalha? Em quais cursos um professor trabalha? Em quais projetos um professor participa? Nos próximos itens serão demonstradas e explanadas, as implementações realizadas para se obter a resolução do problema. Inicialmente, consideraremos a solução do problema em PROLOG, para em seguida, apresentá-lo em Scheme. 8 2 - PROLOG A linguagem PROLOG foi utilizada para demonstrar a implementação da solução, por meio da utilização de uma linguagem lógica. Descrevemos neste tópico, alguns aspectos importantes quanto a conexão com o banco de dados, e quanto a implementação da solução para a busca das respostas especificadas. 2.1 - Conexão com Banco de Dados MySql Para realizar a conexão do PROLOG com o banco de dados MySql, após o banco ter sido criado, o driver de comunicação deve ser instalado e o ODBC precisa ser configurado (as figuras 2 e 3 ilustram esta configuração). Figura 2 – Gerenciador de Fontes de Dados Para criar uma nova fonte de dados, deve-se adicionar uma nova, e selecionar o driver MySQL ODBC 3.5.1 Driver. A configuração do mesmo deve ser realizada na tela seguinte. 9 Figura 3 – Configuração da Fonte de Dados do Sistema Nesta janela devem ser especificados os parâmetros solicitados para a configuração, tais como: banco de dados, servidor, usuário, senha, etc. O status da conexão pode ser testado com o botão “Test”. Após realizado o processo detalhado acima, as seguintes linhas de código em PROLOG, possibilitam a comunicação do mesmo com o banco de dados configurado: Para a conexão ser efetuada, são passados os parâmetros para o driver ODBC, de acordo com o que se demonstra na tabela 1. % Conexão do Prolog ao BD MySql através do ODBC-MS connecta :- odbc_connect('bdprolog', _, [user(root),password('root'),alias(bdprolog),open(once)]). Tabela 1 – Conexão do Prolog ao BD Mysql O predicado `conectado`, tabela 2, foi desenvolvida para retornar se já existe conexão ativa ou não, com a base de dados especificada. % Checagem se conexão do Prolog ao BD MySQL está ativa. conectado(NmBD, DSN) :odbc_current_connection(NmBD, DSN). Tabela 2 – Predicado Conectado 2.2 - Implementação. Baseados no esquema SQL representado no item 1, onde foram especificados os aspectos relacionados ao problema abordado neste estudo de caso, foram desenvolvidos através de scripts de consulta SQL, os predicados necessários para obtermos as 10 respostas em consultas através da linguagem de programação lógica Prolog. Os atributos identificadores são utilizados para compor os relacionamentos entre os predicados. Na seqüência, estaremos detalhando cada predicado criado para retornar acessar as informações no banco e possibilitar a realização de consultas e conseqüentemente a busca das respostas para as perguntas anteriormente definidas. O predicado departamento é utilizado para selecionar os atributos “nome do departamento” (NmDepto) e o “identificador do departamento” (IdDepto). depto(NmDepto, IdDepto) :odbc_query(bdprolog, 'Select nome_dpto, iddepartamento from departamento order by nome_dpto', row(NmDepto, IdDepto)). Tabela 3 – Predicado Departamento O predicado curso seleciona os atributos “Nome do Curso” (NmCurso), “Identificador do Curso” (IdCurso) e “Identificador do Departamento” (IdDepto). curso(NmCurso, IdCurso, IdDepto) :odbc_query(bdprolog, 'Select nome_cur, idcurso, iddepartamento from curso order by nome_cur',row(NmCurso, IdCurso, IdDepto)). Tabela 4 – Predicado Curso O predicado professor seleciona os atributos “Nome do Professor” (NmProf), “Identificador do Professor” (IdProf) e “Identificador do Departamento” (IdDepto). professor(NmProf, IdProf, IdDepto) :odbc_query(bdprolog, 'Select nome_prof, idprofessor, iddepartamento from professor order by nome_prof', row(NmProf, IdProf, IdDepto)). Tabela 5 – Predicado Professor O predicado disciplina é necessário para selecionar os atributos “Nome da Disciplina” (NmDisc), “Identificador do Curso” (IdCurso) e “Identificador da Disciplina” (IdDisc). disciplina(NmDisc, IdCurso, IdDisc) :odbc_query(bdprolog, 'Select nome_disc, iddisciplina, idcurso from disciplina order by nome_disc, idcurso', row(NmDisc, IdDisc, IdCurso)). Tabela 6 – Predicado Disciplina O predicado turno é utilizado para a seleção dos atributos “Nome do Turno” (NmTur) e “Identificador do Turno” (IdTur). turno(NmTur, IdTur) :odbc_query(bdprolog, 'Select turno, idturno from turno', row(NmTur, IdTur)). Tabela 7 – Predicado Turno 11 O predicado dia seleciona atributos “Dia da Semana” (DiaSem), “Identificador do Turno” (IdTur) e “Identificador do Dia”(IdDia). dia(DiaSem, IdTur, IdDia) :odbc_query(bdprolog, 'Select dia_sem, idturno, iddia from dia', row(DiaSem, IdTur, IdDia)). Tabela 8 – Predicado Dia O predicado horario é necessário para selecionar os atributos “Hora” (Hora), “Identificador do Dia” (IdDia) e “Identificador da Hora”(IdHora). horario(Hora, IdDia, IdHora) :odbc_query(bdprolog, 'Select horario, iddia, idhorario from horario', row(Hora, IdDia, IdHora)). Tabela 9 – Predicado Horário O predicado grupo_pesq é utilizado para selecionar os atributos referentes ao grupo de pesquisa, sendo, “Nome do Grupo” (NmGrupo) e “Identificador do Grupo” (IdGrupo). grupo_pesq(NmGrupo, IdGrupo) :odbc_query(bdprolog, 'Select nome_grupo, idgrupo_pesq from grupo_pesq', row(NmGrupo, IdGrupo)). Tabela 10 – Predicado Grupo de Pesquisa O predicado linha_pesq seleciona os atributos “Nome da Linha” (NmLinha), “Área da Linha” (AreaL) e “Identificador da Linha” (IdLinha) utilizados nas consultas referentes à “linha de pesquisa”. linha_pesq(NmLinha, AreaL, IdLinha) :odbc_query(bdprolog, 'Select nome_lin, area_lin, idlinha_pesquisa from linha_pesquisa', row(NmLinha, AreaL, IdLinha)). Tabela 11 – Predicado Linha de Pesquisa O predicado aluno é utilizado na seleção do “Nome do Aluno” (NmAluno) e “Identificados do Aluno” (IdAluno). aluno(NmAluno, IdAluno) :odbc_query(bdprolog, 'Select nome_aluno, idaluno from aluno', row(NmAluno, IdAluno)). Tabela 12 – Predicado Aluno O predicado projeto seleciona os atributos “Nome do Projeto” (NmProj), “Nome do Tema” (NmTema), “Nome da Área” (NmArea) e “Identificados do projeto” (IdProj). projeto(NmProj, NmTema, NmArea, IdProj) :odbc_query(bdprolog, 'Select nome_proj, tema_proj, area_proj, idprojeto from projeto', row(NmProj, NmTema, NmArea, IdProj)). Tabela 13 – Predicado Projeto 12 O predicado artigo é necessário para selecionar os atributos “Título do Artigo” (TitArt), “Resumo do Artigo” (resArt), “Ano do Artigo” (AnoArt), “Identificador da Linha” (IdLinha) e “Identificados do Artigo” (IdArt). artigo(TitArt, ResArt, AnoArt, IdLinha, IdArt) :odbc_query(bdprolog, 'Select titulo_art, resumo_art, ano_art, idlinha_pesquisa, idartigo from artigo', row(TitArt, ResArt, AnoArt, IdLinha, IdArt)). Tabela 14 – Predicado Artigo 2.2.3 - Questões pré-determinadas para a resolução do problema. Na seqüência, serão apresentadas as implementações construídas com base nos predicados anteriormente especificados, de modo que seja possível responder às questões definidas no inicio do projeto. 1. Qual professor ensina uma determinada disciplina? Para encontrar os professores que ministram uma determinada disciplina, utilizamos o predicado prof_disc, que é composto pelos atributos “Nome do Professor”(NmProf), “Nome do Departamento” (NmDepto), “Nome do Curso”(NmCurso) e “Nome da Disciplina” (NmDisc). prof_disc( NmProf, IdProf, NmDisc, IdDisc, IdHora):odbc_query(bdprolog, 'Select idprofessor, iddisciplina, idhorario from professor_disciplina', row(IdProf, IdDisc , IdHora)), professor(NmProf, IdProf, IdDepto), disciplina(NmDisc, IdCurso, IdDisc). Tabela 15 – Predicado Professor x Disciplina A consulta prof_disc seleciona o atributo “Nome do Professor” (NmProf), com base no parâmetro de entrada “Nome da disciplina”. O objeto “_”, utilizado na consulta, tem a finalidade de ocultar os atributos que não são necessários para esta questão. 1 ?- prof_disc(NmProf, _, 'Linguagem de Programação', _, _). NmProf = 'Sérgio' ; Yes 2 ?Tabela 16 – Resposta – Professor x Disciplina No exemplo acima, o nome da disciplina foi passado como parâmetro, e o retorno solicitado foi o nome do professor que a ministra. 2. Em quais horários um professor ministra aula? Para esta questão, foi necessário utilizar o predicado prof_disc devido ao modelo relacional armazenar o horário de aulas na tabela “professor_disciplina”, estabelecendo assim um relacionamento ternário entre professor, disciplina e hora. Foram utilizados ainda, os predicados dia, turno e horário. Os atributos mostrados 13 neste predicado são o “Nome do Professor” (NmProf), “Nome da Disciplina” (NmDisc), “Dia da Semana” (DiaSem), “Turno” (Turno) e “Hora” (Hora). hora_prof(NmProf, NmDisc, DiaSem, Turno, Hora) :prof_disc( NmProf, IdProf, NmDisc, IdHora), dia(DiaSem, IdTur, IdDia), turno(NmTur, IdTur), horario(Hora, IdDia, IdHora). Tabela 17 – Predicado Hora x Professor A execução desta consulta permite que seja exibido todos os horários de todos os professores, como segue o exemplo, ou passar por parâmetro qualquer um dos atributos aplicando um filtro para a execução da consulta. 1 ?- hora_prof(NmProf, NmDisc, DiaSem, Turno, Hora). NmProf NmDisc DiaSem Hora = = 'Sérgio' = 'Linguagem de Programação' = 'Seg' '07:30 s 08:20' ; NmProf NmDisc DiaSem Hora = = 'Sérgio' = 'Engenharia de Software' = 'Seg' '08:20 s 09:10' ; NmProf NmDisc DiaSem Hora = = 'Maria' = 'Engenharia de Software' = 'Seg' '09:40 s 10:30' ; NmProf NmDisc DiaSem Hora = = 'Luiz' = 'Algoritmo e Programação' = 'Seg' '10:30 s 11:20' ; NmProf NmDisc DiaSem Hora = = 'Antonio' = 'Contabilidade' = 'Seg' '13:30 s 14:20' ; NmProf NmDisc DiaSem Hora = = 'Joaquim' = 'Banco de Dados' = 'Seg' '14:20 s 15:10' ; NmProf NmDisc DiaSem Hora = = 'Gervásio' = 'Banco de Dados' = 'Seg' '15:40 s 16:30' ; NmProf NmDisc DiaSem Hora = = 'Luiz' = 'Banco de Dados' = 'Seg' '16:30 s 17:20' ; NmProf = 'Antonio' NmDisc = 'Banco de Dados' DiaSem = 'Seg' 14 Hora = '19:20 s 20:10' ; NmProf NmDisc DiaSem Hora = = 'Luiz' = 'História da Administração' = 'Seg' '20:10 s 21:00' ; NmProf NmDisc DiaSem Hora = = 'Gervásio' = 'Direito Penal' = 'Seg' '21:20 s 22:10' ; NmProf NmDisc DiaSem Hora = = 'Maria' = 'Direito Civil' = 'Seg' '22:10 s 23:00' ; NmProf NmDisc DiaSem Hora = = 'Antonio' = 'História' = 'Ter' '07:30 s 08:20' ; Yes 2 ?Tabela 18 – Resposta – Hora x Professor 3. Qual é o horário de uma disciplina? Para consultar o horário de uma disciplina, utilizamos o predicado hora_prof ocultando o atributo “Nome do Professor” (NmProf) e passando como parâmetro a disciplina específica no atributo “Nome da Disciplina” (NmDisc). 1 ?- hora_prof(_, 'Linguagem de Programação', DiaSem, Turno, Hora). DiaSem = 'Seg' Hora = '07:30 s 08:20' ; Yes 2 ?Tabela 19 – Resposta – Hora x Disciplina No exemplo, o nome da disciplina foi passado como parâmetro, recebendo o dia da semana e o horário da mesma. 4. Quais professores são pesquisadores? O predicado professor_pesq permite consultar os Professores que estejam classificados como pesquisadores, exibindo os atributos “Nome do Professor” (NmProf) e “Pesquisador” (Pesq). professor_pesq(NmProf, Pesq) :odbc_query(bdprolog, 'Select nome_prof, pesquisador from professor order by nome_prof', row(NmProf, Pesq)). Tabela 20 – Predicado Professor Pesquisador 15 Para encontrar os professores pesquisadores, realizamos a consulta passando o parâmetro „S‟ no atributo “Pesquisador”. 1 ?- professor_pesq(NmProf,'S'). NmProf = 'Gervásio' ; NmProf = 'Joaquim' ; NmProf = 'Maria' ; NmProf = 'Sérgio' ; Yes 2 ?Tabela 21 – Resposta – Professor Pesquisador Também é possível que seja passado determinado professor como parâmetro, para consultar se o mesmo é pesquisador ou não. 5. Quais artigos um professor já escreveu? O predicado prof_artigo realiza a consulta referente aos artigos que cada professor escreveu, mostrando os atributos “Nome do Professor” (NmProf), “Título do Artigo” (TitArt), “Resumo do Artigo” (ResArt), “Tipo de Autoria” (TpAutoria) e “Identificador do Artigo” (IdArt). prof_artigo(NmProf, TitArt, ResArt, TpAutoria, IdArt) :odbc_query(bdprolog, 'Select tipo_autoria, idartigo, idprofessor from professor_artigo', row(TpAutoria, IdArt, IdProf)), professor(NmProf, IdProf, _), artigo(TitArt, ResArt, _, _, IdArt). Tabela 22 – Predicado Professor x Artigo Consultando o predicado prof_artigo, estamos exibindo o “Nome do Professor” (NmProf), o “Título do Artigo” (TitArt) e o “Resumo do Artigo” (ResArt). Para mostrar apenas os Autores dos artigos, estamos passando o parâmetro “A”, que define o tipo de autoria do artigo como Autor e assim, ocultamos os Co-autores. 1 ?- prof_artigo(NmProf, TitArt, ResArt, 'A', _). NmProf = 'Sérgio' TitArt = 'Titulo 4' ResArt = 'Resumo do Titulo 4' ; NmProf = 'Luiz' TitArt = 'Titulo 6' ResArt = 'Resumo do Titulo 6' ; NmProf = 'Antonio' TitArt = 'Titulo 5' ResArt = 'Resumo do titulo 5' ; NmProf = 'Gervásio' TitArt = 'Titulo 2' 16 ResArt = 'Resumo do Titulo 2' ; Yes 2 ?Tabela 23 – Resposta – Professor x Artigo Caso não seja passado o parâmetro de autoria, são exibidas todas as autorias ou coautorias dos artigos, como segue o exemplo: 1 ?- prof_artigo(NmProf, TitArt, ResArt, TpAutoria, _). NmProf = 'Sérgio' TitArt = 'Titulo 4' ResArt = 'Resumo do Titulo 4' TpAutoria = 'A' ; NmProf = 'Maria' TitArt = 'Tittulo 3' ResArt = 'Resumo do Titulo 3' TpAutoria = 'C' ; NmProf = 'Maria' TitArt = 'Titulo 4' ResArt = 'Resumo do Titulo 4' TpAutoria = 'C' ; NmProf = 'Luiz' TitArt = 'Titulo 5' ResArt = 'Resumo do titulo 5' TpAutoria = 'C' ; NmProf = 'Luiz' TitArt = 'Titulo 6' ResArt = 'Resumo do Titulo 6' TpAutoria = 'A' ; NmProf = 'Antonio' TitArt = 'Titulo 5' ResArt = 'Resumo do titulo 5' TpAutoria = 'A' ; NmProf = 'Joaquim' TitArt = 'Titulo 1' ResArt = 'Resumo do Titulo 1' TpAutoria = 'C' ; NmProf = 'Joaquim' TitArt = 'Titulo 2' ResArt = 'Resumo do Titulo 2' TpAutoria = 'C' ; NmProf = 'Gervásio' TitArt = 'Titulo 2' ResArt = 'Resumo do Titulo 2' TpAutoria = 'A' ; Yes 2 ?Tabela 24 – Resposta – Professor X Artigo Autoria 17 6. Quais artigos um professor já publicou? Para encontrar os artigos publicados pelos professores, utilizamos dois predicados, sendo eles: O predicado artigo2 tem a finalidade de relacionar o artigo ao ano de submissão, utilizando os atributos “Titulo do Artigo” (TitArt), “Resumo do Artigo” (ResArt), “Ano de Submissão do Artigo” (AnoArt), “Nome da Linha de Pesquisa” (NmLinha), “Área de Pesquisa” (AreaL), “Evento em que o artigo foi submetido” (Evento), “Aceitação do Artigo” (Aceito), “Ano de Submissão” (AnoSub) e “Identificador do Artigo” (IdArt). O segundo é o predicado artigo3 que estabelece o relacionamento entre o predicado artigo2 e o predicado prof_artigo. O predicado artigo3 apresenta os atributos “Nome do Professor” (NmProf), “Tipo de Autoria” (TpAutoria), “Título do Artigo” (TitArt), “Resumo do Artigo” (ResArt), “Ano em que o artigo foi escrito” (AnoArt), “Evento em que foi submetido” (Evento), “Aceite do Artigo” (Aceito) e “Ano de submissão” (AnoSub). artigo2(TitArt, ResArt, AnoArt, NmLinha, AreaL, Evento, Aceito, AnoSub, IdArt) :odbc_query(bdprolog, 'Select titulo_art, resumo_art, ano_art, idlinha_pesquisa, idartigo from artigo', row(TitArt, ResArt, AnoArt, IdLinha, IdArt)), odbc_query(bdprolog, 'Select evento, aceito, ano, idartigo from submissao',row(Evento, Aceito, AnoSub, IdArt)), linha_pesq(NmLinha, AreaL, IdLinha). artigo3(NmProf, TpAutoria, TitArt, ResArt, AnoArt, Evento, Aceito, AnoSub) :artigo2(TitArt, ResArt, AnoArt, _, _, Evento, Aceito, AnoSub, IdArt), prof_artigo(NmProf, _, _, TpAutoria, IdArt). Tabela 25 – Predicado Artigo Para encontrar os artigos publicados por um professor, utilizamos o predicado artigo3 para realizar a consulta. Estamos passando como parâmetro o atributo “Aceito” (Aceito) como „S‟, para que no resultado seja exibido apenas os artigos que foram publicados, onde o professor seja autor ou co-autor. 1 ?- artigo3(NmProf, TpAutoria, TitArt, ResArt, AnoArt, Evento, 'S', AnoSub). NmProf = 'Joaquim' TpAutoria = 'C' TitArt = 'Titulo 1' ResArt = 'Resumo do Titulo 1' AnoArt = '2005' Evento = '3o Sei lá' AnoSub = '2005' ; NmProf = 'Joaquim' TpAutoria = 'C' TitArt = 'Titulo 2' ResArt = 'Resumo do Titulo 2' 18 AnoArt = '2006' Evento = 'Simpósio Nacional de Blá Blá Blá' AnoSub = '2006' ; NmProf = 'Gervásio' TpAutoria = 'A' TitArt = 'Titulo 2' ResArt = 'Resumo do Titulo 2' AnoArt = '2006' Evento = 'Simpósio Nacional de Blá Blá Blá' AnoSub = '2006' ; NmProf = 'Maria' TpAutoria = 'C' TitArt = 'Tittulo 3' ResArt = 'Resumo do Titulo 3' AnoArt = '2004' Evento = '4o Encontro de Blá Blá' AnoSub = '2004' ; NmProf = 'Sérgio' TpAutoria = 'A' TitArt = 'Titulo 4' ResArt = 'Resumo do Titulo 4' AnoArt = '2005' Evento = 'Semana do Saco Cheio' AnoSub = '2004' ; NmProf = 'Maria' TpAutoria = 'C' TitArt = 'Titulo 4' ResArt = 'Resumo do Titulo 4' AnoArt = '2005' Evento = 'Semana do Saco Cheio' AnoSub = '2004' ; NmProf = 'Luiz' TpAutoria = 'C' TitArt = 'Titulo 5' ResArt = 'Resumo do titulo 5' AnoArt = '2003' Evento = 'Congresso de ETs' AnoSub = '2003' ; NmProf = 'Antonio' TpAutoria = 'A' TitArt = 'Titulo 5' ResArt = 'Resumo do titulo 5' AnoArt = '2003' Evento = 'Congresso de ETs' AnoSub = '2003' ; Yes 2 ?Tabela 26 – Resposta Artigo Professor Na execução abaixo, passamos também o parâmetro “Tipo de Autoria” (TpAutoria) como „A‟ para limitar os resultados em apenas os artigos publicados dos professores que foram autores destes artigos. 19 1 ?- artigo3(NmProf, 'A',TitArt,ResArt,AnoArt,Evento,'S',AnoSub). NmProf TitArt ResArt AnoArt Evento AnoSub = = = = = = 'Gervásio' 'Titulo 2' 'Resumo do Titulo 2' '2006' 'Simpósio Nacional de Blá Blá Blá' '2006' ; NmProf TitArt ResArt AnoArt Evento AnoSub = = = = = = 'Sérgio' 'Titulo 4' 'Resumo do Titulo 4' '2005' 'Semana do Saco Cheio' '2004' ; NmProf TitArt ResArt AnoArt Evento AnoSub = = = = = = 'Antonio' 'Titulo 5' 'Resumo do titulo 5' '2003' 'Congresso de ETs' '2003' ; Yes 2 ?Tabela 27 – Resposta Artigo Professor Autoria 7. Em qual departamento um professor trabalha? O predicado prof_depto é utilizado na consulta que resulta em qual departamento um professor trabalha. Este predicado apresenta o atributo “Nome do Professor” (NmProf) e “Nome do Departamento” (NmDepto). prof_depto(NmProf, NmDepto) :professor(NmProf, _, IdDepto), depto(NmDepto, IdDepto). Tabela 28 – Predicado Professor x Departamento Ao realizar a consulta com o predicado pro_depto, foram exibidos apenas os atributos “Nome do Professor” (NmProf) e “Nome do Departamento” (NmDepto). No caso de uma consulta específica, podemos passar como parâmetros tanto o Nome do Professor como o Nome do Departamento, filtrando as informações de acordo com a necessidade. 1 ?- prof_depto(NmProf, NmDepto). NmProf = 'Antonio' NmDepto = 'Departamento de Administração' ; NmProf = 'Gervásio' NmDepto = 'Departamento de Ciências Humanas' ; NmProf = 'Joaquim' NmDepto = 'Departamento de Ciências Humanas' ; NmProf = 'Luiz' NmDepto = 'Departamento de Administração' ; 20 NmProf = 'Maria' NmDepto = 'Departamento de Informática' ; NmProf = 'Sérgio' NmDepto = 'Departamento de Informática' ; Yes 2 ?Tabela 29 – Resposta – Professor x Departamento 8. Em quais cursos um professor trabalha? Para o predicado prof_curso foi utilizados os predicados prof_disc, disciplina e curso, estabelecendo os relacionamentos que são necessários. O predicado prof_curso está exibindo os atributos “Nome do Professor”(NmProf) e “Nome do Curso” (NmCurso). prof_curso(NmCurso, NmProf) :prof_disc( NmProf, IdProf, NmDisc, IdDisc, IdHora), disciplina(NmDisc, IdCurso, IdDisc), curso(NmCurso, IdCurso, IdDepto). Tabela 30 – Predicado Professor x Curso Na execução da consulta no predicado prof_curso, estamos passando por parâmetro o nome do professor para filtrar os cursos que o mesmo participa. 1 ?- prof_curso(NmCurso, 'Sérgio'). NmCurso = 'Ciência da Computação' ; Yes 2 ?Tabela 31 – Resposta Professor x Curso 9. Em quais projetos um professor participa? O predicado prof_projeto apresenta os atributos “Nome do Professor” (NmProf), “Nome do Projeto” (NmProj), “Nome do Tema” (NmTema) e “Nome da Área” (NmArea) e utiliza os predicados professor e projeto para obter o resultado quais projetos um professor participa. prof_projeto(NmProf, NmProj, NmTema, NmArea) :odbc_query(bdprolog, 'Select idprofessor, idprojeto from professor_projeto', row(IdProf, IdProj)), professor(NmProf, IdProf, _), projeto(NmProj, NmTema, NmArea, IdProj). Tabela 32 – Predicado Professor x Projeto Podemos passar como parâmetro qualquer um dos atributos para estabelecer algum filtro. 1 ?- prof_projeto(NmProf, NmProj, NmTema, NmArea). NmProf = 'Sérgio' 21 NmProj = 'Projeto 1 - Grupo 1' NmTema = 'Tema 1' NmArea = 'Area 1' ; NmProf NmProj NmTema NmArea = = = = 'Maria' 'Projeto 1 - Grupo 1' 'Tema 1' 'Area 1' ; Yes 2 ?Tabela 33 – Resposta Professor x Projeto Pode-se verificar nos predicados e nas regras criadas, que o PROLOG é uma linguagem eficiente e prática para a realização de consultas. Essa facilidade é uma das causas que torna a linguagem muito utilizada na área de inteligência artificial entre outras aplicações. Os predicados foram desenvolvidos e possibilitaram a realização de todas as consultas. Em uma linguagem imperativa, tenderíamos a concentrar os esforços diretamente nas cláusulas SQL, para que estas já retornassem os dados solicitados, de acordo com os filtros repassados para a mesma. A linguagem lógica possibilita que os predicados trabalhem para retornar a informação desejada, e se mostra muito eficiente neste processo. 3 - Scheme As implementações em uma linguagem funcional serão desenvolvidas em Scheme. Nos próximos itens estaremos descrevendo como foi realizado o acesso ao banco de dados, como foram obtidas algumas respostas para as questões mencionadas, e também algumas limitações que não foram contornadas utilizando este linguagem. 3.1 - Conexão com Banco de Dados Para a implementação utilizando a linguagem Scheme, utilizou-se um banco de dados com a mesma estrutura do banco utilizado em MySql para o PROLOG (este banco em Access também pode ser utilizado normalmente com os códigos PROLOG detalhados no item anterior). A configuração da fonte de dados segue basicamente os mesmos passos descritos na configuração para o PROLOG, no qual deve-se adicionar a fonte desejada e especificar o banco a que ela deverá estar relacionada. 22 Figura 4 – Fonte de Dados para Access Para a conexão do Scheme com o banco de dados, a seguinte cláusula deverá ser incluída no código: ;; Carga do srpersist (require (lib "srpersist.ss" "srpersist")) Tabela 34 – Função de conexão Este comando relaciona o arquivo srpersist.ss, que estará possibilitando a comunicação com a base de dados utilizada. Sem o relacionamento com este arquivo, não é possível realizar operações com acesso ao banco. Após isso, também exige-se a inclusão da seguinte cláusula: ;; Antes de connectar-se a um banco, é necessário alocar um 'Environment Handle' e um 'Connection Handle' (define henv (alloc-env)) (define hdbc (alloc-connect henv)) Tabela 35 – Alocação de 'Environment Handle' e um 'Connection Handle' Por fim, deve-se incluir um comando que realizará uma chamada externa para que o usuário esteja selecionando a fonte de dados à qual deseja se conectar (figura 5). Após selecionada a fonte de dados, o programa encontra-se pronto para utilização. 23 Figura 5 – Seleção de Fonte de Dados O comando que realiza esta chamada, é descrito abaixo: ; Chamada externa para identificar o drive ODBC (driver-connect hdbc " " 'sql-driver-complete) Tabela 36 – Chamada externa ao drive ODBC 3.3 - Implementação Para a implementação com Scheme, também foi utilizado o esquema SQL representado no item 1. Assim como em Prolog, as listas necessárias para a resolução dos problemas vistos neste estudo de caso, foram criadas também através de scripts de consulta SQL. A função União, foi definida com a finalidade de auxiliar na construção das listas a partir das consultas sql. A lista é criada a partir de uma varredura em todas as tuplas resultantes da consulta, onde cada tupla, é criada uma nova lista, incluída na lista ancestral. Na tabela abaixo, mostramos o código da função união. (define (uniao a b) (if (null? a) b (cons (car a) (uniao (cdr a) b)))) Tabela 37 – Função União 24 Para verificar quais os elementos que existem na lista, utilizamos a função pertence?. (define (pertence? x l) (if (null? l) #f (if (equal? x (car l)) #t (pertence? x (cdr l))))) Tabela 38 – Função Pertence? A função consul é utilizada em todas as questões para criar as listas de respostas. Esta função trabalha de forma genérica, removendo todos os elementos que não fazem parte da resposta. (define consul (lambda (chave tabela) (cond ((null? tabela) '()) ((pertence? chave (car tabela)) (cons (car tabela) (consul chave (cdr tabela)))) (else (consul chave (cdr tabela))) ))) Tabela 39 – Chamada e Execução do Script SQL Para a realização de consultas em cada tabela criada em SQL, é utilizada a função hstmt, exibida na tabela abaixo, que tem por objetivo retornar a conexão com o banco para a execução da consulta. É repetida a definição desta função em cada consulta realizada. (define hstmt (alloc-stmt hdbc)) Tabela 40 – Função HSTMT A chamada ao script SQL é realizada através da função prepare hstm, onde é passada a consulta em SQL e é executada pela função sql-execute, conforme o exemplo exibido na tabela 41. (prepare hstmt "Select pesquisador, nome_prof from Professor order by nome_prof") (sql-execute hstmt) Tabela 41 – Chamada e Execução do Script SQL Para cada questão pré-definida, fizemos o uso de funções para a criação de buffers para cada atributo resultante das consultas SQL, com seus respectivos tipos associados. E também, utilizamos funções para a criação de indicadores para cada atributo. E ainda, para a execução das rotinas fizemos uso de códigos semelhantes, onde alterou apenas os buffers e os indicadores, criados para cada consulta, como poderá ser visto nas especificações de cada questão. 25 3.3.1 - Questões pré-determinadas para a resolução do problema. Na seqüência, são exibidos os códigos para geração impressão das listas criadas para responder as perguntas definidas neste estudo de caso. Estas implementações fazem uso das funções anteriormente especificadas. 1. Em quais horários um professor ministra aula? Para criar a lista que responde a questão acima, a função prepare, para receber a consulta SQL desta questão e a função sql-execute para executar esta consulta, como já foi explicado. Estes códigos estão exibidos na tabela 42. ; Chamada para SQL (prepare hstmt "SELECT p.nome_prof, h.horario, d.dia_sem FROM professor AS p, professor_disciplina AS pd, horario AS h, dia d WHERE (((p.idprofessor)=[pd].[idprofessor]) AND ((pd.idhorario)=[h].[idhorario]))and h.iddia=d.iddia order by p.nome_prof") (sql-execute hstmt) Tabela 42 – Chamada e Execução do Script SQL – 1ª questão Criação dos buffers e indicadores. ; Criação de buffer para cada atributo do SQL com respectivo formato (colocar na sequencia) (define nmprof-buf (make-buffer 'sql-c-char 50)) (define nmhora-buf (make-buffer 'sql-c-char 50)) (define nmdia-buf (make-buffer 'sql-c-char 50)) ; --- comando obrigatório ; Criação de indicador para cada atributo do SQL (define nmprof-ind (make-indicator)) (define nmhora-ind (make-indicator)) (define nmdia-ind (make-indicator)) (define-struct r_prof (pesqui nmprof nmdia)) (define cria-lista (lambda (lista-i lista-c) (cons lista-i (cria-lista )))) (define resul_hora '()) ; Rotina de execução (with-handlers ([(lambda (exn) (exn-no-data? exn)) (lambda (exn) (printf "~n*** Fim dos dados ***~n"))]) (let loop () (fetch hstmt) (get-data hstmt 1 nmprof-buf nmprof-ind) (get-data hstmt 2 nmhora-buf nmhora-ind) (get-data hstmt 3 nmdia-buf nmdia-ind) ; Display dos atributos de professor em formatto de lista. (display (list (read-buffer nmprof-buf 0) 26 (read-buffer nmhora-buf 0) (read-buffer nmdia-buf 0))) (newline) (list (read-buffer nmprof-buf 0) (read-buffer nmhora-buf 0) (read-buffer nmdia-buf 0)) (set! resul_hora (uniao resul_hora (list(list (read-buffer nmprof-buf 0) (read-buffer nmhora-buf 0) (read-buffer nmdia-buf 0))))) (free-buffer! nmprof-buf) (free-buffer! nmhora-buf) (free-buffer! nmdia-buf) (loop))) Tabela 43 – Buffers e Indicadores – 1ª questão. Para obter a resposta a questão, executamos a função cônsul, onde são passados os parâmetros o nome do professor “Sérgio” que será a chave para a consulta e a função resul_hora que armazena, em formato de lista, todas as tuplas resultantes da consulta SQL. A chamada a função e o resultado são exibidos na tabela 44. > (consul "Sérgio" resul_hora) (("Sérgio" "08:20 s 09:10" "Seg") ("Sérgio" "07:30 s 08:20" "Seg")) > Tabela 44 – Chamada da função cônsul e o resultado – 1ª questão. 2. Qual é o horário de uma disciplina? Na tabela 45, mostramos as funções prepare, a criação dos buffers e indicadores, e a rotina de execução. ; Chamada para SQL (prepare hstmt "SELECT d.nome_disc, h.horario FROM disciplina AS d, horario AS h, professor_disciplina AS pd WHERE (((d.iddisciplina)=[d].[iddisciplina]) AND ((pd.idhorario)=[h].[idhorario])) ORDER BY d.nome_disc") (sql-execute hstmt) ; Informa o nro de colunas resultado do sql (display (num-result-cols hstmt)) (newline)(newline) ; Criação de buffer para cada atributo do SQL com respectivo formato (colocar na sequencia) (define nmdisc-buf (make-buffer 'sql-c-char 50)) (define nmhora-buf (make-buffer 'sql-c-char 50)) ; --- comando obrigatório ; Criação de indicador para cada atributo do SQL (define nmdisc-ind (make-indicator)) (define nmhora-ind (make-indicator)) (define resul_dischora '()) ; Rotina de execução (with-handlers 27 ([(lambda (exn) (exn-no-data? exn)) (lambda (exn) (printf "~n*** Fim dos dados ***~n"))]) (let loop () (fetch hstmt) (get-data hstmt 1 nmdisc-buf nmdisc-ind) (get-data hstmt 2 nmhora-buf nmhora-ind) ; Display dos atributos de professor em formatto de lista. (display (list (read-buffer nmdisc-buf 0) (read-buffer nmhora-buf 0))) (newline) (list (read-buffer nmdisc-buf 0) (read-buffer nmhora-buf 0)) (set! resul_dischora (uniao resul_dischora (list(list (read-buffer nmdisc-buf 0) (read-buffer nmhora-buf 0))))) (free-buffer! nmdisc-buf) (free-buffer! nmhora-buf) (loop))) Tabela 45 – Buffer, indicadores e rotinas de execução – 2ª questão. Na execução da função consul, mostrada na tabela 46, passamos como parâmetro “Linguagem” que faz a busca na lista resul_dischora resultante da consulta SQL. > (consul "Linguagem" resul_dischora) (("Linguagem" "07:30 s 08:20") ("Linguagem" "20:10 s 21:00") ("Linguagem" "16:30 s 17:20") ("Linguagem" "07:30 s 08:20") ("Linguagem" "08:20 s 09:10") ("Linguagem" "22:10 s 23:00") ("Linguagem" "19:20 s 20:10") ("Linguagem" "10:30 s 11:20") ("Linguagem" "14:20 s 15:10") ("Linguagem" "09:40 s 10:30") ("Linguagem" "21:20 s 22:10 ") ("Linguagem" "13:30 s 14:20") ("Linguagem" "15:40 s 16:30")) > Tabela 46 – Chamada da função cônsul e o resultado – 2ª questão. 3. Quais professores são pesquisadores? Função prepare e chamada a execução do SQL. (prepare hstmt "Select pesquisador, nome_prof from Professor order by nome_prof") (sql-execute hstmt) Tabela 47 – Chamada e Execução do Script SQL – 3ª questão A tabela 48 mostra o código de criação do buffer e indicadores. 28 ; Criação de buffer para cada atributo do SQL com respectivo formato (colocar na sequencia) (define pesqui-buf (make-buffer 'sql-c-char 2)) (define nmprof-buf (make-buffer 'sql-c-char 50)) ; --- comando obrigatório ; Criação de indicador para cada atributo do SQL (define pesqui-ind (make-indicator)) (define nmprof-ind (make-indicator)) (define-struct r_prof (pesqui nmprof)) (define cria-lista (lambda (lista-i lista-c) (cons lista-i (cria-lista )))) (define resul_professor '()) ; Rotina de execução (with-handlers ([(lambda (exn) (exn-no-data? exn)) (lambda (exn) (printf "~n*** Fim dos dados ***~n"))]) (let loop () (fetch hstmt) (get-data hstmt 1 pesqui-buf pesqui-ind) (get-data hstmt 2 nmprof-buf nmprof-ind) ; Display dos atributos de professor em formatto de lista. (display (list (read-buffer pesqui-buf 0) (read-buffer nmprof-buf 0))) (newline) (list (read-buffer pesqui-buf 0) (read-buffer nmprof-buf 0)) (set! resul_professor (uniao resul_professor (list(list (read-buffer pesqui-buf 0) (read-buffer nmprof-buf 0))))) (free-buffer! pesqui-buf) (free-buffer! nmprof-buf) (loop))) Tabela 48 – Buffers e Indicadores – 3ª questão. Para obter a resposta a questão, executamos a função cônsul, onde são passados os parâmetros “S”. A função resul_professor que é utilizada para guardar os armazenar os valores durante a varredura em todas as tuplas da tabela. A chamada a função e o resultado é exibido na tabela 49. > (consul "S" resul_professor) (("S" "Maria Conceição") ("S" "Sérgio")) > Tabela 49 – Chamada da função cônsul e o resultado de professor – 3ª questão. 29 4. Quais artigos um professor já escreveu? Na tabela 50, mostramos as funções prepare, a criação dos buffers e indicadores, e a rotina de execução. ; Chamada para SQL (prepare hstmt "SELECT professor.nome_prof, artigo.titulo_art, professor_artigo.tipo_autoria FROM artigo, professor, professor_artigo WHERE professor_artigo.idprofessor = professor.idprofessor and professor_artigo.idartigo = artigo.idartigo and professor_artigo.tipo_autoria='A' ORDER BY professor.nome_prof") (sql-execute hstmt) ; Informa o nro de colunas resultado do sql (display (num-result-cols hstmt)) (newline)(newline) ; Criação de buffer para cada atributo do SQL com respectivo formato (colocar na sequencia) (define nmprof-buf (make-buffer 'sql-c-char 50)) (define nmarti-buf (make-buffer 'sql-c-char 50)) ; --- comando obrigatório ; Criação de indicador para cada atributo do SQL (define nmprof-ind (make-indicator)) (define nmarti-ind (make-indicator)) (define-struct r_prof (pesqui nmprof)) (define cria-lista (lambda (lista-i lista-c) (cons lista-i (cria-lista )))) (define resul_artigo '()) ; Rotina de execução (with-handlers ([(lambda (exn) (exn-no-data? exn)) (lambda (exn) (printf "~n*** Fim dos dados ***~n"))]) (let loop () (fetch hstmt) (get-data hstmt 1 nmprof-buf nmprof-ind) (get-data hstmt 2 nmarti-buf nmarti-ind) ; Display dos atributos de professor em formatto de lista. (display (list (read-buffer nmprof-buf 0) (read-buffer nmarti-buf 0))) (newline) (list (read-buffer nmprof-buf 0) (read-buffer nmarti-buf 0)) (set! resul_artigo (uniao resul_artigo (list(list (read-buffer nmprof-buf 0) (read-buffer nmarti-buf 0))))) (free-buffer! nmprof-buf) 30 (free-buffer! nmarti-buf) (loop))) Tabela 50– Buffer, indicadores e rotinas de execução – 4ª questão. Na execução da função consul, mostrada na tabela 51, passamos como parâmetro “Linguagem” que faz a busca na lista resul_artigo resultante da consulta SQL. > (consul "Sérgio" resul_artigo) (("Sérgio" "Titulo 4")) > Tabela 51 – Chamada da função cônsul e o resultado – 4ª questão. 5. Quais artigos um professor já publicou? Na tabela 52, mostramos as funções prepare, a criação dos buffers e indicadores, e a rotina de execução. ; Chamada para SQL (prepare hstmt "SELECT professor.nome_prof, artigo.titulo_art FROM artigo, professor, professor_artigo WHERE professor_artigo.idprofessor = professor.idprofessor and professor_artigo.idartigo = artigo.idartigo ORDER BY professor.nome_prof") (sql-execute hstmt) ; Informa o nro de colunas resultado do sql (display (num-result-cols hstmt)) (newline)(newline) ; Criação de buffer para cada atributo do SQL com respectivo formato (colocar na sequencia) (define nmprof-buf (make-buffer 'sql-c-char 50)) (define nmarti-buf (make-buffer 'sql-c-char 50)) ; --- comando obrigatório ; Criação de indicador para cada atributo do SQL (define nmprof-ind (make-indicator)) (define nmarti-ind (make-indicator)) (define-struct r_prof (pesqui nmprof)) (define cria-lista (lambda (lista-i lista-c) (cons lista-i (cria-lista )))) (define resul_artigo '()) ; Rotina de execução (with-handlers ([(lambda (exn) (exn-no-data? exn)) (lambda (exn) (printf "~n*** Fim dos dados ***~n"))]) (let loop () (fetch hstmt) (get-data hstmt 1 nmprof-buf nmprof-ind) (get-data hstmt 2 nmarti-buf nmarti-ind) 31 ; Display dos atributos de professor em formatto de lista. (display (list (read-buffer nmprof-buf 0) (read-buffer nmarti-buf 0))) (newline) (list (read-buffer nmprof-buf 0) (read-buffer nmarti-buf 0)) (set! resul_artigo (uniao resul_artigo (list(list (read-buffer nmprof-buf 0) (read-buffer nmarti-buf 0))))) (free-buffer! nmprof-buf) (free-buffer! nmarti-buf) (loop))) Tabela 52 – Buffer, indicadores e rotinas de execução – 5ª questão. Na tabela 53 mostra a execução da função consul, passamos como parâmetro “Sérgio” que faz a busca na lista resul_artigo resultante da consulta SQL. > (consul "Sérgio" resul_artigo) (("Sérgio" "Titulo 4")) > Tabela 53– Chamada da função cônsul e o resultado – 5ª questão. 6. Em qual departamento um professor trabalha? Na tabela 54, mostramos as funções prepare, a criação dos buffers e indicadores, e a rotina de execução. ; Chamada para SQL (prepare hstmt "select p.nome_prof, d.nome_dpto from departamento d, professor p where p.iddepartamento=d.iddepartamento order by d.nome_dpto") (sql-execute hstmt) ; Informa o nro de colunas resultado do sql (display (num-result-cols hstmt)) (newline)(newline) ; Criação de buffer para cada atributo do SQL com respectivo formato (colocar na sequencia) (define nmprof-buf (make-buffer 'sql-c-char 50)) (define nmdpto-buf (make-buffer 'sql-c-char 50)) ; --- comando obrigatório ; Criação de indicador para cada atributo do SQL (define nmprof-ind (make-indicator)) (define nmdpto-ind (make-indicator)) (define resul_depto '()) ; Rotina de execução (with-handlers ([(lambda (exn) (exn-no-data? exn)) (lambda (exn) (printf "~n*** Fim dos dados ***~n"))]) 32 (let loop () (fetch hstmt) (get-data hstmt 1 nmprof-buf nmprof-ind) (get-data hstmt 2 nmdpto-buf nmdpto-ind) ; Display dos atributos de professor e departamento em formatto de lista. (display (list (read-buffer nmprof-buf 0) (read-buffer nmdpto-buf 0))) (newline) (list (read-buffer nmprof-buf 0) (read-buffer nmdpto-buf 0)) (set! resul_depto (uniao resul_depto (list(list (read-buffer nmprof-buf 0) (read-buffer nmdpto-buf 0))))) (free-buffer! nmprof-buf) (free-buffer! nmdpto-buf) (loop))) Tabela 54 – Buffer, indicadores e rotinas de execução – 6ª questão. Na tabela 55 mostra a execução da função consul, passamos como parâmetro “Sérgio” que faz a busca na lista resul_depto resultante da consulta SQL. > (consul "Sérgio" resul_depto) (("Sérgio" "DepartamentoInformtica")) > Tabela 55– Chamada da função cônsul e o resultado – 6ª questão. 7. Em quais cursos um professor trabalha? Na tabela 56, mostramos as funções prepare, a criação dos buffers e indicadores, e a rotina de execução para a questão 7. ; Chamada para SQL (prepare hstmt "select p.nome_prof, c.nome_cur from professor p, curso c, disciplina d, professor_disciplina pd where pd.iddisciplina=d.iddisciplina and pd.idprofessor=p.idprofessor and d.idcurso=c.idcurso order by p.nome_prof") (sql-execute hstmt) ; Informa o nro de colunas resultado do sql (display (num-result-cols hstmt)) (newline)(newline) ; Criação de buffer para cada atributo do SQL com respectivo formato (colocar na sequencia) (define nmprof-buf (make-buffer 'sql-c-char 50)) (define nmcurs-buf (make-buffer 'sql-c-char 50)) ; --- comando obrigatório ; Criação de indicador para cada atributo do SQL (define nmprof-ind (make-indicator)) (define nmcurs-ind (make-indicator)) (define resul_curso '()) 33 ; Rotina de execução (with-handlers ([(lambda (exn) (exn-no-data? exn)) (lambda (exn) (printf "~n*** Fim dos dados ***~n"))]) (let loop () (fetch hstmt) (get-data hstmt 1 nmprof-buf nmprof-ind) (get-data hstmt 2 nmcurs-buf nmcurs-ind) ; Display dos atributos de professor e departamento em formatto de lista. (display (list (read-buffer nmprof-buf 0) (read-buffer nmcurs-buf 0))) (newline) (list (read-buffer nmprof-buf 0) (read-buffer nmcurs-buf 0)) (set! resul_curso (uniao resul_curso (list(list (read-buffer nmprof-buf 0) (read-buffer nmcurs-buf 0))))) (free-buffer! nmprof-buf) (free-buffer! nmcurs-buf) (loop))) Tabela 56 – Buffer, indicadores e rotinas de execução – 7ª questão. Na tabela 57 mostra a execução da função consul, passamos como parâmetro “Sérgio” que faz a busca na lista resul_curso resultante da consulta SQL. > (consul "Sérgio" resul_curso) (("Sérgio" "CiênciaComputação") ("Sérgio" "CiênciaComputação")) > Tabela 57– Chamada da função cônsul e o resultado – 7ª questão. 8. Em quais projetos um professor participa? Na tabela 58, mostramos as funções prepare, a criação dos buffers e indicadores, e a rotina de execução. ; Chamada para SQL (prepare hstmt "SELECT p.nome_prof, pj.nome_proj FROM professor AS p, projeto AS pj, professor_projeto AS pp WHERE p.idprofessor=pp.idprofessor and pj.idprojeto=pp.idprojeto ORDER BY p.nome_prof") (sql-execute hstmt) ; Informa o nro de colunas resultado do sql (display (num-result-cols hstmt)) (newline)(newline) ; Criação de buffer para cada atributo do SQL com respectivo formato (colocar na sequencia) (define nmprof-buf (make-buffer 'sql-c-char 50)) (define nmproj-buf (make-buffer 'sql-c-char 50)) 34 ; --- comando obrigatório ; Criação de indicador para cada atributo do SQL (define nmprof-ind (make-indicator)) (define nmproj-ind (make-indicator)) (define resul_proj '()) ; Rotina de execução (with-handlers ([(lambda (exn) (exn-no-data? exn)) (lambda (exn) (printf "~n*** Fim dos dados ***~n"))]) (let loop () (fetch hstmt) (get-data hstmt 1 nmprof-buf nmprof-ind) (get-data hstmt 2 nmproj-buf nmproj-ind) ; Display dos atributos de professor e do projeto. (display (list (read-buffer nmprof-buf 0) (read-buffer nmproj-buf 0))) (newline) (list (read-buffer nmprof-buf 0) (read-buffer nmproj-buf 0)) (set! resul_proj (uniao resul_proj (list(list (read-buffer nmprof-buf 0) (read-buffer nmproj-buf 0))))) (free-buffer! nmprof-buf) (free-buffer! nmproj-buf) (loop))) Tabela 58 – Buffer, indicadores e rotinas de execução – 8ª questão. Na tabela 59 mostra a execução da função consul, passamos como parâmetro “Sérgio” que faz a busca na lista resul_ proj resultante da consulta SQL. > (consul "Sérgio" resul_proj) (("Sérgio" "Projeto1Grupo1")) > Tabela 59– Chamada da função cônsul e o resultado – 8ª questão. 35 4 - Conclusão Trabalhar na busca de solução para um problema específico utilizando os paradigmas lógico e funcional, permitiu pela prática, a inferência de muitos itens que dizem respeito à importância, às diferenças, às dificuldades, facilidades e características próprias de cada abordagem. No decorrer deste trabalho, percebemos que mudar de paradigma é muito mais do que simplesmente aprender e compreender uma nova linguagem de programação; a forma de pensar, de raciocinar, de buscar a solução para um problema também tem de ser modificada. Cada paradigma distinto, corresponde à uma forma particular de resolver e representar um problema, e isto exige que a nossa capacidade de pensamento ajustese às formas de cada um. Essa questão de „pensar diferente‟ contribui para que estejamos, não só aprendendo a ver de várias formas a mesma solução para um problema, mas também, a construir e elaborar estruturas de raciocínio, que nos permitam ver várias soluções para um mesmo problema. Torna-se possível evoluir na forma como costumamos abordar e propor soluções para os problemas de uma forma geral. Nas experiências realizadas utilizando o paradigma funcional, a busca pela solução ocasionou uma alteração radical em nossa forma „comum‟ de tratar um problema. Foi necessária a definição de funções, a utilização de mecanismos de controle recursivos ao invés de iterativos, e também, uma série de procedimentos completamente diferentes dos métodos utilizados nas linguagens imperativas (como a não utilização de variáveis e de comandos de atribuição). No contexto do problema, a linguagem funcional Scheme apresentou-se mais complexa para se aprender e implementar, porém, as respostas para as perguntas realizadas puderam ser obtidas através da criação de uma única função, criada para trabalhar com uma lista que disponibiliza as informações acessadas na base de dados. Considerando-se as implementações efetuadas utilizando o paradigma da programação em lógica, o seu desenvolvimento exigiu um meio totalmente diferente de codificação, porém, menos conflitante com nossa capacidade e com nosso costume de raciocinar sobre os problemas do mundo real. Na abordagem lógica, a representação do problema a ser resolvido deve ser expressa na forma de lógica simbólica, e um programa não é caracterizado por uma seqüência de operações como é o caso das linguagens imperativas, e sim por uma „base de conhecimento‟ relacionada ao domínio do problema, juntamente com as perguntas realizadas para a mesma. As implementações realizadas em Prolog foram mais facilmente elaboradas e construídas que em Scheme, porém, exigiram um volume de codificação significativamente maior, visto que não é possível definir perguntas tão genéricas, numa mesma proporção em que é possível criar funções deste tipo em uma linguagem funcional. Uma avaliação sobre as duas abordagens, exigiria a análise de um complexo conjunto de fatores como domínio do problema, propósito da implementação, conhecimento e experiência dos programadores etc, para então ser possível optar por qual delas utilizar. Uma linguagem lógica é mais prática para retornar respostas às perguntas realizadas (o caso do nosso problema), enquanto que uma linguagem funcional seria mais indicada para implementações que exigem cálculo e operações matemáticas mais complexas. Assim, no contexto da realização do trabalho, podemos mencionar que as principais representações de cada paradigma são: as "funções" aplicadas aos argumentos e que retornam os valores no caso do paradigma 36 funcional, e as "proposições", aceitas como verdadeiras em um certo domínio no caso do paradigma lógico. 37 5 – Referencias Bibliográficas BARANAUSKAS, Maria Cecília Calani; Procedimento, Função, Objeto ou Lógica? Linguagens de Programação Vistas Pelos Seus Paradigmas; NIED UNICAMP; 1998. CASANOVA, Marco A; GIORNO, Fernando A. C.; FURTADO, Antonio L.; Programação em Lógica e a Linguagem Prolog; São Paulo, Ed. Edgard Blücher Ltda; 1987. GHEZZI, Carlo; JAZAYERI, Mehdi. Programminf Language Concepts. 3 ed – USA;1997. PUC-RJ; http://www.inf.puc-rio.br/~roberto/icc/texto/icc.html; acessado em novembro/2006. SEBESTA, Robert W; Conceitos de linguagens de programação; 5 ed. – Porto Alegre, Bookman; 2003. VICENTE, André Abe; Apostila Prolog; http://www.inf.unioeste.br/~abvicente; acessado em outubro/2006.