diff --git a/guides/Getting-Started.md b/guides/Getting-Started.md index 5193542a..7fa7985f 100644 --- a/guides/Getting-Started.md +++ b/guides/Getting-Started.md @@ -6,13 +6,17 @@ We'll start with the installation of the compiler and Spago build tool, and then #### Installing the Compiler -You'll need [Node.js and npm](https://docs.npmjs.com/getting-started/installing-node) and to be [able to install global packages](https://docs.npmjs.com/getting-started/fixing-npm-permissions#option-1-change-the-permission-to-npm-s-default-directory) to proceed. +You'll need to install [Node.js and npm](https://docs.npmjs.com/getting-started/installing-node). We recommend installing [Node.js and npm via a node version manager](https://docs.npmjs.com/getting-started/installing-node) to avoid issues with installing packages globally. If you choose to install it manually, you might experience the [`EACCES` error when installing packages globally](https://docs.npmjs.com/getting-started/fixing-npm-permissions#option-1-change-the-permission-to-npm-s-default-directory). -The Purescript compiler (`purs`) can be installed with npm: +Install the Purescript compiler (`purs`) with npm: npm install -g purescript -(It can also be installed from [Hackage](http://hackage.haskell.org/package/purescript), or by downloading the latest [binary bundle](https://github.com/purescript/purescript/releases) for your OS. If you do so, make sure the `purs` executable is on your `$PATH`.) +Try running the PureScript compiler on the command line to verify that the PureScript compiler executables are available on your `$PATH`: + + purs + +It can also be installed from [Hackage](http://hackage.haskell.org/package/purescript), or by downloading the latest [binary bundle](https://github.com/purescript/purescript/releases) for your OS. If you do so, make sure the `purs` executable is on your `$PATH`. #### Setting up the Development Environment @@ -24,6 +28,8 @@ If you don't have Spago installed, install it now: Create a new project in an empty directory using `spago init`: + mkdir my-project + cd my-project spago init Your directory should now contain the following files: @@ -50,10 +56,12 @@ If everything was built successfully, and the tests ran without problems, then t #### Installing Dependencies -Dependencies can be installed using Spago. We will be using the `purescript-lists` library shortly, so install it now: +Dependencies can be installed using Spago. We will be using the `lists` library shortly, so install it now: spago install lists +The `lists` library sources should now be available in the `.spago/lists/{version}/` subdirectory, and will be included when you compile your project. + #### Working in PSCI PSCi is the interactive mode of PureScript. It is useful for working with pure computations, and for testing ideas. @@ -172,6 +180,11 @@ multiples = filter (\n -> mod n 3 == 0 || mod n 5 == 0) ns answer = sum multiples ``` +This sample illustrates a few key ideas regarding modules: + +- Every file begins with a module header. A module name consists of one or more capitalized words separated by dots. In this case, only a single word is used, but `My.First.Module` would be an equally valid module name. +- Modules are imported using their full names, including dots to separate the parts of the module name. Here, we import the `Prelude` module, which provides `mod`, `==`, and many other common functions. We also import `Data.List` which provides the explicitly-listed `range` and `filter` functions. We can either import all functions in a module implicitly, as is done with `Prelude`, or list them explicitly. Guidelines are to only have one module with implicit imports. + It is possible to load this file directly into the REPL and to continue working: spago repl @@ -191,7 +204,7 @@ The compiler will display several warnings about missing type declarations. In g #### Writing a Test Suite -To test our code, we'll use the `purescript-assert` library: +To test our code, we'll use the `assert` library: spago install assert @@ -231,10 +244,84 @@ main = do The `spago run` command can be used to compile and run the `Main` module: - > spago run + $ spago run [info] Build succeeded. The answer is 233168 + +#### Compiling for the Browser + +Spago can be used to turn our PureScript code into JavaScript suitable for use in the web browser by using the `spago bundle-app` command: + + $ spago bundle-app + ... + Build succeeded. + Bundle succeeded and output file to index.js + +All the code in the `src` directory and any project dependencies have been compiled to JavaScript. The resulting code is bundled as `index.js` and has also had any unused code removed, a process known as dead code elimination. This `index.js` file can now be included in an HTML document. If you try this, you should see the words "Hello, World!" printed to your browser's console. + +If you open `index.js`, you should see a few compiled modules which look like this: + +```javascript +// Generated by purs bundle 0.13.6 +var PS = {}; + +// ... + +(function($PS) { + "use strict"; + $PS["Euler"] = $PS["Euler"] || {}; + var exports = $PS["Euler"]; + var Data_EuclideanRing = $PS["Data.EuclideanRing"]; + var Data_Foldable = $PS["Data.Foldable"]; + var Data_List = $PS["Data.List"]; + var Data_List_Types = $PS["Data.List.Types"]; + var Data_Semiring = $PS["Data.Semiring"]; + var ns = Data_List.range(0)(999); + var multiples = Data_List.filter(function (n) { + return Data_EuclideanRing.mod(Data_EuclideanRing.euclideanRingInt)(n)(3) === 0 || Data_EuclideanRing.mod(Data_EuclideanRing.euclideanRingInt)(n)(5) === 0; + })(ns); + var answer = Data_Foldable.sum(Data_List_Types.foldableList)(Data_Semiring.semiringInt)(multiples); + exports["answer"] = answer; +})(PS); + +(function($PS) { + // Generated by purs version 0.13.6 + "use strict"; + $PS["Main"] = $PS["Main"] || {}; + var exports = $PS["Main"]; + var Data_Show = $PS["Data.Show"]; + var Effect_Console = $PS["Effect.Console"]; + var Euler = $PS["Euler"]; + var main = Effect_Console.log("The answer is " + Data_Show.show(Data_Show.showInt)(Euler.answer)); + exports["main"] = main; +})(PS); + +PS["Main"].main(); +``` + +This illustrates a few points about the way the PureScript compiler generates JavaScript code: + +- Every module gets turned into an object, created by a wrapper function, which contains the module's exported members. +- PureScript tries to preserve the names of variables wherever possible. +- Function applications in PureScript get turned into function applications in JavaScript. +- The main method is run after all modules have been defined and is generated as a simple method call with no arguments. +- PureScript code does not rely on any runtime libraries. All of the code that is generated by the compiler originated in a PureScript module somewhere which your code depended on. + +These points are important since they mean that PureScript generates simple, understandable code. The code generation process, in general, is quite a shallow transformation. It takes relatively little understanding of the language to predict what JavaScript code will be generated for a particular input. + +#### Compiling CommonJS Modules + +Spago can also be used to generate CommonJS modules from PureScript code. This can be useful when using NodeJS, or just when developing a larger project which uses CommonJS modules to break code into smaller components. + +To build CommonJS modules, use the `spago build` command: + + $ spago build + ... + Build succeeded. + +The generated modules will be placed in the `output` directory by default. Each PureScript module will be compiled to its own CommonJS module, in its own subdirectory. + #### What Next? If you're new to typed functional programming, your next stop should be [PureScript by Example](https://book.purescript.org/), which will walk you through learning PureScript by solving practical problems.