Zona HTML Zona Java Zona PHP Zona ASP Zona Bases de datos
Inicio > Tutoriales > Otros lenguajes > Prolog > Curso intermedio de programación en Prolog
-Tutoriales

Curso intermedio de programación en Prolog


Entrada/Salida

. Streams

Como en todos los lenguajes, en Prolog existe la posibilidad de manejar entrada/salida, esto es, ficheros, pantalla, impresoras, etc. Todo ello se hace a través de streams (concepto idéntico al de otros lenguajes).

Los streams son buffers para escribir y/o leer de dispositivos como el teclado, la pantalla, el disco, etc. De modo que consideramos tres tipos de streams:

  • Streams de entrada (lectura).
  • Streams de salida (escritura).
  • Streams de entrada y salida (híbridos).

Existen dos grupos de predicados para manejar streams:

  • Aquellos donde el stream se indica explícitamente. Se suelen utilizar para manipular ficheros y sockets.
  • Aquellos donde el stream es ímplicito. Manipulan la entrada y salida standard, lo que habitualmente supone el teclado y la pantalla.

. Entrada/Salida standard

Cada vez que ejecutamos un programa, éste tiene predefinidos tres streams correspondientes a la entrada, salida y error standard. Los siguientes predicados sirven para conocer cuales son dichos streams:

Predicado Modo de uso Descripción
current_output/1 current_output(-Stream) Retorna el stream asociado a la salida standard
current_input/1 current_input(-Stream) Retorna el stream asociado a la entrada standard

Un programa siempre puede cambiar dichos streams para que se dirijan a otros dispositivos. El nuevo stream debe obtenerse mediante alguno de los predicados que veremos más tarde.

Predicado Modo de uso Descripción
set_output/1 set_output(+Stream) Cambia el stream asociado a la salida standard
set_input/1 set_input(+Stream) Cambia el stream asociado a la entrada standard

. Entrada standard

El predicado estrella para leer de la entrada standard es read/1 cuyo modo de uso es read(-Term). Dicho predicado es capaz únicamente de leer términos que estarán separados unos de otros por un punto (.) y un salto de línea, igual que cuando tecleamos en el top-level shell.

Cuando ya no hay más términos para leer en la entrada standard, el predicado retorna el término end_of_file/0.

Si leer términos no es lo nuestro, simpre podemos leer caracteres uno a uno mediante el predicado get/1. Su modo de uso es get(-Char) y retorna el código ASCII del caracter leido. Cuando ya no hay más caracteres retorna -1.

. Salida standard

Para escribir en la salida standard disponemos del predicado write/1 que recibe un término como argumento. Análogamente a la entrada standard, el predicado put/1 escribe caracteres simples, recibiendo como argumento el codigo ASCII correspondiente.

Adicionalmente existen los predicados display/1 cuyo efecto es el mismo que write/1, y el predicado nl/0 que escribe un salto de línea en la salida standard.

. Ejemplo

Este es un programa que lee números de la entrada standard (separados por punto) hasta que se encuentra algún término que no sea un número. Entonces suma todos los números y escribe el resultado por la salida standard.

 sumar_lista([],Parcial,Parcial). 
 
 sumar_lista([Num|Resto],Parcial,Result) :- 
   NParcial is Num+Parcial, 
   sumar_lista(Resto,NParcial,Result). 
 
 leer_numero(Num) :- 
   read(Num), 
   number(Num). 
 
 suma :- 
   suma_aux([]). 
 
 suma_aux(Lista) :- 
   leer_numero(Num), 
   suma_aux([Num|Lista]). 
 
 suma_aux(Lista) :- 
   sumar_lista(Lista,0,Result), 
   nl, 
   display('LA SUMA ES : '), 
   display(Result), 
   nl.
 

. Entrada/Salida explícita

A diferencia de la entrada/salida standard, estos predicados podrían no estar predefinidos, en tal caso deben ser importados previamente. La biblioteca a importar puede variar de un entorno de desarrollo a otro, por lo que debe consultar la documentación correspondiente. El modo de importar bibliotecas también varía de un sistema a otro.

.  El predicado read_term/3

Modo de uso: read_term(+Stream,-Termino,+Opciones).

