Scheme

Scheme
Información sobre la plantilla
Parte de la familia Lenguaje de Programación
Scheme.jpg
lenguaje interpretado
Creadorlaboratorios del MIT
DesarrolladorGuy L. Steele y Gerald Jay Sussman
Lanzamiento inicial1975

Scheme es un dialecto de Lisp, es un lenguaje interpretado, muy expresivo y soporta varios paradigmas. Fue desarrollado por Guy L. Steele y Gerald Jay Sussman en la década de los setenta e introducido en el mundo académico a través de una serie de artículos conocidos como los Lambda Papers de Sussman y Steele.

Historia

Scheme es un lenguaje de programación que surgió en los laboratorios del MIT en 1975, cuando Guy L. Steele y Gerarld J. Sussman buscaban un lenguaje con una semántica muy clara y sencilla. Pensaban que los lenguajes no se deberían desarrollar añadiendo muchas características, sino quitando las debilidades y las limitaciones que hacen que las características adicionales parezcan necesarias.

Estuvo influenciado por el cálculo lambda. El desarrollo de Scheme ha sido lento, ya que la gente que lo estandarizó es muy conservadora en cuanto a añadirle nuevas características porque la calidad ha sido siempre más importante que la utilidad empresarial. Por eso Scheme es considerado como uno de los lenguajes mejor diseñados de propósito general.

Características

La filosofía de Scheme es minimalista. Su objetivo no es acumular un gran número de funcionalidades, sino evitar las debilidades y restricciones que hacen necesaria su adicción. Así, Scheme proporciona el mínimo número posible de nociones primitivas, construyendo todo lo demás a partir de un reducido número de abstracciones. Por ejemplo, el mecanismo principal para el control de flujo son las llamadas recursivas finales.

Scheme fue el primer dialecto de Lisp que usó ámbito estático o léxico en lugar de dinámico de forma exclusiva. También fue uno de los primeros lenguajes de programación con continuaciones explícitas. Scheme ofrece también gestión automática de memoria (recolección de basura).

Las listas son la estructura de datos básica del lenguaje, que también ofrece arrays entre sus tipos predefinidos. Debido a su especificación minimalista, no hay sintaxis explícita para crear registros o estructuras, o para programación orientada a objetos, pero muchas implementaciones ofrecen dichas funcionalidades. Scheme se llamaba originalmente "Schemer", siguiendo la tradición de los lenguajes Planner y Conniver. Su nombre actual es debido a que sus autores usaban el sistema operativo ITS, que limitaba la longitud de los nombres de fichero a 6 caracteres.

Ventajas de Scheme

Scheme, como todos los dialectos de Lisp, tiene una sintaxis muy reducida, comparado con muchos otros lenguajes. No necesita reglas de precedencia, ya que, en esencia, carece de operadores: usa notación prefija para todas las llamadas a función. Las macros de Scheme permiten adaptarlo a cualquier dominio. Pueden ser usadas, por ejemplo, para añadir soporte a la programación orientada a objetos. Scheme proporciona un sistema de macros higiénico que, aunque no tan potente como el de Common Lisp, es mucho más seguro y, con frecuencia, sencillo de utilizar. La ventaja de un sistema de macros de este tipo (que también se encuentra en otros lenguajes, como Dylan) es que evita automáticamente colisiones entre los nombres usados en la definición de la macro y en el contexto en que ésta se expande. En contrapartida, las macros higiénicas no pueden introducir nuevos símbolos.

Scheme facilita la programación funcional. La programación funcional pura no precisa de variables globales ni sufre de efectos secundarios, y es, por tanto, automáticamente segura en presencia de procesos concurrentes (thread-safe), forma esta de facilitar considerablemente la verificación de programas, al menos en comparación con el estilo imperativo.

En Scheme, los procedimientos son objetos de primera clase. Ello permite la definición de funciones de orden superior, que facilitan un mayor grado de abstracción en los programas. También es posible la creación de procedimientos anónimos.

El estándar de Scheme es también minimalista. Ello conlleva ventajas e inconvenientes. Por ejemplo, escribir un compilador o intérprete de Scheme que sea fiel al estándar es más fácil que implementar uno de Common Lisp; empotrar Lisp en dispositivos con poca memoria será también más factible si usamos Scheme en lugar de Common Lisp. A los aficionados a Scheme les divierte mucho señalar que su estándar, con sólo 50 páginas, ¡es más corto que el índice del libro de Guy Steele Common Lisp: The Language!

Desventajas de Scheme

