1 Introduction

1.7 Setting up a Development Environment

The last thing we need to do before you're off and running is to discuss a good standard process for setting up a development environment. There are several key aspects to this:

  • Intent
    • exploring LFE and LFE examples
    • creating an LFE library
    • creating an LFE service/daemon/application
    • hacking on LFE itself
  • Tools
    • kerl
    • rebar
    • testing
    • IDEs

This section takes a pragmatic approach of getting started as quickly as possible, so we will not cover these in great detail. However, we will provide useful links and additional references so that you can explore at your own leisure.

1.7.1 Starting from Scratch

In the LFE Quick Start, you saw how to get up and running, and we're going to repeat some of that here. However, we do this for the sake of completeness and having all the information in one easy-to-access reference.

1.7.2 lfetool

lfetool is a powerful little utility that eases the tasks of the LFE developer. It can do everything from install software to run tests and start up REPLs.

Since using lfetool makes pretty much everything easier, we'll rely on it heavily for the development tasks described in the LFE documentation. Let's get it set up.

Here's how to download and install it:

$ curl -L -o ./lfetool https://raw.github.com/lfe/lfetool/master/lfetool
$ bash lfetool install /usr/local/bin

If you already have lfetool installed, but it's been a while, you should probably update it:

$ lfetool update

Development on lfetool is on-going, with new features landing on a fairly regular basis. It's probably a good idea to update rather freqently, to take advantage of the latest improvements. Also note that all versions are tagged; should you ever want to revert to an earlier release, it is rivial to do so.

1.7.3 Dependencies

kerl

First and foremost, you're going to need Erlang. In the course of your experiments with LFE, you may want to try out different versions of Erlang, so we'll start off right: using kerl. If you don't have Erlang install or you want to be able to run multiple versions of Erlang, instlal kerl:

$ lfetool install kerl

This will download and save it to /usr/local/bin.

rebar

Next up is rebar. No matter what your intent with LFE, you're going to need rebar sooner or later. We don't rely on it exlusively (e.g., we have our own test runner), but we do use it for maintaining and compiling dependencies.

$ lfetool install rebar

1.7.4 How to Use LFE

There are many ways in which you may download and use LFE:

  • As a project dependency
  • Via a direct git clone working directory
  • A "system-wide" install (where system here is defined as your currently active version of Erlang)

More often than not, you won't be downloading and directly interacting with LFE code. Rather, you'll be including LFE in your project dependencies (the rebar.config file).

1.7.4.1 Project Install

To create a new LFE project, with your rebar.config set up to download LFE, simply do the following:

$ lfetool new library my-lib
$ cd my-lib
$ make compile

Or, if you want to build an OTP app:

$ lfetool new service my-svc
$ cd my-svc
$ make compile

1.7.4.2 Getting and Building LFE

You can, of course, just do it the old fashioned way:

$ git clone git://github.com/rvirding/lfe.git
$ cd ./lfe
$ rebar compile

1.7.4.3 Installing LFE

We don't actually recommend installing LFE system-wide. The only time it's really necessary is when you want to run lfescript scripts from anywhere on your box.

In such a case, here's what you do:

$ lfetool install lfe

1.7.5 A Test Drive with the REPL

With LFE built, you're ready to play :-) If you've created an LFE project with lfetool, you can use the make target provided for you:

$ make shell

This will compile all the deps; if you want to skip that, you can do:

$ make shell-no-deps

This will compile just your project code. If that's more hand-holding than you need and you don't want anything compiled for you before you leap into the REPL, you can just use lfetool directly:

$ lfetool repl lfe

Note that all of the above commands will look for and add dependency directories to ERL_LIBS and start Erlang/LFE with those defined.

If you're running from an LFE working directory, you can simply do this:

$ ./bin/lfe -pa ./ebin

Once you are in the REPL you can Lisp it up:

> (* 6 7)
42
> (cons 6 7)
(6 . 7)
> (cons (list 6 7) (list 40 2))
((6 7) 40 2)
> (* 2 (+ 1 2 3 4 5 6))
42
> (lists:foldl (lambda (n acc) (+ n acc)) 0 (lists:seq 1 6))
42
>

1.7.6 Running Some Examples

While in the REPL, you can run some examples by slurping them in:

> (slurp '"./examples/internal-state.lfe")
#(ok internal-state)
> (set account (new-account '"Alice" 100.00 0.06))
#Fun<lfe_eval.10.6046715>
> (name account)
"Alice"
> (balance account)
100.0
>

And another one:

> (slurp '"./examples/church.lfe")
#(ok church)
> (church->int1 (three))
3
>

To quit out of the REPL, hit ^g and then q<ENTER>.

1.7.7 An Example IDE: Sublime Text 2

First off: our definition of "IDE" is text editor + REPL + terminal. So there you have it.

As we are sure is obvious, you can use any text editor you want with LFE. If you're a Lisper, Emacs might be a natural choice. Vim, quite honestly, can work just as well.

For this example, though, we will be using Sublime Text 2 as the example editor. To use LFE effectively with Sublime, we recommend the following plugins:

  • Package Control

  • Bracket Highlighter

  • Lisp Indent

  • Trailing Spaces

  • LFE

  • Theme - Vim Blackboard (for those who like dark editors and a classic terminal syntax highlight look)

Instructions for installing Package Control are here.

After the restart, you're ready to go. For each package you want to install, do the following:

  1. Go to Sublime Text 2 -> Preferences -> Package Control

  2. Type "Package Control: Install Package"

  3. Wait for the text entry box to display (available packages are loading)

  4. Enter the name of the package you want to install and hit <ENTER>

After you have done that for each packge, you will need to restart. Many of the packages will then have their own entries under Sublime Text 2 -> Preferences -> Package Settings where you can copy the default settings and paste them into your own ("User") settings, modifying as you see fit.

To configure the dark theme, you'll want to visit see the project README.

The LFE plugin doesn't need any configuration. Once you restart Sublime, it should recognize your LFE files by the file extension.

For the Lispindent plugin you will need to add some configuration. Go to Sublime Text 2 -> Preferences -> Package Settings -> Lispindent and click on "Settings - User". In the new file that pops up, paste the following:

{
    "languages": {
        "LFE": {
            "detect": ".*\\.(lfe)$",
            "syntax": "LFE.tmLanguage",
            "default_indent": "function",
            "regex":
            ["(ns|fn|def[^\\s]*|bound-fn|if|if-not|case|condp|when|while|",
             "when-not|when-first|do|future|comment|doto|locking|proxy|",
             "with-open|with-precision|with-local-vars|reify|deftype|",
             "defrecord|defprotocol|extend|extend-protocol|extend-type|",
             "try|catch|finally|let|letfn|binding|loop|for|doseq|dotimes|",
             "when-let|if-let|defstruct|struct-map|assoc|defmethod|testing|",
             "deftest|use-fixtures|handler-case|handle|dotrace|deftrace|",
             "begin|case|delay|do|define|lambda|let|let\\*|letrec|",
             "let-values|let\\*-values|sequence|let-syntax|letrec-syntax|",
             "syntax-rules|syntax-case|call-with-input-file|",
             "with-input-from-file|with-input-from-port|",
             "call-with-output-file|with-output-to-file|",
             "with-output-to-port|call-with-values|dynamic-wind|catch|",
             "defvar|defclass|defconstant|defcustom|defparameter|defconst|",
             "define-condition|define-modify-macro|defsetf|defun|",
             "defgeneric|define-setf-method|define-self-expander|",
             "defmacro|defsubst|deftype|defmethod|defpackage|defstruct|",
             "dolist|dotimes|lambda|let|let\\*|prog1|prog2|unless|when)$"]
        }
    }
}

Your text editor is now ready to rock out some LFE!

1.7.8 A Quick Note on Writing Tests

We've covered getting LFE running, using the REPL, and operating your text editor in an LFE-friendly manner. The next of the essentils we need to look at is unit tests. This will be covered in much more detail in the TDD section of the Checks and Testing chapter.

For now, though, let's give you a quick overview... and some caveats. In fact, let's do the caveats first.

Ideally, LFE would use eunit, like it does with most other libraries. Unfortunately, there are some quirky edge cases in LFE's Erlang macro handling that prevent correct usage of eunit. As such, an interim solution was created. Once the macro issue in LFE is addressed for eunit (and progress is being made!), we will be able to abandon lfeunit (or make it a thin wrapper).

A quick and dirty intro to using lfeunit follows:

  1. Create the test/unit directories in your project, if they don't already exist.

  2. In test/unit, create a unit-<module-name>-tests.lfe file.

  3. Ensure that your module name matches in the file:

   (defmodule unit-<module-name>-tests
     ...)
  1. Update the import statement to include the unit test functions you need, as well as the required include, e.g.:
  ...
  (import
    (from lfeunit-util
      (check-failed-assert 2)
      (check-wrong-assert-exception 2))))

  (include-lib "include/lfeunit-macros.lfe")
  ...)
  1. Create test functions of the form (deftest <some-name>, with some asserts added, e.g.:
   (deftest my-function
     (is-true 42 (my-function 1 2 3)))
  1. Run the following to verify your tests (and to get nicely formatted, colored test runner output!):
   $ lfetool tests unit

Do this for every commit.

1.7.9 Toolchain

The primary tool used for LFE development is lfetool. It makes use of many other tools in the Erlang, Elixir, and LFE ecosystems, enabling everything from dependency management and compiling to running your unit tests and releasing your software.

Projects created with lfetool's new command also have a Makefile with various *.mk includes.