Este predicado sirve para leer términos del stream indicado. Su peculiaridad radica en que podemos indicar algunas opciones sobre como leer el término. El argumento Opciones consiste en una lista (posiblemente vacía) de términos que pueden ser cualquiera de los siguientes:

  • variables(-ListaVariables). Unifica ListaVariables con la lista de variables libres que aparecen en el término leido.
  • variable_names(-ListaNombres). Unifica ListaNombres con una lista de terminos cero-arios que representan los nombres de las variables libres que aparecen en el término leido.
  • Otras opciones dependen del entorno de desarrollo usado. Consulte la documentación asociada.

Recuerde que, cuando ocurre el evento de fin de fichero, este predicado retorna el término end_of_file/0.

. Ejemplo

  ?-  current_input(I),read_term(I,Term,[variables(L1),variable_names(L2)]).  
  |:  t(A,b(C,A)). 
  
  I = user_input, 
  L1 = [_A,_B], 
  L2 = ['A'=_A,'C'=_B], 
  Term = t(_A,b(_B,_A)) ? 
  yes 
  ?- 
  

. El predicado write_term/3

Modo de uso: write_term(+Stream,+Termino,+Opciones).

Este predicado es similar al anterior puesto que nos permite escribir un término en un stream controlando una serie de opciones. El argumento Opciones debe ser instanciado a una lísta (posiblemente vacía) de términos que se encontrarán entre alguno de los siguientes:

  • quoted(true). Aquellos functores que contengan "caracteres raros" (no alfanuméricos) serán escritos entre comillas simples. Esta opción es muy importante si los términos van a ser leidos posteriormente con read_term/3 o similar.
  • ignore_ops(true). Normalmente, aquellos functores que esten declarados como operadores se escriben de manera infija o postfija según corresponda. Con esta opción obligamos a que siempre se escriban de manera prefija. Por ejemplo, a+b se escribiría forzosamente como +(a,b).
  • Otras opciones dependen del entorno de desarrollo usado. Consulte la documentación asociada.

. Ejemplo

  ?- current_output(O),write_term(O,'1 y 2'+Z,[quoted(true),ignore_ops(true)]).
  
  +('1 y 2',_347) 
  O = user_output ? 
  yes 
  ?- 
  

. Ficheros

Para manipular ficheros solamente necesitamos abrirlos y/o cerrarlos. Cuando abrimos un fichero obtenemos un stream que podemos manejar mediante los predicados anteriormente descritos.

. Apertura de ficheros

Se hace mediante el predicado open/3, con el modo de uso open(+Fichero,+Modo,-Stream). Fichero es un término cero-ario con la ruta del fichero (normalmente entre comillas simples). Modo puede ser uno de estos términos:

  • read/0. Abrir en modo de solamente lectura.
  • write/0. Abrir en modo de solamente escritura. Si el fichero contiene datos, se truncan.
  • append/0. Abrir en modo de solamente escritura. El fichero no se trunca, los nuevos datos se añaden al final.

. Cierre de ficheros

Para ello existe el predicado close/1, cuyo modo de uso es close(+Stream). El stream queda invalidado una vez que se cierra el fichero. Este predicado vuelca a disco los contenidos del buffer antes de cerrarlo. Si deseamos hacer esto sin cerrar el fichero, disponemos del predicado flush_output/1.

. Culturilla

  • Cuando read/1 intenta leer un término pero se encuentra con un error sintáctico (el término está mal construido), emite un mensaje de error y el predicado falla. Afortunadamente, hay medios para cambiar este comportamiento, que veremos más adelante.
  • Nada impide que read/1 lea un término que contenga variables libres. Tenga en cuenta que dichas variables serán siempre distintas a las variables del programa en ejecución y de las variables leídas en llamadas anteriores a read/1, independientemente del nombre que se les ponga a dichas variables. Naturalmente, si una variable aparece dos veces en el mismo término leido, en efecto se tratará de la misma variable.
  • Cuando la entrada standard es el teclado e intentamos leer de él, Prolog muestra un símbolo de "prompt" para indicarnos que está preparado para que tecleemos. Dicho símbolo tiene este curioso aspecto: ¦

© Copyright 2000-2001

Angel Fernández Pineda.

 
Patrocinados
 

Copyright © 1999-2006 Programación en castellano. Todos los derechos reservados.
Formulario de Contacto - Datos legales - Publicidad

Hospedaje web y servidores dedicados linux por Ferca Network