El estándar de Scheme es realmente minimalista y específico en sí. Ello provoca que existan multitud de implementaciones diferentes, cada una de las cuales introduce extensiones y bibliotecas propias que las hace incompatibles entre sí. Los Scheme Requests for Implementation (SRFI) tratan de poner remedio a este problema.

Hay quien ve el hecho de que los procedimientos y variables compartan el mismo espacio de nombres como una desventaja, ya que algunas funciones tienen nombres que son de uso común para variables. Por ejemplo, list es el nombre de un procedimiento, así que es muy habitual ver lst o xs como nombres de variables, en lugar de "list".

Como hemos dicho, el espacio de nombres es único (Scheme es un LISP-1) y, por tanto, también incluye a las macros. Ello hace imposible distinguir el uso de una macro del de una función, así que, si no consultamos la definición de cada uno de los objetos usados, no será en general posible determinar el orden de evaluación en programas con los que no estemos familiarizados.

Sintaxis

Scheme posee una sintaxis reducida comparada a otros lenguajes. Utiliza la notación prefija. Por ejemplo, si se desea realizar la suma 1+1, se debe programar la siguiente instrucción

(+ 1 1) 

Los paréntesis son obligatorios, ya que separan las instrucciones que serán evaluadas por el intérprete. Para realizar comentarios dentro del código, se utiliza el ";", así se marca que toda la línea será de comentario Ejemplo:

;Esta línea es un comentario, y la orden de abajo es ejecutada 
(+ 1 1)

Sintaxis Básica

Expresión -> átomo | lista
átomo -> número | string | identificador | carácter | boolean
lista -> '(' secuencia-expresión ')'
secuencia-expresión -> expresión secuencia - expresión | expresión
función -> ( nombre_función argumento1 argumento 2... argumento n)

Variables locales y globales

Las variables son dinámicamente tipadas. Dicho de otra forma, no se debe especificar lo que se va a guardar dentro de la misma. Las variables globales se nombran con la instrucción (define nombre valor) Por ejemplo,

 (define variable 5) 

Por otro lado, las variables locales se definen con la instrucción ( let variables función). Por ejemplo: sumar dos números guardados en una variable local

 (let 
 ;variables de la operación 
 ((numero1 5) 
 (numero2 7)) 
 ;instrucción que suma los números, es decir, la función 
 (+ numero1 numer2))

Creando Procedimientos Completos

Utilizando la instrucción (define (nombre args) función) se crea un procedimiento dentro del programa. En mi caso, voy a implementar la instrucción del ejemplo anterior en una función

; función que suma dos números agregados como argumento 
(define (suma num1 num2) 
; implementación del let anterior, aunque no es estrictamente necesario 
(let 
;variables de la operación 
((numero1 num1) 
(numero2 num2)) 
; instrucción que suma los números, es decir, la función 
(+ numero1 numero2)) 

De la misma manera, el procedimiento anterior pudo ser escrito de esta manera:

;segunda implementación de suma de dos números, esta vez, sin el let 
(define (suma num1 num2) 
(+ num1 num2)) 

para llamar a la función creada, se utiliza la orden (función args). Así, para llamar a nuestra función de suma, se escribe:

(suma 2 3) 

Se llama con dos números, debido a que con esa cantidad de argumentos se estableció la función.

Estructuras de control

En Scheme existe la instrucción cond, con la cual se pueden revisar si se cumplen o no con requerimientos para realizar dicha funcion. Su sintaxis es:

(cond 
((condición) (función-salida) 
.... 
.... 
.... 
(else (función-salida)) 

En este caso, el else es opcional

Por ejemplo, si se desea sumar solamente numeros positivos en nuestra funcion de suma, se podría realizar la siguiente implementación

; Función de suma, esta vez, aceptara solamente numeros positivos 
(define suma num1 num2) 
;;manejo de las condiciones 
(cond 
((and (> num1 0) (>num2 0)) (+ num1 num2)) 
(else 
"error al recibir parámetros" )))

Manejo de valores booleanos

En Scheme se utiliza el #t como verdadero y el #f como falso. Técnicamente, cualquier símbolo que no sea #f será tomado por el interprete como #t. Para poder operarlos, existen las instrucciones AND, OR, NOT, de funcionamiento idéntico a los demás lenguajes de programación. En el caso de AND, devolverá #t si y solo si ambos argumentos son verdaderos

 (and #t #t) 
 OR devolverá #t si uno o ambos argumentos son verdaderos 
 (or #t #f) 
 NOT devolverá el complemento a su argumento 
 (not #t)

Referencias