Curso intermedio de programación en Prolog

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.

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP
SIGUIENTE ARTÍCULO