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 lfetool /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 slurp
ing them in:
> (slurp "./examples/internal-state.lfe")
#(ok internal-state)
> (set account (new-account "Alice" 100.00 0.06))
#Fun<lfe_eval.10.6046715>
> (send account 'name)
"Alice"
> (send account 'balance)
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:
Go to Sublime Text 2 -> Preferences -> Package Control
Type "Package Control: Install Package"
Wait for the text entry box to display (available packages are loading)
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:
Create the
test/unit
directories in your project, if they don't already exist.In
test/unit
, create aunit-<module-name>-tests.lfe
file.Ensure that your module name matches in the file:
(defmodule unit-<module-name>-tests
...)
- 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")
...)
- 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)))
- 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.