From 3f5e4ce94a4ec4173755c81ce33e60e1389476c6 Mon Sep 17 00:00:00 2001 From: Gordon Guthrie Date: Wed, 5 Jan 2011 22:21:24 +0000 Subject: [PATCH] Refactoring tidy up --- _build/html/.buildinfo | 2 +- conf.py | 5 +- rsts/best-practice-1.rst | 48 ------ rsts/community.rst | 33 ---- rsts/emacs-and-the-dot-emacs-file.rst | 66 -------- rsts/getting-started.rst | 35 ---- rsts/learning-elisp.rst | 17 -- rsts/lesson-1-1.rst | 45 ------ rsts/lesson-2-1.rst | 94 ----------- rsts/lesson-2-2.rst | 221 -------------------------- rsts/lesson-2-3.rst | 93 ----------- rsts/lesson-2-4.rst | 171 -------------------- rsts/lesson-2-5.rst | 76 --------- rsts/lesson-3-1.rst | 135 ---------------- rsts/lesson-3-2.rst | 114 ------------- rsts/lesson-4-1.rst | 49 ------ rsts/lesson-4-2.rst | 132 --------------- rsts/lesson-4-3.rst | 147 ----------------- rsts/lesson-4-4.rst | 45 ------ rsts/lesson-5-1.rst | 102 ------------ rsts/lesson.template | 20 --- rsts/other-formats.rst | 11 -- rsts/references.rst | 18 --- rsts/ttd.rst | 21 --- rsts/what.rst | 21 --- rsts/who.rst | 29 ---- rsts/why.rst | 64 -------- 27 files changed, 3 insertions(+), 1811 deletions(-) delete mode 100644 rsts/best-practice-1.rst delete mode 100644 rsts/community.rst delete mode 100644 rsts/emacs-and-the-dot-emacs-file.rst delete mode 100644 rsts/getting-started.rst delete mode 100644 rsts/learning-elisp.rst delete mode 100644 rsts/lesson-1-1.rst delete mode 100644 rsts/lesson-2-1.rst delete mode 100644 rsts/lesson-2-2.rst delete mode 100644 rsts/lesson-2-3.rst delete mode 100644 rsts/lesson-2-4.rst delete mode 100644 rsts/lesson-2-5.rst delete mode 100644 rsts/lesson-3-1.rst delete mode 100644 rsts/lesson-3-2.rst delete mode 100644 rsts/lesson-4-1.rst delete mode 100644 rsts/lesson-4-2.rst delete mode 100644 rsts/lesson-4-3.rst delete mode 100644 rsts/lesson-4-4.rst delete mode 100644 rsts/lesson-5-1.rst delete mode 100644 rsts/lesson.template delete mode 100644 rsts/other-formats.rst delete mode 100644 rsts/references.rst delete mode 100644 rsts/ttd.rst delete mode 100644 rsts/what.rst delete mode 100644 rsts/who.rst delete mode 100644 rsts/why.rst diff --git a/_build/html/.buildinfo b/_build/html/.buildinfo index cc24262..f0c881b 100644 --- a/_build/html/.buildinfo +++ b/_build/html/.buildinfo @@ -1,4 +1,4 @@ # Sphinx build info version 1 # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. -config: 3eb2f7d468f63cadd7d6413ca5d093e1 +config: 524d1b55c662a7d873df5e2fe4c0afd5 tags: fbb0d17656682115ca4d033fb2f83ba1 diff --git a/conf.py b/conf.py index b9d0426..a2b349f 100644 --- a/conf.py +++ b/conf.py @@ -151,7 +151,7 @@ #html_use_smartypants = True # Custom sidebar templates, maps document names to template names. -#html_sidebars = {} +html_sidebars = {'index' : 'comments.html'} # Additional templates that should be rendered to pages, maps page names to # template names. @@ -167,7 +167,7 @@ #html_split_index = False # If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True +html_show_sourcelink = False # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the @@ -180,7 +180,6 @@ # Output file base name for HTML help builder. htmlhelp_basename = 'Learn-eLisp-For-Emacsdoc' - # -- Options for LaTeX output -------------------------------------------------- # The paper size ('letter' or 'a4'). diff --git a/rsts/best-practice-1.rst b/rsts/best-practice-1.rst deleted file mode 100644 index 7e75440..0000000 --- a/rsts/best-practice-1.rst +++ /dev/null @@ -1,48 +0,0 @@ -====================================== -Best Practice 1 - Writing Better eLisp -====================================== - ------------- -Introduction ------------- - -So far we have knocked up quick'n'dirty eLisp. As we get deeper into writing eLisp it is important to start following best practices to try and make sure our code is clean, good and easy to maintain. - -Best practices will be introduced in small chapters like this. - ------------------------------- -Avoiding Name Space Collisions ------------------------------- - -Emacs (and the eLisp it is written in) uses a lot of global state to manage itself. One of the problems with global state is that it can lead to developers accidentally overwriting other peoples function definitions and variables through name space collisions. - -When writing custom code for Emacs you should choose a name that describes what you are doing and use that as a prefix on all your variable and function definitions. - -For the rest of this book our chosen name is *omar*. Why omar? I like *The Wire* so why not. - ------------------------------ -Which Keys Should You Bind To ------------------------------ - -Emacs as an editor has an emphasis on keyboard shortcuts. There are lots of different add-ons and packages, major and minor modes, all of which use keyboard short cuts. - -If you start binding functions to key combinations randomly you may well start breaking other parts of Emacs. - -There are a complex set of conventions about which keys you should use - but we will conform to the most basic set of there here. - -The following keys are reserved for the use of users: - -* *[F5]* to *[F9]* -* *[C-c][a]* to *[C-c][z]* - -We will follow these conventions. - ------------------- -Additional Reading ------------------- - -There are more `Coding Conventions`_ for writing eLisp additional and rules about `Key-Binding Conventions`_ in the *Emacs Lisp Reference Manual*. - -.. _Coding Conventions: http://www.gnu.org/software/emacs/elisp/html_node/Coding-Conventions.html#Coding-Conventions - -.. _Key-Binding Conventions: http://www.gnu.org/s/emacs/manual/html_node/elisp/Key-Binding-Conventions.html#Key-Binding-Conventions diff --git a/rsts/community.rst b/rsts/community.rst deleted file mode 100644 index d209dc5..0000000 --- a/rsts/community.rst +++ /dev/null @@ -1,33 +0,0 @@ -=================================== -The Learn eLisp For Emacs Community -=================================== - -------- -License -------- - -When this book is finished it will be released under a Creative Commons License. At the moment is remain copyright Gordon Guthrie (2010). Until it has been finsihed you MAY NOT redistribute it but may participate in the community development of the text by forking the git repository. - ------------ -eMail Group ------------ - -You can join the `Mailing List`_ to contribute your thoughts or ask for help. - ---------------------- -Public Git Repository ---------------------- - -You can checkout the sources for this book from the `Public Git Repository`_ - -------- -Website -------- - -This book has an `Official Website`_. - -.. _Mailing List: http://groups.google.com/group/learn-elisp-for-emacs - -.. _Public Git Repository: https://github.com/hypernumbers/learn_elisp_the_hard_way - -.. _Official Website: http://learn-elisp-for-emacs.org/ diff --git a/rsts/emacs-and-the-dot-emacs-file.rst b/rsts/emacs-and-the-dot-emacs-file.rst deleted file mode 100644 index e5cd3cb..0000000 --- a/rsts/emacs-and-the-dot-emacs-file.rst +++ /dev/null @@ -1,66 +0,0 @@ -========================= -Emacs And The .emacs File -========================= - ------------- -Introduction ------------- - -We will be using the `.emacs` file a lot to get our functionality into Emacs. Emacs itself also uses the `.emacs` file. Lets see how it uses it. - --------------- -Saving Options --------------- - -Emacs saves some of your options in the `.emacs` file. Lets change some options, save them and then see how they appear. - -Lets start by clearing the `.emacs` file - open it in an editor, delete all the contents and save it. (You might want to copy it elsewhere if it has stuff in it you really care about). - -If you edited it in Emacs you will need to close Emacs and reopen it to 'lose' all your old configuration - if you edited it in an other editor, simply open Emacs. - -We are going to do some simple changes to our default fonts and then save them. - -Use the menu item *Options -> Set Default Fonts...* and you will get the standard font dialog box: - -.. image :: /images/emacs-font-dialog-box.png - -Choose a different font, size, weight etc etc. Your open buffers will redraw with the new fonts. - -Now save the options with the menu item *Options -> Save Options*. - -Notice that the modeline now says something like `Wrote /home/gordonguthrie/.emacs` - obviously it will have your name in it and not mine. - -Now open the `.emacs` file. Mine looks like: - -| ``(custom-set-variables`` -| ``;; custom-set-variables was added by Custom.`` -| ``;; If you edit it by hand, you could mess it up, so be careful.`` -| ``;; Your init file should contain only one such instance.`` -| ``;; If there is more than one, they won't work right.`` -| ``)`` -| ``(custom-set-faces`` -| ``;; custom-set-faces was added by Custom.`` -| ``;; If you edit it by hand, you could mess it up, so be careful.`` -| ``;; Your init file should contain only one such instance.`` -| ``;; If there is more than one, they won't work right.`` -| ``'(default ((t (:inherit nil :stipple nil :background "white" :foreground "black" :inverse-video nil :box nil :strike-through nil :overline nil :underline nil :slant normal :weight normal :height 143 :width normal :foundry "bitstream" :family "Courier 10 Pitch")))))`` - -Emacs has *saved options* into the `.emacs` file. Emacs marks the code that it adds with quotes as above. If you see big chunks of code like this in your `.emacs` file - that's what it is. Don't panic. - ---------------------- -What You Have Learned ---------------------- - -You have learned not to worry about finding strange code in your `.emacs` file. - ----------------- -Extra Activities ----------------- - -You can really customise Emacs with the menu item *Options -> Customise Emacs - > Browse Customization Groups*. - -This should open up a page that looks like this: - -.. image :: /images/emacs-customization-groups.png - -Have a play with the various options and see what happens to your `.emacs` file when you save them. diff --git a/rsts/getting-started.rst b/rsts/getting-started.rst deleted file mode 100644 index e4e6705..0000000 --- a/rsts/getting-started.rst +++ /dev/null @@ -1,35 +0,0 @@ -=============== -Getting Started -=============== - --------------------------- -What Needs To Be Installed --------------------------- - -This book assumes that you have a clean install of Ubuntu 10.10 Desktop which can be obtained `from Ubuntu`_. - -Having created a clean install the Emacs package (version 23.1+1-4ubunutu7) should be installed. - -This can be done by: - -* selecting the Ubuntu menu `System -> Administration -> Synaptic Package Manager` -* use the Quick search input box in the top right -* select `emacs` by clicking the tick box in the first column -* click the `Apply` button and click `Apply` in the Summary dialog box - -.. image :: /images/synaptic_package_manager.png - -A dialog box entitled `Applying Changes` will appear. When the changes have been applied you may close the dialog box. - -**Please** only install the Emacs package as indicated. The exercises in this book are predicated on that being the case. - ------------------------ -How This Book Will Work ------------------------ - -The work on learning eLisp will take place within an X-Windows enabled version of Emacs as shown below. - -.. image :: /images/emacs.png - - -.. _from Ubuntu: http://www.ubuntu.com/desktop/get-ubuntu/alternative-download diff --git a/rsts/learning-elisp.rst b/rsts/learning-elisp.rst deleted file mode 100644 index 98769c4..0000000 --- a/rsts/learning-elisp.rst +++ /dev/null @@ -1,17 +0,0 @@ -============== -Learning eLisp -============== - --------------------- -Who This Book Is For --------------------- - -This book is for people who can already programme, but who are not familiar with functional programming. It is suitable for most programmers with experience of popular programming languages like Ruby, Java, Python, Perl, C, C++ and so on. - -It assumes that the reader can get a clean install of Ubuntu GNU/Linux up and running. - ---------------------------- -How This Book Teaches eLisp ---------------------------- - -This book teaches eLisp throught the medium of Emacs. Emacs has a *scratch* window in which arbritary eLisp expressions can be evaluated. Intitial lessons will use the *scratch* window. Later lessons will move on to creating external lisp files and loading them into Emacs to use them. diff --git a/rsts/lesson-1-1.rst b/rsts/lesson-1-1.rst deleted file mode 100644 index df06e46..0000000 --- a/rsts/lesson-1-1.rst +++ /dev/null @@ -1,45 +0,0 @@ -======================== -Lesson 1-1 - Using Emacs -======================== - --------------- -Learning Emacs --------------- - -This book is not designed to teach you how to use Emacs. It will teach you enough Emacs to complete the work in this book, but not more. - -If you want to learn to use Emacs then you should consider buying a book - I recommend `Learning Gnu Emacs`_. - ----------------- -Emacs Components ----------------- - -The version of Emacs we are using has 5 components on it: - -* a menubar -* a toolbar -* a window area (it is possible to have multiple window views) -* a mode line -* a minibuffer - -These are used for different things and are marked on the diagram below: - -.. image :: /images/emacs-components.png - -A file is referred to as a buffer - and a window is therefore a view of a buffer. - ----------- -Emacs Keys ----------- - -Emacs is primarly a keyboard-focused editor. The version we are using has mouse-friendly components (the menu bar, the toolbar) but they are very much tacked on. In a lot of environments the non-X Windows version isn't supported so learning the key short cuts for **all** menu actions is essential. - -In this book the various keyboard short cuts will be introduced as needed. There are two keys that you will need to know about. - -Emacs uses so-called key modifiers to implement keyboard shortcuts. The two important ones are the Control Key (`[Ctrl]` on your keyboard) and the Meta Key (`[Alt]` on your keyboard). Some keyboard shortcuts require you to use both of them at the same time. - -The most common key modifier on the keyboard is the Shift Key `[Shift]`. Control and Meta/Alt work in the same way. You implement Control-x by pressing `[Ctrl]` first, and then, whilst holding it down, pressing `x` - the same way as you do Shift-x. - -Where keyboard commands are required in this book they will be spelled out, but in other publication online (or the Emacs help) they are often written in a contracted form like C-x or M-x - -.. _Learning Gnu Emacs: http://oreilly.com/catalog/9781565921528 diff --git a/rsts/lesson-2-1.rst b/rsts/lesson-2-1.rst deleted file mode 100644 index fa78a6e..0000000 --- a/rsts/lesson-2-1.rst +++ /dev/null @@ -1,94 +0,0 @@ -================================== -Lesson 2-1 - First eLisp Programme -================================== - ----------------- -Lets Get Started ----------------- - -This lesson will show you how to execute your first eLisp programme. - -* start Emacs -* go to the scratch buffer by using the menu `Buffers -> \*scratch\*` - -:You Type: ``(+ 1 2)`` - -Then put the cursor at the **end** of the expression - that is to say after the right bracket and type ``Control-j`` - -:Result: ``3`` - -What you typed in consists of an expression ``(+ 1 2)`` and a command to Emacs to execute it ``[Control-j]``. Expressions are sometimes called *forms*. - -eLisp is a dialect of Lisp - which stands for List Processing. A list is any thing between two brackets ``(`` and ``)`` - -The programme that was executed consisted of an operator ``+`` and two constants ``1`` and ``2`` - -The command ``Control-j`` in Emacs is applied at the point where the cursor is - it evaluates all the eLisp in the window up to that point and prints the output. - -Lets look at executing the same expression in a different way. Delete the expression in the \*scratch\* buffer and type in a new one. - -:You Type: ``(+ 1.0 2.0)`` - -Now put the cursor in the **middle** of the expression - that is to say between the brackets and type ``Control-Alt-x`` - -:Result: In the window nothing will change. The result of the expression is now put in the *minibuffer* ``3.0`` - -The way in which you evaluate the expression determines where the output goes. Also notice that the previous examples used integers like ``1`` and ``2`` and returned an integer value. This expression uses floating point numbers like ``1.0`` and returns a float as the result. - -:You Type: ``(+ 1.0e+3 2.0e-2)`` - -Now put the cursor at the **end** of the expression and type ``Control-x Control-e`` - -:Result: In the window nothing will change by the value is now placed in the *minibuffer* ``1000.02`` - -You can express floating point numbers in scientific notation - ---------------------- -What You Have Learned ---------------------- - -You have learned how to evaluate a basic eLisp expression (or form) in the scratch buffer. - -**In future lessons you will not be told how to evaluate an expression - be sure to remember the key sequences to do it.** - ------------------- -Additional Reading ------------------- - -There is a section on data types in the `GNU Emacs Lisp Reference Manual`_. - ----------------- -Extra Activities ----------------- - -Try some expressions that add integers to floats. What is the result? - -What happens if you use scientific integers like ``1e+10``? - -Can you add negative numbers? - -What do you think the following expressions will return? - -| ``(- 3 4)`` -| ``(* 4 5)`` -| ``(/ 1.0 4.0)`` - -Evaluate the following expressions and try and work out why they return what they do? - -| ``(/ 1 4)`` -| ``(/ 1 4.)`` - -What do you think these symbols represent? - -| ``#b10101010`` -| ``#o127`` -| ``#x12DE`` -| (**Tip**: try using them in arithmetic expressions) - -What do you think these symbols represent? - -| ``1.0e+INF`` -| ``-1.0e+INF`` -| ``0.0e+NaN`` or ``-0.0e+NaN`` - -.. _GNU Emacs Lisp Reference Manual: http://www.gnu.org/software/emacs/emacs-lisp-intro/elisp/Numbers.html#Numbers diff --git a/rsts/lesson-2-2.rst b/rsts/lesson-2-2.rst deleted file mode 100644 index f49432e..0000000 --- a/rsts/lesson-2-2.rst +++ /dev/null @@ -1,221 +0,0 @@ -===================================== -Lesson 2-2 - Primitive Data Types (1) -===================================== - -**Prerequesite:** This lesson presumes you know how to invoke eLisp expression as shown in Lesson 2-1. - -------- -Context -------- - -The previous lessons looked at performing basic arithmetic operations on various sorts of numbers. - -This lessons will look at the other sorts of data types in eLisp. There are two different sorts of data types: - -* primitive data types -* non-primitive data types - -The diference between them is that non-primitive data types can be assembled from primitive ones. - -The general set of primitive data types of eLisp are: - -* integer -* float -* string -* character -* bool-vector -* symbol -* sequence -* cons -* array -* vector -* char-table -* hash-table -* function -* primitive function (or subr) -* macro -* byte-code -* auto-load - -These primitive data types largely correspond to the primitive data types of other Lisps. - -In addition eLisp has a number of data types that are peculiar to it, because they pertain to the fact that eLisp is the scripting language of an editor. These data types are: - -* buffer -* marker -* window -* frame -* terminal -* window configuration -* frame configuration -* process -* stream -* keymap -* overlay -* font - -.. warning:: - - don't really understand types, primitive and otherwise... - ---------------------------- -What This Lesson Will Cover ---------------------------- - -This lesson will look at: - -* the representation of boolean values -* the integer and float data types which were introduced ealier -* the string data type -* testing for data types -* casting between values - --------- -Booleans --------- - -Booleans represents *true* and *false*. - -:You Type: ``(= 1 1)`` -:Result: ``t`` - -This function tests for equality. The value ``t`` is a boolean (ie means *true*). This expression (which means *is 1 equal to 1*) is easy to switch to test for false. - -:You Type: ``(= 1 2)`` -:Result: ``nil`` - -The value ``nil`` is the second boolean it means *false*. The two values ``t`` and ``nil`` are *constant values* that always evaluate to themselves. - -We can use the function ``if`` to investigate the boolean types. ``if`` takes three parameters, it is a standard ternary if function familiar from other langauges. - -:You Type: ``(if t "it's true" "it's false")`` -:Result: ``"it's true"`` - -You can read the if expression like this ``if t`` *is true then return* ``"it's true"`` *if it isn't then return* ``"it's false"``. - -:You Type: ``(if nil "it's true" "it's false")`` -:Result: ``"it's false"`` - -However booleans are not types. They are called *Constant Variables*. - -Handling *true/false* is not so simple however consider the following: - -:You Type: ``(if () "it's true" "it's false")`` -:Result: ``nil`` - -The empty list ``()`` is also a synomym for false. ``if``, however, follows the convention that *that which is not false is true* as we can see from the following: - -:You Type: ``(if 101 "it's true" "it's false")`` -:Result: ``"it's true"`` - -------- -Strings -------- - -We have seen string data types being used in the previous tests - strings are represented by characters between double quotes. - -:You Type: ``(concat "ab" "cd")`` -:Result: ``"abcd"`` - -``concat`` is just a string concatenation function. The strings can include single quotes and escaped double quotes. - -:You Type: ``(concat "a`b" "c\"d")`` -:Result: ``"a'bc\"d"`` - -The ``concat`` operator can a indefinite number of arguments. - -:You Type: ``(concat "ab" "cd" "ef" "12" "34" "45")`` -:Result: ``"abcdef123445"`` - -------------------------------------------------- -Predicate Functions - Testing The Types Of Vaules -------------------------------------------------- - -There are a whole class of functions that tests data types - the so-called *predicates*. - -:You Type: ``(integerp 11)`` -:Result: ``t`` - -This predicate function (like most predicate functions) can be recognised by the fact that it ends in p - -:You Type: ``(integerp (+ 1 2.0))`` -:Result: ``nil`` - -We see from this example that data types cast automatically. The sum of an integer and a float is a float - and the predicate therefore fails. - -Certain functions expect certain types - for instance ``+`` expects numbers as it parameters. - -:You Type: ``(+ 1 "two")`` -:Result: The functions throws an error and dumps you into the debugger. - -This is in a window called \*backtrace\*. It is worth looking at the output in some detail. - -| ``Debugger entered--Lisp error: (wrong-type-argument number-or-marker-p "two")`` -| ``+(1 "two")`` -| ``eval((+ 1 "two"))`` -| ``eval-last-sexp-1(t)`` -| ``eval-last-sexp(t)`` -| ``eval-print-last-sexp()`` -| ``call-interactively(eval-print-last-sexp nil nil)`` - -The first line of this give us some details of the problem, it is a Lisp error - the predicate function ``number-or-marker-p`` on the parameter ``two`` threw an ``wrong-type-argument`` error. We will look at the debugger later on in the book. If you go back to the list of Emacs specific types you will see that there is one called marker. The operator ``+`` can operate on numbers or markers and so it uses this special predicate function to test the arguments before running the function. - ------------------------------ -Converting Between Data Types ------------------------------ - -Sometimes eLisp converts between data types. Consider mixed arithmetic with integers and floating point numbers: - -:You Type: ``(+ 1 2.5)`` -:Result: ``3.5`` - -The integer value of ``1`` has been *cast* to a floating point number. - -You can force this casting with functions: - -:You Type: ``(float 1)`` -:Result: ``1.0`` - -You can turns numbers into string: - -:You Type: ``(number-to-string 1234)`` -:Result: ``"1234"`` - -You can also cast strings which contain the numerical characters into numbers: - -:You Type: ``(string-to-number "1234")`` -:Result: ``1234`` - ---------------------- -What You Have Learned ---------------------- - -We have seen the list of primitive and composite data types and have looked at a couple of the most common of them in some detail. We have seen how to test what data type an object it, and how to cast one data type to another. - ------------------- -Additional Reading ------------------- - -There is a section on data types in the `GNU Emacs Lisp Reference Manual`_. - ----------------- -Extra Activities ----------------- - -List gets its name from LIS(t) P(rocessing) - and yet lists don't appear as a primitive data types. From the additional reading can you work out why? - -What do the following predicate functions do: - -* ``floatp`` -* ``numberp`` -* ``zerop`` -* ``wholenump`` - -What do the following functions do: - -* ``float`` -* ``truncate`` -* ``ceiling`` -* ``floor`` - -.. _GNU Emacs Lisp Reference Manual: http://www.gnu.org/software/emacs/emacs-lisp-intro/elisp/Lisp-Data-Types.html#Lisp-Data-Types diff --git a/rsts/lesson-2-3.rst b/rsts/lesson-2-3.rst deleted file mode 100644 index ad56f8c..0000000 --- a/rsts/lesson-2-3.rst +++ /dev/null @@ -1,93 +0,0 @@ -============================ -Lesson 2-3 - Lists (At Last) -============================ - -**Prerequesite:** This lesson presumes you know how to invoke eLisp expression as shown in Lesson 2-1. - ------------- -Introduction ------------- - -eLisp is a dialect of Lisp - the LISt Processing language. - -You will have noticed that all the expressions we have used so far has been of the form ``(something somethingelse anotherthing)``. That basic form is a list - defined by the opening and closing brackets. All the expressions we have looked at so far have been the simplest sort of programmes - lists where the first element is an operator and the remaining elements are data. But a list can also be simple data. - ----------- -Data Lists ----------- - -The eLisp interpreter has to be told that it is a data list. This is done by **quoting** it with a single quote. - -:You Type: ``'(1 2 3)`` -:Result: ``(1 2 3)`` - -The apostrophe ``'`` is syntactic sugare for the quote operator which can be invoked like a normal operator: - -:You Type: ``(quote (1 2 3))`` -:Result: ``(1 2 3)`` - -You can also make a list with the list operator: - -:You Type: ``(list 1 2 3)`` -:Result: ``(1 2 3)`` - -It all seems so reasonable, but wait, lets try that again. - -:You Type: ```(1 2 3)`` -:Result: ``(1 2 3)`` - -"*Ah, we have just done that*" sez you - except we haven't. This last example has a **backtick** ````` and not a **single quote** ``'``. The backtick is a different operator which, in this instance, just produces a list. In other circumstances it behaves very differently to the single quote operator. - ------------------- -Nested Expressions ------------------- - -You can nest expressions. - -:You Type: ``(+ 1 (* 2 3))`` -:Result: ``7`` - -The inner expression is evaluated first: - -:Inner: ``(* 2 3)`` -:Result: ``6`` - -This is then put into the outer expression which is then evaluated: - -:Outer: ``(+ 1 6)`` -:Result: ``7`` - ---------------------- -What You Have Learned ---------------------- - -One of the great simplicities of Lisp is that data and programmes are very similar - both are lists - and that you can manipulate programmes as if they were data. - -We have previously seen *lists-as-programmes* and this section has looked at *lists-as-data* and the nesting of lists. - ----------------- -Extra Activities ----------------- - -There are three additional functions that can be used to make and break lists ``cons``, ``car`` and ``cdr``. - -``cons`` is short for constructs and is used to build lists. ``car`` and ``cdr`` take their name from assembly code instructions whose meanings may as well be lost in the mists of time. - -You build a lists with ``cons`` like this: - -:You Type: ``(cons 1 '(2 3))`` -:Result: ``(1 2 3)`` - -``cons`` adds a new value to the start or *head* of a list. Note that the list to which you are adding it has to be quoted. - -You can split a list into two parts - the first value (the *head*) and the remaning ones (the *tail*). The head is extracted with ``car``: - -:You Type: ``(car '(1 2 3))`` -:Result: ``1`` - -The tail is extracted with ``cdr``: - -:You Type: ``(cdr '(1 2 3))`` -:Result: ``(2 3)`` - - diff --git a/rsts/lesson-2-4.rst b/rsts/lesson-2-4.rst deleted file mode 100644 index 467ada7..0000000 --- a/rsts/lesson-2-4.rst +++ /dev/null @@ -1,171 +0,0 @@ -================================== -Lesson 2-4 - Symbols And Variables -================================== - -**Prerequesite:** This lesson presumes you know how to invoke eLisp expression as shown in Lesson 2-1. - ----------------- -Symbols Overview ----------------- - -Before you can start building functions we need to understand what symbols are. We have seen expressions like ``(concat "blah" "bleh")``. In that expression ``concat`` is a symbol - a symbol whose value is a function or an operator. - -Symbols can be three different things: - -* operators or functions -* data values -* property lists - -Some symbols are also the so-called *constant variables* - they evaluate to themselves (their data value is their name) and they cannot have their datavalue set to anything else. - -The constant values are used to define property lists. - -------------------------- -Symbols As Function Names -------------------------- - -Symbols can be the name of functions (or operators). We will look into how these are set in a later lesson. - --------------------- -Symbols As Variables --------------------- - -Instances of Data Types evaluate to themselves in eLisp: - -:You Type: ``9`` -:Result: ``9`` - -You can evaluate Symbols similarly - -:You Type: ``fill-column`` -:Result: ``70`` - -(It might not be ``70`` - but it probably will be). ``fill-column`` is a variable in eLisp with global scope. Later on we will see how this sort of variable will be used and have its value changed. - -Variables don't just exist with default values. If you try and use a random symbol in an expression it will fail. - -:You Type: ``(+ 1 do_tell)`` -:Result: You are dropped into the debugger - -| ``Debugger entered--Lisp error: (void-variable do_tell)`` -| ``(+ 1 do_tell)`` -| ``eval((+ 1 do_tell))`` -| ``eval-last-sexp-1(t)`` -| ``eval-last-sexp(t)`` -| ``eval-print-last-sexp()`` -| ``call-interactively(eval-print-last-sexp nil nil)`` - -The variable ``do_tell`` has been created but its value is *void* and it cannot be used. - -You give a symbol a value using the operators ``set`` and ``setq``. **These define global variables**. - -:You Type: ``(set 'do_tell '11)`` -:Result: ``11`` - -If we now evaluate the ``do_tell`` it no longer throws an error: - -:You Type: ``do_tell`` -:Result: ``11`` - -Notice that when the value of ``do_tell`` was set ``do_tell`` was quoted viz ``'do_tell``. The quoting says to eLisp "*don't treat do_tell as a variable is a value to be passed to the operator set*". The operator ``setq`` just *absorbs* that quote and lets you not quote the first parameter. - -:You Type: ``(setq do_tell '22)`` -:Return: ``22`` - -We can now use this variable in an expression: - -:You Type: ``(+ do_tell 33)`` -:Return: ``55`` - -There is a variant on ``set`` and ``setq`` called ``defvar`` that defines a variable. It is different from them in that it only applies to unitialised variables. If a variable is already defined it won't overwrite it. - -:You Type: ``(defvar farmer_dell 123)`` -:Return: ``farmer_dell`` - -We can now see what ``defvar`` has done to the variable ``farmer_dell`` by evaluating that: - -:You Type: ``farmer_dell`` -:Return: ``123`` - -But if we ``defvar`` on ``do_tell`` it won't take: - -:You Type: ``(defvar do_tell 123)`` -:Return: ``do_tel`` - -and now evaluate ``do_tell``: - -:You Type: ``do_tell`` -:Return: ``33`` - -(This only works if you have used ``set`` or ``setq`` to define ``do_tell`` in the \*scratch\* buffer earlier in the same editing session). - --------------------------------------- -Constant Variables And Keyword Symbols --------------------------------------- - -Some symbols can't be redefined. We have met a couple of them before ``nil`` and ``t``. Dy design all symbols which begin with ``:`` are also constant values. - -If you try and set a symbol whose name starts with ``:`` you will get an error. - -:You Type: ``(setq :hotdog 3)`` -:Return: ``Debugger entered--Lisp error: (setting-constant :hotdog) ...`` - -An alternative name for a symbol which starts with ``:`` is a keyword symbol and these *constant variables* are commonly used as keywords in property lists. - --------------- -Property Lists --------------- - -Property lists are lists where each pair of concurrent values are regarded as a pair. The two values can be anything, but conventionally the first of them is a constant variable with a name beginning with ``:``. Here is an example: - -``(:quality "great" :achievement "impressive")`` - -The relationship of property lists with symbols is a bit messy and is discussed in the *Extra Activities* section of this lesson. - ---------------------- -What You Have Learned ---------------------- - -You have learned how to set values of Symbols and then reuse those symbols in expressions. - ------------------- -Additional Reading ------------------- - -Symbols in eLisp are a bit more complex than symbols in other languages - there is a discussion of `Symbols`_ in the *Introduction To Emacs Lisp* manual. - -You can read about `Symbol Properties`_ in the *Emacs Lisp Reference* manual. - ------------------------- -Extra Quoting Activities ------------------------- - -If we fail to quote variables properly with the set operator will generate errors. Can you work out what they mean? - -| ``(set bleh '(1 2 3))`` -| ``(set 'bleh (1 2 3))`` - ----------------------------- -Extra Property List Activity ----------------------------- - -Property lists can be the *value* of a symbol and are associated with it by ``setq``: - -:You Type: ``(setq hotdog '(:quality "great" :achievement "impressive"))`` -:Return: ``(:quality "great" :achievement "impressive")`` - -But the symbol can also have its own *plist* which is created by the special function ``setplist``. (the symbol must already have been created.) - -:You Type: ``(setplist hotdog '(:rhubarb "custard" :status "borked"))`` -:Return: ``(:rhubarb "custard" :status "borked")`` - -However if we now evaluate the value of ``hotdog`` you will see that it is ``(:quality "great" :achievement "impressive")`` as that is the *value* we set previously: - -:You Type: ``hotdog`` -:Return: ``(:quality "great" :achievement "impressive")`` - -What happens if you try and set the property list of an undefined symbol? - -.. _Symbols: http://www.gnu.org/software/emacs/emacs-lisp-intro/elisp/Symbol-Components.html#Symbol-Components - -.. _Symbol Properties: http://www.gnu.org/software/emacs/elisp/html_node/Symbol-Plists.html#Symbol-Plists diff --git a/rsts/lesson-2-5.rst b/rsts/lesson-2-5.rst deleted file mode 100644 index 54d29c2..0000000 --- a/rsts/lesson-2-5.rst +++ /dev/null @@ -1,76 +0,0 @@ -=================================== -Lesson 2-5 - Arrays (And Sequences) -=================================== - -**Prerequesite:** This lesson presumes you know how to invoke eLisp expression as shown in Lesson 2-1. - ------------- -Introduction ------------- - -We have seen *lists* in eLisp. Lists are an example of a *sequence* - a load of things stored in another thing which we can access sequentially. - -There is another type of *sequence* in eLisp - an *array*. Arrays themselves come in 2 flavours: - -* strings -* vectors -* bool-vector -* char-table - -The relationship of all these things is shown below: - -.. image :: /images/elisp-sequences.png - -There are sets of functions that operate on all *sequences*, some which apply to *array*'s only and then other sets for the actual data types themselves (*lists*, *strings*, *vectors*, *bool-vectors* and *char-tables*). - -This lesson will look at: - -* strings -* vectors - -The Extra Activities section will cover functions that operate on sequences. - -------------------------- -Why Arrays And Not Lists? -------------------------- - -The difference betweeen arrays and lists is that arrays have fixed lengths and lists have variable length. This gives them different performance characteristics - array elements are accessible in constant time, whereas the access time for lists is proportional to their length. - --------------------------------------- -Difference Between Strings And Vectors --------------------------------------- - -In eLisp a string is simply an array whose elements consists of the integers which represent unicode points. A vector is a general array whose elements are any valid eLisp term. - -------------------- -Why Only 1D Arrays? -------------------- - -Arrays are 1 dimensional only. Given that the elements of a vector can consist of other valid eLisp symbol, multi-dimensional arrays can be implemented as vectors of vectors. - ---------------- -Creating Arrays ---------------- - -A array is delimied by square brackets (``[`` and ``]``). You can create them inline: - -:You Type: ``[1 2 3]`` -:Return: ``[1 2 3]`` - -You can create vectors using the ``vector`` operator: - -:You Type: ``(vector 1 2 3)`` -:Return: ``[1 2 3]`` - -The operator ``string`` does the same for strings. To create a string you need array elements that are the integers which represent characters - a full set of unicode values is supported. - -:You Type: ``(string 97 98 99)`` -:Result: ``"abc"`` - -(96 is ascii for ``a``) - ---------------------- -What You Have Learned ---------------------- - -You have learned about additional types of sequences and see how they are constructed. diff --git a/rsts/lesson-3-1.rst b/rsts/lesson-3-1.rst deleted file mode 100644 index 95b1a4d..0000000 --- a/rsts/lesson-3-1.rst +++ /dev/null @@ -1,135 +0,0 @@ -============================== -Lesson 3-1 - Writing Functions -============================== - ------------------ -Script Mode eLisp ------------------ - -In order to write functions it is necessary to change the way in which eLisp expressions will be evaluated. Instead of invoking expressions in the \*scratch\* buffer it is time to switch to running eLisp as a script. - -To do this an eLisp file has to be invoked from the command line. If you had some eLisp expressions in a file called *first_programme.el* the following command would be run it as a script ``emacs --no-site-file --script first_programme.el`` - -The option ``--no-site-file`` means that emacs doesn't load any eLisp from the site libraries. By default the ``--script`` option also includes option ``--no-init-file``. Normally emacs starts and executes a init file. In Ubuntu this file is ``.emacs`` in the users home directory. - -Start by creating a new directory, and in that create a file called *message.el*. The contents of that file is a single eLisp expression: - -``(message "Bonjour Tout Le Monde")`` - -The file should be executed by running this batch command in the directory in which you have created *message.el* - -``emacs --no-site-file --script message.el`` - -The output should be ``Bonjour Tout Le Monde`` - --------------------------- -Defining A Simple Function --------------------------- - -We will start by defining a function. Create a file with the following code in it: - -| ``(defun bonjour () (message "Bonjour Tout Le Monde"))`` -| ``(bonjour)`` - -On executing this file the output will be: - -``Bonjour Tout Le Monde`` - -Lets understand what we are seeing. Consider the first line - the operator ``defun`` indicates that we are defining a function. Here it is taking 3 parameters: - -| **1** ``bonjour`` which is the name of the function -| **2** ``()`` which is a list of the parameters that the function will take -| **3** ``(message "Bonjour Tout Le Monde")`` is the body of code that will executed when the function is run - -The second line simply executes the fuction ``bonjour``. The function definition states that ``bonjour`` takes no parameters (the list of parameters is empty). - --------------------------------- -Defining A More Complex Function --------------------------------- - -Lets create a function that takes multiple arguments: - -| ``(defun tough_maths (i j k)`` -| ``"jeepers maths is tough!"`` -| ``(message (number-to-string (+ i j k))))`` -| ``(tough_maths 3 4 5)`` - -When executed this will return: - -``12`` - -In this case (unlike the simple case) ``defun`` takes 4 parameters and not three. The second paramater ```(i j k)`` is a list of parameters that the function takes. The third parameter is the documentation - it can be a string broken over many lines. The fourth parameter is the body of the function as in the previous example. Notice that in order to write the output the value of the expression ``(+ i j k)`` must be cast to a string with the operator ``number-to-string``. - --------------------------------------------- -Functions With Variable Numbers Of Arguments --------------------------------------------- - -We have seen that the function ``defun`` has variable arity - that is to say it can take 3 or 4 arguments - we will see later that it can actually take 5 parameters. - -Lets write a variable arity function: - -| ``(defun variable_arity (a &optional b &rest c)`` -| ``"This is a function which has variable arity"`` -| ``(message (concat "variable a is " a))`` -| ``(message (concat "variable b is " b))`` -| ``(if c (message "c is not an empty list") (message "c is an empty list")))`` -| ``(message "run the fn with 1 variable")`` -| ``(variable_arity "eh")`` -| ``(message "run the fn with 2 variables")`` -| ``(variable_arity "eh" "bee")`` -| ``(message "run the fn with 3 variables")`` -| ``(variable_arity "eh" "bee" "see")`` -| ``(message "run the fn with 4 variables")`` -| ``(variable_arity "eh" "bee" "see" "dee")`` -| ``(message "run the fn with 5 variables")`` -| ``(variable_arity "eh" "bee" "see" "dee" "eee")`` - - -The result is: - -| ``run the fn with 1 variable`` -| ``variable a is eh`` -| ``variable b is`` -| ``c is an empty list`` -| ``run the fn with 2 variables`` -| ``variable a is eh`` -| ``variable b is bee`` -| ``c is an empty list`` -| ``run the fn with 3 variables`` -| ``variable a is eh`` -| ``variable b is bee`` -| ``c is not an empty list`` -| ``run the fn with 4 variables`` -| ``variable a is eh`` -| ``variable b is bee`` -| ``c is not an empty list`` -| ``run the fn with 5 variables`` -| ``variable a is eh`` -| ``variable b is bee`` -| ``c is not an empty list`` - -The important part of this is the first part of the function definition ``(defun variable_arity (a &optional b &rest c)...``. ``a`` is a required option - calling ``variable_arity`` with zero parameters will result in an error. The marker ``&optional b`` indicates that the subsequent parameter ``b`` is optional. In this function there is only one optional function but a clause like ``(i j &optional k l m)`` would have three optional arguments. The final clause ``&rest c`` indicates that all parameters from 3 onwards will be collected into the variable ``c`` as a list. You can have either ``&optional`` or ``&rest`` or both together as in this function. - ---------------------- -What You Have Learned ---------------------- - -You have learned how to run eLisp programmes in batch mode, and also how to define simple, more complex and variable arity functions and invoke them. - ------------------- -Additional Reading ------------------- - -There is a section of the eLisp Reference Manual entitled `Functions`_. - ----------------- -Extra Activities ----------------- - -Write a function with multiple line documentation. - -The *required*, *optional* and *rest* clauses must be specified in that order. Can you work out why? - - -.. _Functions: http://www.gnu.org/software/emacs/elisp/html_node/Functions.html#Functions - diff --git a/rsts/lesson-3-2.rst b/rsts/lesson-3-2.rst deleted file mode 100644 index 6052881..0000000 --- a/rsts/lesson-3-2.rst +++ /dev/null @@ -1,114 +0,0 @@ -=========================== -Lesson 3-2 - More Functions -=========================== - -**Prerequesite:** This lesson presumes you know how to invoke eLisp expression as scripts as shown in Lesson 3-1. - ------------- -Introduction ------------- - -The functions we built in the previous lesson were a bit useless. This lesson will look at some more sophisticated functions: - -* ones which can use local variables -* recursive functions - ------------------------------- -Functions With Local Variables ------------------------------- - -We have seen how to use ``set`` and ``setq`` to set *global* variables. Global variables are very ugly to use as they can be changed from anywhere and at anytime. This makes them very hard to reason about, and hence to use safely and debug. - -It is important to be able to define *local* variables - variables which can only be set and changed locally from a small number of defined and known places. - -The function used to do this is ``let``. It works like ``set``. - -Type the following expressions in a file: - -| ``(let ((first "hey")`` -| ``(second "ho"))`` -| ``(message first)`` -| ``(message second))`` - -The output should be: - -| ``hey`` -| ``ho`` - -If you carefully count the brackets you will see that ``(first "hey")`` and ``(second "ho")`` are both within a list that is the first parameter of ``let``. The scope of those variables is then the list that makes up the rest of the expression that has ``let`` as its operator. - -We can see that this is the case by adding another message line: - -| ``(let ((first "hey")`` -| ``(second "ho"))`` -| ``(message first)`` -| ``(message second))`` -| ``(message first)`` - -When we try and run this we get an error message printed out: - -| ``hey`` -| ``ho`` -| ``Symbol's value as variable is void: first`` - -This can now be used to make functions which are safe to use. Type in the following function: - -| ``(defun myfun (a b c d)`` -| ``"This is a nonce function designed to show how to`` -| ``use local variables safely"`` -| ``(let ((e (+ a b))`` -| ``(f (* c d)))`` -| ``(- e f)))`` -| ``(message (number-to-string (myfun 7 5 3 1)))`` - -The result should be: - -``9`` - -Check that result yourself by working through the arithmetic. - -------------------- -Recursive Functions -------------------- - -Recursive functions are an important part of functional programming. A recursive function is simply one that calls itself - -Create the following file: - -| ``(defun print_int (n)`` -| ``"This function prints a list of integers in reverse order"`` -| ``(message (number-to-string n))`` -| ``(if (= n 0) (message "That's all folks!") (print_int (- n 1))))`` -| ``(print_int 5)`` - -Your output should be: - -| ``5`` -| ``4`` -| ``3`` -| ``2`` -| ``1`` -| ``0`` -| ``That's all folks!`` - -The key is the ``if`` expression. The first expression is *the terminal test*. If it is true the function prints "*That's all folks!*". If the terminal test is not met (ie it is false) the function calls itself with a value of the current value of ``n - 1``. - ---------------------- -What You Have Learned ---------------------- - -You have learned how to build basic functions with local variables and then how to build functions that call themselves. - ------------------- -Additional Reading ------------------- - -There is a section on `Recursive Functions`_ in the Gnu Emacs Lisp Intro. - ----------------- -Extra Activities ----------------- - -Write a recursive function to calculate the factorial of an integer. - -.. _Recursive Functions: http://www.gnu.org/software/emacs/emacs-lisp-intro/html_node/Recursive-Definition-Parts.html#Recursive-Definition-Parts diff --git a/rsts/lesson-4-1.rst b/rsts/lesson-4-1.rst deleted file mode 100644 index 0fd25bb..0000000 --- a/rsts/lesson-4-1.rst +++ /dev/null @@ -1,49 +0,0 @@ -=================================== -Lesson 4-1 - Writing eLisp In Emacs -=================================== - ------------- -Introduction ------------- - -Emacs as an editor provides a host of specific tools to help software developers in a wide range of languages. Not suprisingly the support for the eLisp language in Emacs is very good. - -This lesson will explore Emacs as an editor for eLisp. - -Emacs switches into a special mode for a particular programming language by looking at the extension on the filename - the exension for eLisp is ``.el``. If you create a file called *something*.el and open it with Emacs you will see that the editor has changed itself. - -.. image :: /images/emacs-lisp.png - -The modeline now contains the expression (Emacs-Lisp) which indicates that it is in *the Emacs Lisp Major Mode*. The menu bar now has an *Emacs-Lisp* menu. - -A new menu has appeared. Lets look at some of the commands on it. There are indenting commands that can be used to pretty up the source code and lay it out consistently. (*Indent Line* uses the [Tab] key to indent a line. Regions commands can be used on regions - blocks of code which have been selected by marking their starts with [Control][Space] and the moving the cursor point. - -There are menu commands for evaluating expressions and the contents of the buffer as well as various profiling and tracing tools. - -If you execute expressions now, the operator ``message`` will now ouput to the *minibuffer* at the bottom of Emacs. - -One of the most important features in the debugger - which is triggered when you instrument a function for debugging using the menu command *Instrument Functions for Debugger*. - -.. image :: /images/emacs-debugger.png - -Detailed instructions on using the Emacs debugger can be found in the `Emacs Manual`_ - -Load an eLisp file, and execute it under the debugger. The diagram below shows it working. You can step through the code line-by-line. The debugger shows the values of the last expression executed in the minibuffer at the bottom. In the picture the last expression executed is ``a`` (as shown by the debugger cursor which is placed after it) - its current value (``7``) is shown in the minibuffer. - -.. image :: /images/emacs-debugger2.png - -Read the manual section and try out the debugger until you have mastered it - it will be necessary to use it to develop more complex functionality. - ---------------------- -What You Have Learned ---------------------- - -This lesson has covered the operations of the Emacs debugger Edebug. - ----------------- -Extra Activities ----------------- - -Run the menu item *Check Document Strings* in the *Emacs-Lisp* menu - can you work out what does the operator ``provide`` does? - -.. _Emacs Manual: http://www.gnu.org/software/emacs/manual/html_node/elisp/Using-Edebug.html#Using-Edebug diff --git a/rsts/lesson-4-2.rst b/rsts/lesson-4-2.rst deleted file mode 100644 index 297320d..0000000 --- a/rsts/lesson-4-2.rst +++ /dev/null @@ -1,132 +0,0 @@ -============================================= -Lesson 4-2 - Adding Custom Functions To Emacs -============================================= - ------------- -Introduction ------------- - -In order to run custom eLisp functions it is necessary to have them loaded into Emacs at run time. - -On load time emacs executes a startup file. In Emacs-23 on Ubuntu 10.10 this is a file called ``.emacs`` in your home directory. - -This file may or may not exist. Emacs is quite happy for it not to exist. If you change any settings using the *Options* menu and then save them, the results will be written to the ``.emacs`` file. - ------------------------- -A Simple Custom Function ------------------------- - -Open the ``.emacs`` file (or create it if it doesn't exist) and add the following function: - -| ``(defun doodlebug ()`` -| ``"Nonce function"`` -| ``(interactive)`` -| ``(message "Howdie-doodie fella"))`` - -The first time you do this, edit the ``.emacs`` file and then open Emacs. If you edit it in Emacs you will need to quit and restart. - -On starting Emacs all the code in ``.emacs`` is reloaded and evaluated. - -This function can be run simply. The command *[Alt][x]* is used to a run a function interactively. Typing *[Alt][x]* switches the focus in Emacs to the minibuffer - if you then type in a function name it will be executed. To run ``doodlebug`` simply type *[Alt][x]* and then *doodlebug*. - -You should then see the output in the minibuffer: - -``Howdie-doodie fella`` - -Look carefully at the function definition. The third parameter of the list is the expression ``(interactive)`` - this is necessary if we are to invoke the function from either a key-binding or the minibuffer. - ---------------------------------- -A Custom Function With User Input ---------------------------------- - -Lets edit the function to take some parameters: - -| ``(defun doodlebug (a b c)`` -| ``"Nonce function"`` -| ``(interactive "sAdjective: \nsNoun: \nsExclamation: \n")`` -| ``(message "Its a %s thing, this %s, so it is, %s" a b c))`` - -You can't reload the ``.emacs`` file, but you can manually re-evaluated by using the command *Emacs-Lisp -> Evaluate Buffer* in the ``.emacs`` buffer. - -When you run this version of the function with *[Alt][x]doodlebug* it will offer up three prompts, to wit: - -| ``Adjective:`` -| ``Noun:`` -| ``Exclamation:`` - -As you type in a string at each prompt (ending with *[Return]*) each of the strings wll be bound to the variables ``a``, ``b`` and ``c`` in turn. - -This behaviour in enabled by the new form of the *interactive* expresion. The string which has been added to that expression consists of 6 seperate components: - -| ``s`` -| ``Adjective: \n`` -| ``s`` -| ``Noun: \n`` -| ``s`` -| ``Exclamation: \n`` - -The 2nd, 4th and 6th parts are the prompts which will be shown in the minibuffer. The three ``s``'s are Interactive Codes which refer to strings (ie key sequences terminated with *[Return]* which are entered at the prompt. There are a range of other Interative Codes, some of which are: - -| ``a`` - a function name -| ``b`` - the name of an existing buffer -| ``B`` - the name of a buffer which may or may not exist -| ``c`` - a character -| ``C`` - a command -| etc, etc - -You can read the full list of `Interactive Codes`_ in the reference manual - ---------------------------------------------- -Binding The Custom Function To A Key Sequence ---------------------------------------------- - -To bind the custom function to a key sequence add the following line to the ``.emacs`` file. - -``(global-set-key [f5] 'doodlebug)`` - -This expression will bind the function ``doodlebug`` to the *F5* function key. Once you have re-evaluated the ``.emacs`` buffer you will be able to fire the function with the *F5* key. - -We can identify which function is bound to which key with the command: - -``(lookup-key (current-global-map) [f5])`` - -The rules for binding keys are a bit complex. We can use the operator ``kbd`` to generate the appropriate input to ``global-set-key`` and ``lookup-key``, for instance: - -| ``(global-set-key (kbd "C-c a") 'doodlebug)`` -| ``(lookup-key (current-global-map) (kbd "C-c a"))`` - -The expression ``(kbd "C-c a")`` generates the appropriate keymap for the key sequence *[C-c][a]*. - ---------------------- -What You Have Learned ---------------------- - -You have learned: - -* a way to load a new function into emacs -* how to make the function take interactive paramters -* how to invoke that command - via the command line and via a custom key - ------------------- -Additional Reading ------------------- - -There is a good discussion of keybindings in your ``.emacs`` file in the Emacs Lisp Introduction. - -The whole process of binding keys to functions in emacs is quite complex and is covered in the `Keymaps`_ section of the manual - ----------------- -Extra Activities ----------------- - -What happens if you try and run a function which doesn't include the expression ``(interactive)``? - -Experiment with other Interactive Codes in your functions. - -Bind and unbind some keys to functions in your ``.emacs`` file. - -.. _Interactive Codes: http://www.gnu.org/software/emacs/elisp/html_node/Interactive-Codes.html#Interactive-Codes - -.. _Key Bindings: http://www.gnu.org/software/emacs/emacs-lisp-intro/html_node/Keybindings.html#Keybindings - -.. _Keymaps: http://www.gnu.org/s/emacs/manual/html_node/elisp/Keymaps.html#Keymaps diff --git a/rsts/lesson-4-3.rst b/rsts/lesson-4-3.rst deleted file mode 100644 index 395fb5f..0000000 --- a/rsts/lesson-4-3.rst +++ /dev/null @@ -1,147 +0,0 @@ -======================== -Lesson 4-3 - Emacs Menus -======================== - -**Prerequesite:** this lesson presumes you know how to use the ``.emacs`` file as outlined in Lessons 4-1 and 4-2. - ------------- -Introduction ------------- - -This section will look at creating a new menu in Emacs and binding a custom function to it. Before doing that we need to create a couple of functions in our ``.emacs`` file to bind to the menu. - -We will incorporate our best practice naming conventions in it. - -| ``(defun omar-hip ()`` -| ``"a nonce menu function"`` -| ``(interactive)`` -| ``(message "hip, hop, don't stop"))`` - -| ``(defun omar-hotel ()`` -| ``"another nonce menu function"`` -| ``(interactive)`` -| ``(message "hotel, motel, holiday inn"))`` - -------------------- -The Basics Of Menus -------------------- - -We are going to create a menu called ``Omar`` which calls these two functions. - -Type the following into your ``.emacs`` file and re-evaluate the buffer. - -| ``(define-key global-map [menu-bar omar]`` -| ``(cons "Omar's Menu" (make-sparse-keymap "Omar")))`` - -You will see that this has created a new top-level menu at the left of the menu bar. It consists of the words *Omar's Menu*. There are no items below it. - -Lets look at that expression - it is defining a new key in the ``global-map``. The global map is a data structure which holds details of all key inputs: - -* menu items -* toolbar items -* key shortcuts -* etc, etc - -You can look at the value of the global keymap by evaluating the expression ``(current-global-map)`` in the \*scratch\* buffer. - -The next parameter is the array ``[menu-bar omar]`` which tells the global keymap that this new key is under the menu. The final item is a parameter list - in this cause just jusing a normal string as the key. The function ``make-sparse-keymap`` creates an empty keymap - we will fill this keymap with the menu items later. - -You should be quite confused by the terminology now. We are creating *menus* and all the functions refer to *keys*. Emacs has a mechanism for handling keyboard events. All the other user input mechanisms (mouse events, menus, toolbar buttons, etc, etc) are all extensions of key-handling mechanisms. Hence the fact that all these things are configured by *key* related functions. - -The menu we have just created is in the wrong place really. The standard Emacs menus are: - -* *File* -* *Edit* -* *Options* -* *Buffers* -* *Tools* - -These constitute the *global* menu bar. In addition there is the *Help* menu - this is the *final items* menu. The Emacs convention is that user or mode-specific menus appear in the middle - that is to say to the right of the global menus and to the -left of the final items menu. - -We can make our menu do that by changing the definition from ``define-key`` to ``define-key-after``. - -Now lets make a proper menu. Type the following into your ``.emacs`` file and re-evaluate the buffer: - -| ``(define-key-after global-map [menu-bar omar]`` -| ``(cons "Omar's Menu" (make-sparse-keymap "Omar")))`` -| ``(define-key global-map [menu-bar omar omar-hip]`` -| ``'(menu-item "Hip" omar-hip`` -| ``:help "Hip, yeah!"))`` -| ``(define-key global-map [menu-bar omar separator-replace-tags]`` -| ``'(menu-item "--"))`` -| ``(define-key global-map [menu-bar omar omar-hotel]`` -| ``'(menu-item "Hotel" omar-hotel`` -| ``:help "Hotel, yeah!"))`` - -Notice how we are adding menu-items down the array ``[menu-bar omar omar-hip]`` and so on and so forth. - ------------------------------------- -Adding New Items To An Existing Menu ------------------------------------- - -Lets bind the two nonce functions to an existing menu. Clear out the menu definition code from your ``.emacs`` file and replace it with this: - -| ``(defvar menu-bar-omar-menu (make-sparse-keymap "Omar's Menu"))`` -| ``(define-key menu-bar-omar-menu [omar-hip]`` -| ``'(menu-item "Hip" omar-hip`` -| ``:help "Hip, yeah!"))`` -| ``(define-key menu-bar-omar-menu [separator-omar-1]`` -| ``'(menu-item "--"))`` -| ``(define-key menu-bar-omar-menu [omar-hotel]`` -| ``'(menu-item "Hotel" omar-hotel`` -| ``:help "Hotel, yeah!"))`` -| ``(define-key menu-bar-edit-menu [omar]`` -| ``(list 'menu-item "Omar Menu" menu-bar-omar-menu))`` - -Lets step through it line by line. The first line defines a new variable ``menu-bar-omar-menu``. Note that it has a conventional name. It is part of the *menu* system so it has the prefix ``menu-bar-``. The value of this variable is set to a *sparse keymap*. The entire input management system is built around datatypes called *keymaps*. A *sparse* keymap is just an empty unitialised one. - -The next three lines add elements to the sparse keymap. The first and third items are normal menu items, the second is a separator. - -The ``define-key`` operator defines a key: - -* the first parameter it takes is the keymap to which the key is added -* the second is an array with the function name the menu item is bound to -* the third item is the value that the ``menu-item`` operator returns (which is why the third expression is quoted) - -The ``menu-item`` expression takes 3 parameters: - -* the string that appears in the menu -* the function that is associated with the menu -* the final parameter is a property list (ie 2 elements) containing the constant variable ``:help`` and the help string which appears as the tooltip on the menu - -Notice how we built this menu in a different way - creating a new keymap, adding elements into it, and finally sticking the new keymap into a keymap ``menu-bar-edit-menu`` which is already bound into the global-map. - ------------------- -Keyboard Shortcuts ------------------- - -Keyboard shortcuts are automatically added to menus if they exist. To try this out bind one of the functions to a key combination. Add a key binding to ``.emacs`` and revaluate the buffer. - -``(global-set-key [f5] 'omar-hip)`` - -When you look at the menu now you should see the keyboard shortcut ```` alonside the menu item *Hip*. - ---------------------- -What You Have Learned ---------------------- - -You have seen how to add basic menu items which bind to functions. - ------------------- -Additional Reading ------------------- - -There is a section on `Keymaps`_ in the *Introduction To Emacs Lisp* Manual - it includes a section on menu manipulation. - ----------------- -Extra Activities ----------------- - -You can alter the layout of your menus with a variety of `Menu Separators`_ create a new menu with some swanky separators. - -We have build menus with single items - can you build sub-menus and sub-sub-menus? - -.. _Keymaps: http://www.gnu.org/software/emacs/emacs-lisp-intro/elisp/Keymaps.html#Keymaps - -.. _Menu Separators: http://www.gnu.org/software/emacs/elisp/html_node/Menu-Separators.html#Menu-Separators diff --git a/rsts/lesson-4-4.rst b/rsts/lesson-4-4.rst deleted file mode 100644 index 27439c4..0000000 --- a/rsts/lesson-4-4.rst +++ /dev/null @@ -1,45 +0,0 @@ -=========================================== -Lesson 4-4 - Adding Buttons To The Tool-bar -=========================================== - -**Prerequesite:** this lesson presumes you know how to use the ``.emacs`` file as outlined in Lessons 4-1 and 4-2. - ------------- -Introduction ------------- - -Adding buttons to the tool-bar is conceptually similar to adding menu items - binding in a 'non-key' keymap to the ``global=map``. - -Before you do it you will need to create a new button image. Emacs buttons are stored in the directory ``usr/share/emacs/23.1/etc/images/``. Copy one out to a directory under your home directory. Fire up the Gimp, edit the image and resave it as ``omar.xmp``. Sudo to root and copy the new icon back to ``usr/share/emacs/23.1/etc/images/``. - -We will use the functions ``omar-hip`` and ``omar-hotel`` which we defined for the previous lesson. - -------------------------- -The Basics Of The Toolbar -------------------------- - -Add the following line to your ``.emacs`` file and re-evaluate the buffer: - -| ``(define-key global-map [tool-bar omar-button]`` -| ``'(menu-item "Hotel" omar-hotel`` -| ``:help "OMG Omar!"`` -| ``:image (image :type xpm :file "omar.xpm")))`` - -We are binding in a ``menu-item`` onto the tool-bar - the ``menu-item`` has a paired-list with an image description. - ---------------------- -What You Have Learned ---------------------- - -You have learned: - -* where tool-bar icons are -* how to edit them -* how to bind them in - ----------------- -Extra Activities ----------------- - -The tool-bar button we created was added at the start of the tool-bar. How would you add it to the end of the toolbar? - diff --git a/rsts/lesson-5-1.rst b/rsts/lesson-5-1.rst deleted file mode 100644 index 4a298e3..0000000 --- a/rsts/lesson-5-1.rst +++ /dev/null @@ -1,102 +0,0 @@ -=========================== -Lesson 5-1 - Emacs In Files -=========================== - ------------- -Introduction ------------- - -So far we have created emacs functions in the ``.emacs`` file and attached that to menu-bar and the like. This is a bit sub-optimal. To use eLisp properly we should package up functionality into files and make it easy for them to be added to emacs. - -Emacs loads files from various libraries. It used a global variable called ``load-path`` to work out where to load them from. - -You can look at the current value of that global variable in the \*scratch\* buffer by evaluating (type in the text and type *[Control][j]* at the end): - -``load-path`` - -Your install of emacs will dump out loads of directories: - -``("/usr/share/emacs23/site-lisp/thailatex" "/usr/share/emacs23/site-lisp/latex-cjk-thai" "/usr/share/emacs23/site-lisp/latex-cjk-common" "/usr/share/emacs23/site-lisp/dictionaries-common" "/etc/emacs23" "/etc/emacs" "/usr/local/share/emacs/23.1/site-lisp" "/usr/local/share/emacs/site-lisp" "/usr/share/emacs/23.1/site-lisp" "/usr/share/emacs/23.1/site-lisp/dictionaries-common" "/usr/share/emacs/23.1/site-lisp/latex-cjk-common" "/usr/share/emacs/23.1/site-lisp/latex-cjk-thai" ...)`` - -For a shared production package (ie one that everyone on a particular machine will need access to) the install directory would be somewhere in the shared path space (ie a directory like ``/usr/share/emacs23/site-lisp/``). The convention is that there are ``site-lisp`` directories for all versions of Emacs as well a for specific versions. Upgrades of the base Emacs operator can cause some packages to fail. - -For this lesson we will store our eLisp files locally. Conventionally this is done in a directory called ``.emacs.d``. Best practice says that we don't not add ``.emacs.d`` to the ``load-path``, but we can create a sub-directory under that and add it. - -Create a subdirectory called ``omars-dir`` in ``~/.emacs.d/`` and inside that create a file called ``myomar.el``. - -Add versions of our old favourite functions to ``myomar.el`` - -| ``(defun omar-hip ()`` -| ``(interactive)`` -| ``(message "hip, hop, don't stop"))`` - -| ``(defun omar-hotel ()`` -| ``(interactive)`` -| ``(message "hotel, motel, holiday inn"))`` - -In order to make this available to us we need to add the path to ``load-path``. This is done in our ``.emacs`` file. - -``(add-to-list 'load-path "~/.emacs.d/omars-dir")`` - -Re-evaluate the ``.emacs`` buffer and then switch to the scratch buffer and evaluate ``load-path`` - our directory should now be the first path in the list. - --------------- -Using Our File --------------- - -We have our new directory in the *load-path* we have our file in that directory. Is that enough? - -Quit Emacs and restart (thus losing all our history and defined functions). Our new directory should still be in the *load-path*; but will the code be loaded? - -Emacs has an interactive command for executing interactive functions called execute-extended-command. It is bound to the key combination *[M-x]* so simply type that and the focus will switch to the mini-buffer and wait for you to enter the name of the command you want to run. Stick in ``omar-hotel``. Your attempt to run it should fail. - -Providing code in a searchable path isn't enough. You need to add a line to the ``.emacs`` file telling it to load our new file, and another line in the file itself to identify what it is that the file is providing. - -To make life simpler we are going to call the features that our ``myomar.el`` file provides the same base name as the file, ie ``myomar``. - -To get this to autoload we add the following line to our ``.emacs`` file after the line where we have added ``~/.emacs.d/omars-dir/`` to the ``load-path``: - -``(require 'myomar)`` - -and we add this line at the top of ``myomar.el``: - -``(provide 'myomar)`` - -Now if we quite Emacs and restart it and the use the *[M-x]* trick with ``omar-hip`` the function will execute. - -------------------- -Our Execution Model -------------------- - -This is the execution model we will use from now on: - -* create a custom file or files in a standard directory -* edit ``.emacs`` to run an initialisation function - -The initialisation function will do a number of things: - -* set up the global environment -* change menus, tool-bars and key bindings -* load the code that is needed - -Usually this is done conditionally via hooks. The classic route is a *major-mode* which is triggered by editing files with a certain file type. Later on we will create our own major mode for *omar*. When files whose names match ``*.omar`` are loaded a new mode with menus, tool-bar buttons and key bindings will *magically* appear. - -On starting Emacs our ``.emacs`` file will bind a variety of functions such that Emacs runs them when a file that matches ``*.omar`` is edited. These functions will load our modules as needed and dynamically customise Emacs. - ---------------------- -What You Have Learned ---------------------- - -You have learned: - -* the basics of including code -* how Emacs looks for modules -* how to load some custom code into Emacs at startup - ------------------- -Additional Reading ------------------- - -There is a slightly more to loading code in eLisp which is descriped in the `Loading Code`_ section of the eLisp Reference Manual. - -.. _Loading Code: http://www.gnu.org/software/emacs/emacs-lisp-intro/elisp/How-Programs-Do-Loading.html#How-Programs-Do-Loading diff --git a/rsts/lesson.template b/rsts/lesson.template deleted file mode 100644 index 9cc9e28..0000000 --- a/rsts/lesson.template +++ /dev/null @@ -1,20 +0,0 @@ -================================ -Lesson -================================ - -:You Type: -:Result: - ---------------------- -What You Have Learned ---------------------- - ------------------- -Additional Reading ------------------- - ----------------- -Extra Activities ----------------- - - diff --git a/rsts/other-formats.rst b/rsts/other-formats.rst deleted file mode 100644 index 932dab5..0000000 --- a/rsts/other-formats.rst +++ /dev/null @@ -1,11 +0,0 @@ -============= -Other Formats -============= - ---- -PDF ---- - -This book is also available as a `PDF`_. - -.. _PDF: http://learn-elisp-for-emacs.org/files/Learn-eLisp-For-Emacs.pdf diff --git a/rsts/references.rst b/rsts/references.rst deleted file mode 100644 index 3a38ddd..0000000 --- a/rsts/references.rst +++ /dev/null @@ -1,18 +0,0 @@ -========== -References -========== - -The GNU organisation has published a book on programming in eLisp. It is entitled `An Introduction To Programming In eLisp`_. - -There is also a reference manual - the `GNU Emacs Lisp Reference Manual`_. - -There is also a commercially published book `Writing GNU Emacs Extensions`_. - -Where appropriate this book will refer you to these works for further reading. - - -.. _An Introduction To Programming In eLisp: http://www.gnu.org/software/emacs/emacs-lisp-intro/ - -.. _GNU Emacs Lisp Reference Manual: http://www.gnu.org/software/emacs/emacs-lisp-intro/elisp/index.html#Top - -.. _Writing GNU Emacs Extensions: http://astore.amazon.com/hypernumbersc-20/detail/1565922611 diff --git a/rsts/ttd.rst b/rsts/ttd.rst deleted file mode 100644 index d85e155..0000000 --- a/rsts/ttd.rst +++ /dev/null @@ -1,21 +0,0 @@ -============ -Things To Do -============ - --------------------------- -Changes to written lessons --------------------------- - -* need a lesson on arrays (used in menus for lesson 9) - called lesson-6 a for he mo pending reorganisation - -* lesson 9 needs finishing - ------------------------------- -Suggestions for future lessons ------------------------------- - -* needs some lessons on control structures - do/while - eek no for loops - -* needs some more list processing functions - map etc, etc - -* mebbies needs some anonymous function stuff diff --git a/rsts/what.rst b/rsts/what.rst deleted file mode 100644 index 971e51d..0000000 --- a/rsts/what.rst +++ /dev/null @@ -1,21 +0,0 @@ -========================== -What This Book Will Cover? -========================== - ---------- -What's In ---------- - -This book will cover enough eLisp to enable you to: - -* understand ``.emacs`` files -* write your own functions to put in ``.emacs`` files -* create your own Emacs menu's -* write functions that execute on events like opening and closing a file -* attach functions to key strokes to enable you to customise the behaviour of your Emacs - -------------- -What's Not In -------------- - -This book will not teach you enough Lisp to be an proper Lisp developer. diff --git a/rsts/who.rst b/rsts/who.rst deleted file mode 100644 index 8b61bec..0000000 --- a/rsts/who.rst +++ /dev/null @@ -1,29 +0,0 @@ -===================== -Who Is This Book For? -===================== - ---------------- -Target Audience ---------------- - -The target audience for this book is people with some experience of programming in a non-functional programming language: - -* procedural languages like Fortran, Algol, C etc, etc -* object orientated languages like C++, Java, Ruby etc, etc -* scripting languages like PHP, Python, Perl etc, etc - -(I appreciate that these categories probably fail as strict Comp Sci definitions.) - -If you have already mastered a 'conventional' Functional Programming language this book **might not** be for you - there are good books about learning a variety of Lisps out there. Functional Programming languages include: - -* Lisp and it dialects like Scheme, Clojure, Common Lisp (CL) etc, etc -* Erlang -* Haskell - -(Of course the majority of the worlds 'programmers' are end-users who use the functional programming spreadsheet paradigm in Excel, Open Office or, natch, Hypernumbers. This book is not really aimed at end-user FP/spreadsheet 'programmers' either.) - ------------------------------- -How Much Experience Is Needed? ------------------------------- - -If you can write a small programme to do something in a non-functional programming language from scratch then you should be experienced enough. diff --git a/rsts/why.rst b/rsts/why.rst deleted file mode 100644 index bf60fc0..0000000 --- a/rsts/why.rst +++ /dev/null @@ -1,64 +0,0 @@ -========================== -Why Did I Write This Book? -========================== - ----------- -Why eLisp? ----------- - -I am writing this book to lean eLisp myself. I use Emacs every day because it is the IDE of choice for Erlang and I am an Erlang programmer. - -My relationship with Emacs is that of Simson Garfinkel, Daniel Weise and Steven Strassmann to `Unix`_ - I genuinely loathe it. - -Emacs is the most prominent piece of software in the *apostolic* tradition. You are supposed to learn it by being instructed by someone who learnt it by being instructed by someone recursively all the way back to the original authors in a continuous apostolic succession. - -I would fain be the John Knox, the Calvin, the Luther, and hell mend them. - -By writing this book I hope to be able to write eLisp to configure and extend Emacs in my working environment. - ------------------------ -Why Choose This Format? ------------------------ - -I have chosen to use a format based on *Learn X The Hard Way*. That format is specifically aimed at writing books for non-programmers. My target audience is programmes with no functional programming experiences. Funtional Programming Languages in general (and Lisp in particular) are far enough from Object Orientated or Procedural languages that learning then is like starting to programme again - so the *beginners* format is quite appropriate. - -I have not called the book *Learn eLisp The Hard Way* because this slightly hybrid formula would confuse that core brand. - -I occassionally have to dip into eLisp in the form of .emacs files which are executed on startup and are how you configure Emacs to do specific stuff for your particular requirements. - -One of the reasons why the *Learn X The Hard Way* books work is that the format of forcing people to type in code is a great way to teach them how to read the syntax. eLisp still looks like line noise to me and I have been programming since the late 70s in languages as diverse as Fortran, VB, C++, Java, Perl, Python, PHP, Ruby and Erlang. Writing this book has been a good way to learn how to *read* eLisp for me, and I hope it will work for the readers. - -The transition from Fortran to the Obect Orientated paradigm of C++ was enormously painful. The shift from the OO paradigm (Ruby was my language *de jour* then) to functional programming in the form of Erlang was also horrendous. - -I may be wrong, but I think that many experienced programmers who have no previous exposure to functional programming would benefit from a pretty brutal beginners style book about eLisp. - -I have copies of `On Lisp`_ by Paul Graham and `Common Lisp A Gentle Introduction To Symbolic Computing`_ but have never been able to learn Lisp because of the very basic problem that Zed Shaw identified in `his article`_ on *How To Write A LxTHW* - I could never work out how to get to a basic working shell to type the code examples into. It's not that I didn't try, its just that after a summer of trying to start learning Lisp I had gotten nowhere. If you think that that's my fault, then it falls to you to explain how I managed to learn a brazillian other languages succesfully. - -The other appealing part of this format is that it isn't a reference book. To make clear just how unsuited I am to write a reference book about Lisp, let me enumerate ATTIDNK (All The Things I Do Not Know): - -* the difference between Emacs and XEmacs -* the difference between eLisp and Lisp -* how Common Lisp is related to Clojure or any other Lisp -* how Lisp does package management -* pretty much everything else I would need to know to write a reference book - ----------------------------------- -On Learning Functional Programming ----------------------------------- - -If you just want to learn **a functional programming language** you really should learn Erlang and I recommend `Joe's book`_ or `Franceso and Simon's one`_. - -------------------- -Big Up For Zed Shaw -------------------- - -Zed Shaw? `Who?`_ `Why?`_ - -.. _Unix: http://www.amazon.com/UNIX-Haters-Handbook-Daniel-Weise/dp/1568842031/ref=sr_1_1?ie=UTF8&s=books&qid=1290297419&sr=1-1 -.. _On Lisp: http://www.amazon.com/LISP-Advanced-Techniques-Common/dp/0130305529/ref=sr_1_1?ie=UTF8&qid=1290295941&sr=8-1 -.. _Common Lisp A Gentle Introduction To Symbolic Computing: http://www.amazon.com/Common-Lisp-Introduction-Symbolic-Computation/dp/0805304924/ref=sr_1_8?s=books&ie=UTF8&qid=1290296197&sr=1-8 -.. _his article: http://sheddingbikes.com/posts/1288945508.html -.. _Joe's book: http://www.amazon.com/Programming-Erlang-Software-Concurrent-World/dp/193435600X/ref=sr_1_2?s=books&ie=UTF8&qid=1290296292&sr=1-2 -.. _Franceso and Simon's one: http://www.amazon.com/ERLANG-Programming-Francesco-Cesarini/dp/0596518188/ref=sr_1_1?s=books&ie=UTF8&qid=1290296292&sr=1-1 -.. _Who? : http://www.zedshaw.com/ -.. _Why? : http://sheddingbikes.com/posts/1288945508.html