Utilizar guile como calculadora
Los que me conocen saben que llevo tiempo hablándoles de las
maravillas de algunas herramientas como bc
, una gran calculadora que
he utilizado durante años y que sigo utilizando, aunque cada vez
menos. bc
se está viendo desplazada en mi línea de comandos como
calculadora por guile
, pero ¿qué es guile
?
guile
¿Eso no es un lenguaje de programación?
Pues sí, guile es un scheme. Su nombre son las siglas de GNU's Ubiquitous Intelligent Language for Extensions. Que como indican es un lenguaje creado para proporcionar extensiones a otros programas y de hecho consiste, principalmente, en una librería pensada para ser ensamblada con cualquier otro programa y ser utilizada para escribir scripts que amplíen la funcionalidad del mismo.
Como he dicho antes, es un scheme, lenguaje derivado de LISP. Iba a decir del antiguo LISP pero es mejor puntualizar a eterno LISP.
Además, para mi propósito de hoy, guile viene con un intérprete y se puede lanzar desde línea de comandos y utilizarlo de forma interactiva.
Calculadora para la línea de comandos
Utilizo en mi ordenador como gestor de ventanas i3vm. Es un buen gestor, muy eficaz, pero para serlo se basa mucho en el uso del teclado minimizando el uso del ratón. Para utilizarlo procuro tener las aplicaciones que más utiliza a un golpe de teclas (o dos, si contamos con la tecla mod). Por ejemplo, una consola la abro pulsando mod+enter.
Por ello, me es mucho más sencillo cuando necesito una calculadora
pulsar mod+enter y teclear bc
que buscar la calculadora gráfica
que haya instalada y manejarla con el ratón. bc
además proporciona
una calculadora programable muy potente, incluso puedes definir
funciones para realizar cálculos complejos como si un lenguaje de
programación fuera. Pero ¿por qué estoy sustituyendo bc
con guile?
Lo mejor para explicarlo es ver un ejemplo:
> bc bc 1.07.1 Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006, 2008, 2012-2017 Free Software Foundation, Inc. This is free software with ABSOLUTELY NO WARRANTY. For details type `warranty'. (2/3)+(1/3) 0 scale=2 (2/3)+(1/3) .99 scale=5 (2/3)+(1/3) .99999 quit
El primer resultado de (2/3)+(1/3)
es totalmente inexacto. Se va
ajustando según modificamos el valor de la variable scale
que nos
dice qué cantidad de decimales debe calcular. Sin embargo, vemos que
son en realidad aproximaciones. Vamos al mismo ejemplo desde
guile:
GNU Guile 2.0.14 Copyright (C) 1995-2016 Free Software Foundation, Inc. Guile comes with ABSOLUTELY NO WARRANTY; for details type `,show w'. This program is free software, and you are welcome to redistribute it under certain conditions; type `,show c' for details. Enter `,help' for help. scheme@(guile-user)> (+ (/ 2 3) (/ 1 3)) $1 = 1
Si comparamos las dos formas de cálculo veremos que guile es más
preciso, todos sabemos que (2/3)+(1/3)
son (3/3)
o lo que es lo
mismo 1
. La primera respuesta de bc
es 0
algo inaceptable, pero
empieza a acercarse según el valor de la variable scale
que
determina cuántos decimales se calcularán.
Usando guile como calculadora
Muchas veces descarto temas sobre los que escribir porque me da la sensación de que son tan básicos que todo el mundo los conoce ya, o son tan sencillos que no merece la pena escribir sobre ellos. Luego veo esos mismos temas en otro blog y pienso que quizá podría haberlo escrito yo, porque no era tan básico o tan simple para la mayoría de la gente. Este es uno de esos casos en los que tengo casi descartado el borrador y he pensado al revés: a lo mejor no es tan básico y tan simple o a alguien le puede interesar.
Cualquier lenguaje interpretado se puede utilizar como calculadora. He utilizado también Python alguna vez para lo mismo, aunque generalmente he venido usando más bc como calculadora de consola.
Cálculos sencillos
La peculiaridad de guile, como cualquier otro scheme o descendiente de LISP utiliza una notación rara para la mayoría de los mortales y hay que acostumbrarse a ella. En este tipo de lenguajes todo es una lista y todo se presenta en una lista. El primer elemento de la lista es la función que evaluará el intérprete y los demás elementos son los datos que necesita la función para ser evaluada. Un ejemplo de cálculos sencillos con guile.
scheme@(guile-user)> (+ 2 3) $1 = 5 scheme@(guile-user)> (- 4 2) $2 = 2 scheme@(guile-user)> (- $1 $2) $3 = 3 scheme@(guile-user)> (+ $1 2) $4 = 7 scheme@(guile-user)> (+ 1 2 3 4) $5 = 10 scheme@(guile-user)> (- $5 $3 1 1) $6 = 5
Para realizar el cálculo de (2+3)
se utiliza una notación que
puede parecer extraña. En realidad es muy sencilla de entender, la
expresión (+ 2 3)
la podemos desglosar en sus componentes más
sencillos. Para empezar está la pareja de ()
. Esos signos nos
delimitan una lista. Como he dicho antes, el intérprete evaluará el
primer elemento de la lista, lo que quiere decir que el intérprete
espera que sea una expresión «ejecutable». En nuestro caso, hay una
función que se llama +
que lo que hace al ser evaluada es sumar la
lista de argumentos que se le pasen, en este caso 2 y 3.
Pero además, vemos que guile va guardando los resultados en
variables que marca con un carácter $
y esas variables se pueden
utilizar en los cálculos. Algo muy interesante cuando los cálculos son
complejos y los divides en partes o cuando quieres almacenar alguna
constante que emplearás en varios cálculos.
scheme@(guile-user)> (/ 21 3) $3 = 7 scheme@(guile-user)> (/ 21 3 7) $4 = 1 scheme@(guile-user)> (/ 21 3 7 2) $5 = 1/2
Otro de los puntos a tener en cuenta es que las divisiones no se efectúan para convertir a decimal sino que las operaciones con enteros que no den otro entero, se guardan como fracciones.
Este hecho es fundamental para mantener la exactitud en los cálculos,
no se emplean las aproximaciones decimales de las fracciones. Y por
eso vemos que el resultado de la serie de divisiones (/ 21 3 7 2)
se
realiza de la siguiente manera:
21 / 3 → 7 / 7 → 1 / 2 → 1/2
Cálculos no tan sencillos
Hay algunos otros cálculos que no son operaciones básicas sino cosas más complicadas. Por ejemplo, algunas operaciones especiales sobre la división, como calcular el cociente o el resto.
scheme@(guile-user)> (quotient 7 3) $1 = 2 scheme@(guile-user)> (modulo 7 3) $2 = 1 scheme@(guile-user)>
También hay funciones para cálculo de exponentes (exp
) o logaritmos
(log
), o para las funciones trigonométricas sin
, cos
, tan
,
asin
, acos
, atan
. Por ejemplo:
scheme@(guile-user)> (* 4 (atan 1)) $3 = 3.141592653589793 scheme@(guile-user)>