Empezando
Objetivos del capítulo
En este capítulo, el objetivo será preparar un entorno de desarrollo para PureScript y escribir nuestro primer programa en PureScript.
Nuestro primer proyecto será una biblioteca PureScript muy simple, que proporcionará una única función para calcular la longitud de la diagonal de un triángulo rectángulo.
Introducción
Estas son las herramientas que vamos a usar para preparar nuestro entorno de desarrollo para PureScript:
-
purs- El propio compilador de PureScript. -
npm- El gestor de paquetes de Node, que nos ayudará a instalar el resto de herramientas de desarrollo. - Pulp - Una herramienta de línea de comandos que automatiza muchas de las tareas asociadas a la gestión de proyectos PureScript.
El resto del capítulo te guiará en la instalación y configuración de estas herramientas.
Instalando PureScript
La manera recomendada de instalar el compilador de PureScript es descargar una distribución binaria para tu plataforma en el sitio web de PureScript.
Debes verificar que los ejecutables del compilador de PureScript están disponibles en tu ruta de ejecutables. Intenta ejecutar el compilador de PureScript en la línea de comandos para comprobarlo:
1 $ purs
Otras opciones para instalar el compilador de PureScript:
- Mediante NPM:
npm install -g purescript. - Construir el compilador a partir del código fuente. Las instrucciones están disponibles en el sitio web de PureScript.
Instalando las herramientas
Si no tienes una instalación funcional de NodeJS, debes instalarlo. Esto instalará también el gestor de paquetes npm en tu sistema. Asegúrate de que tienes npm instalado y disponible en tu ruta de ejecutables.
También necesitarás instalar la herramienta de línea de comandos Pulp y el gestor de paquetes Bower usando npm como sigue:
1 $ npm install -g pulp bower
Esto dejará las herramientas de línea de comandos pulp y bower en tu ruta de ejecutables. En este punto tienes todas las herramientas necesarias para crear tu primer proyecto PureScript.
¡Hola, PureScript!
Empecemos simple. Usaremos Pulp para compilar y ejecutar un simple programa “Hello World!”.
Comienza creando un proyecto en un directorio vacío usando el comando pulp init:
1 $ mkdir my-project
2 $ cd my-project
3 $ pulp init
4
5 * Generating project skeleton in ~/my-project
6
7 $ ls
8
9 bower.json src test
Pulp ha creado por nosotros dos directorios, src y test, y un fichero de configuración bower.json. El directorio src contendrá nuestros ficheros fuente y el directorio test nuestras pruebas. Usaremos el directorio test más adelante.
Modifica el fichero src/Main.purs para que contenga lo siguiente:
1 module Main where
2
3 import Control.Monad.Eff.Console
4
5 main = log "Hello, World!"
Este pequeño ejemplo ilustra unas cuantas ideas clave:
- Todos los ficheros comienzan con una cabecera de módulo. Un nombre de módulo consiste en una o más palabras comenzando por mayúsculas y separadas por puntos. En este caso hemos usado una única palabra, pero
Mi.Primer.Moduloseria un nombre de módulo igualmente válido. - Los módulos se importan usando su nombre completo, incluyendo los puntos que separan las partes del nombre de módulo. Aquí, importamos el módulo
Control.Monad.Eff.Consoleque proporciona la funciónlog. - El programa
mainestá definido como una aplicación de función. En PureScript, la aplicación de función se indica con espacio en blanco separando el nombre de la función de sus argumentos.
Ejecutemos este código usando el siguiente comando:
1 $ pulp run
2
3 * Building project in ~/my-project
4 * Build successful.
5 Hello, World!
¡Enhorabuena! Acabas de compilar y ejecutar tu primer programa PureScript.
Compilando para el navegador
Pulp puede usarse para convertir nuestro código PureScript en JavaScript susceptible de ser usado un un navegador web mediante el uso del comando pulp browserify:
1 $ pulp browserify
2
3 * Browserifying project in ~/my-project
4 * Building project in ~/my-project
5 * Build successful.
6 * Browserifying...
A continuación de esto, debes ver un montón de código JavaScript impreso en la consola. Esto es la salida de la herramienta Browserify aplicada a una biblioteca estándar de PureScript llamada Prelude, así como el código del directorio src. Este código JavaScript puede redirigirse a un fichero e incluirse en un documento HTML. Si lo intentas, debes ver las palabras “Hello, World!” impresas en la consola de tu navegador.
Quitando código no usado
Pulp proporciona un comando alternativo, pulp build, que puede usarse con la opción -O para aplicar la fase de eliminación de código muerto responsable de quitar JavaScript innecesario de la salida. El resultado es mucho más pequeño:
1 $ pulp build -O --to output.js
2
3 * Building project in ~/my-project
4 * Build successful.
5 * Bundling Javascript...
6 * Bundled.
De nuevo, el código generado se puede usar en un documento HTML. Si abres output.js, debes ver unos cuantos módulos compilados con esta pinta:
1 (function(exports) {
2 "use strict";
3
4 var Control_Monad_Eff_Console = PS["Control.Monad.Eff.Console"];
5
6 var main = Control_Monad_Eff_Console.log("Hello, World!");
7 exports["main"] = main;
8 })(PS["Main"] = PS["Main"] || {});
Esto ilustra unos cuantos puntos sobre el modo en que el compilador de PureScript genera el código JavaScript:
- Todo módulo se convierte en un objeto, creado por una función envoltorio, que contiene los miembros exportados por el módulo.
- PureScript intenta preservar los nombres de las variables cuando sea posible.
- La aplicación de funciones en PureScript se convierte en aplicación de funciones de JavaScript.
- El método principal se ejecuta después de que todos los módulos hayan sido definidos, y es generado como una simple llamada a método sin argumentos.
- El código PureScript no depende de ninguna biblioteca de tiempo de ejecución (runtime library). Todo el código que genera el compilador tiene su origen en un módulo PureScript del que tu código depende.
Estos puntos son importantes, ya que significan que PureScript genera código simple e inteligible. De hecho, el proceso de generación de código es una transformación bastante superficial. No es necesario un conocimiento avanzado del lenguaje para predecir qué código JavaScript será generado para cierto código de entrada.
Compilando módulos CommonJS
Pulp también puede usarse para generar módulos CommonJS a partir de código PureScript. Esto puede ser útil cuando usemos NodeJS o cuando estemos desarrollando un proyecto grande que usa módulos CommonJS para partir el código en componentes más pequeñas.
Para construir módulos CommonJS, usa el comando pulp build (sin la opción -O):
1 $ pulp build
2
3 * Building project in ~/my-project
4 * Build successful.
Los módulos generados serán colocados en el directorio output por defecto. Cada módulo PureScript se compilará a su propio módulo CommonJS en su propio subdirectorio.
Seguimiento de dependencias con Bower
Para escribir la función diagonal (el objetivo de este capítulo), necesitaremos poder calcular raíces cuadradas. El paquete purescript-math contiene definiciones de tipos para las funciones definidas en el objeto JavaScript Math, así que instalémoslo:
1 $ bower install purescript-math --save
La opción --save hace que la dependencia se añada al fichero de configuración bower.json.
Los fuentes de la biblioteca purescript-math deben estar ahora disponibles en el subdirectorio bower_components y serán incluidos cuando compiles tu proyecto.
Calculando diagonales
Escribamos la función diagonal, que será un ejemplo de uso de una función de una biblioteca externa.
Primero importa el módulo Math añadiendo la siguiente línea al principio del fichero src/Main.purs:
1 import Math (sqrt)
También es necesario importar el módulo Prelude que define operaciones muy básicas como la suma y multiplicación de números:
1 import Prelude
Ahora define la función diagonal como sigue:
1 diagonal w h = sqrt (w * w + h * h)
Date cuenta de que no es necesario definir un tipo para nuestra función. El compilador es capaz de inferir que diagonal es una función que toma dos números y devuelve un número. Sin embargo, en general es una buena práctica proporcionar anotaciones de tipo como una forma de documentación.
Modifiquemos la función main para que use la nueva función diagonal:
1 main = logShow (diagonal 3.0 4.0)
Ahora compila y ejecuta el proyecto de nuevo usando pulp run:
1 $ pulp run
2
3 * Building project in ~/my-project
4 * Build successful.
5 5.0
Probando el código usando el modo interactivo
El compilador PureScript viene con un REPL (Read Eval Print Loop) interactivo llamado PSCi. Puede ser muy util para probar tu código y experimentar con nuevas ideas. Usemos PSCi para probar la función diagonal.
Pulp puede cargar módulos fuente en PSCi automáticamente mediante el comando pulp repl.
1 $ pulp repl
2 >
Puedes escribir :? para ver una lista de comandos:
1 > :?
2 The following commands are available:
3
4 :? Show this help menu
5 :quit Quit PSCi
6 :reset Reset
7 :browse <module> Browse <module>
8 :type <expr> Show the type of <expr>
9 :kind <type> Show the kind of <type>
10 :show import Show imported modules
11 :show loaded Show loaded modules
12 :paste paste Enter multiple lines, terminated by ^D
Pulsando la tecla Tab puedes ver una lista de todas las funciones disponibles en tu propio código, así como las disponibles en las dependencias Bower y el módulo Prelude.
Empieza importando el módulo Prelude:
1 > import Prelude
Intenta evaluar unas cuantas expresiones ahora:
1 > 1 + 2
2 3
3
4 > "Hello, " <> "World!"
5 "Hello, World!"
Probemos ahora nuestra nueva función diagonal en PSCi:
1 > import Main
2 > diagonal 5.0 12.0
3
4 13.0
También puedes usar PSCi para definir funciones:
1 > double x = x * 2
2
3 > double 10
4 20
No te preocupes si la sintaxis de estos ejemplos no te resulta muy clara. Tendrá más sentido según vayas leyendo el libro.
Finalmente, puedes comprobar el tipo de una expresión usando el comando :type:
1 > :type true
2 Boolean
3
4 > :type [1, 2, 3]
5 Array Int
Prueba el modo interactivo ahora. Si te atascas en algún punto, usa el comando de Reset :reset para descargar cualquier módulo que pueda estar compilado en memoria.
Conclusión
En este capítulo hemos preparado un proyecto simple en PureScript usando la herramienta Pulp.
También hemos escrito nuestra primera función en PureScript y un programa JavaScript que puede ser ejecutado tanto en el navegador como en NodeJS.
Usaremos este entorno en los siguientes capítulos para compilar, depurar y probar nuestro código, así que debes asegurarte de que estás cómodo con las herramientas y técnicas involucradas.