14 October 2009

Learning Lisp

I’m finally done with the basics of Lisp. But being able to finally understand how to use Lisp does not end there. It simply means that there will be more interesting problems to solve in the future and expectations will be high. For this entry, I will be discussing a few things about what I’ve learned about Lisp. I will also be posting source codes from the exercises that I answered and likewise the real-world implementations that I created using Lisp.

I’ve read almost a third of Paul Graham’s On Lisp Book and allow me to summarize it, based on my own pace and understanding, in a nutshell. I will only write important pointers that you might help you understand lisp better. The discussion on the syntax will already be up to you. Don’t worry though since I’ll be posting materials for your reference. :)

Introduction:
Lisp stands for List Processor and was developed by John McCarthy in the late 1950s. The paradigm it follows is Functional Programming. That is, functions are the natural place to begin with. This type of paradigm tells you what it wants to do rather than what to do. Lisp allows you to change the language to suit the solution to the problem. Prototyping and debugging of programs are easier and more interactive. Arguments are also evaluated first before the function is issued since it follows the read, evaluate, and then print cycle. Lastly, Lisp can either be compiled, interpreted, or both. Examples of software created using Lisp are GNU Emacs, Autocad, and Interleaf.

There are a lot of dialects that you can use to program in Lisp. The most popular dialect is Common Lisp. But for the entirety of my Lisp entries, I shall be dealing with Common Lisp syntax unless otherwise stated. For the interpreters that you can use , refer to my previous entry which discusses on how to install the interpreters.

In Lisp, f(x) is written as (f x) since it is Postfix.

eg. cos(0) is written as (cos 0).

In Lisp, there are only 2 kinds of objects:

1. Atoms – symbols, arrays, and other data structures.

* symbols are represented as sequences of characters of reasonable length.

2. Lists – are recursively constructed from atoms. It may contain either atoms or lists, or both.

* “()” or “NIL” is both an atom and a list.
* special atoms: numbers, t, or nil.
* primitive functions: +, -, *, /, exp, expt, log, sqrt, sin, cos, tan, max, min.

Ingredients of an abstract data type:

1. Constructors – forms that create new instances of a data type.

i. cons – allows you to add a member to the front of a list

eg. (cons ‘a ‘(1 2 3)) -> (A 1 2 3)

ii. quote or ‘ – use if you do not wish the interpreter to evaluate.

eg. (setq a 4) = (set ‘a 4) = (set (quote a) 4)

*shorthand commands are called macros.

2. Selectors – returns one of its components, given a composite object out of several components.

i. first or car

eg. (first ‘(1 2 3)) -> 1

ii. rest or cdr

eg. (rest ‘(1 2 3)) -> (2 3)

3. Recognizers – expressions that test how an object is constructed.

Lists versus Sets:
1. Sets are unordered but lists are.

eg. (a b c) and (c b a) are two different lists.

2. An element either belongs to a set or not. There is no notion of multiple occurences. Yet, a list may
contain multiple occurences of the same element.

eg. (a b b c) is a list whilst (a b c) is a set.

Recursions:
1. Linear Recursion – the function may make at most one recursive call from any level of invocation.

eg. factorial.lisp

2. Multiple Recursion – the function definition contains two or more self references.

eg. fibonacci.lisp

3. Structural Recursion – the function checks the structure of the parameter.

eg. recursive-list-length.lisp

Tail Recursion means that when the result of each recursive call is returned right away as the value of the function.

* when implementing linearly recursive functions, you are encouraged to restructure it as a tail recursion after you have fully debugged your implementation.

The implementation of tail recursion is new to me since I don’t(or did not) really bother using this in the 2 years that I’ve been working as a developer. This may have been introduced in my Computer Science classes but was not really given that much attention. So I didn’t bother.

Iterators:

- in higher-order function, mapcar is used and does exactly what mapfirst is intended for.

- *car is used to define first in other dialects and rest was called *cdr in these dialects.

- Common Lisp still supports car and cdr but stick with the more readable first and rest.

Types of Iterators:

1. Generic Iterators – captures the generic logic of iterating through a list.

2. Transformation Iterators – transforming a list by systematically applying a list member that
satisfies a given condition.

eg. repeat-transformation.lisp

3. Filter Iteration – screening out all members that does not satisfy a given condition.

eg. remove-short-lists.lisp

Compiling to executable:

Also, if you want your program to be executable within the commandline, you can issue this command:

(save-lisp-and-die “<executable_file_name>” :toplevel #’<function_name> :executable T)

eg. (save-lisp-and-die “javaphones” :toplevel #’main :executable T)

*please do note that I’m running on Ubuntu 9.04 and I haven’t tested it on other Linux distros.

So far those are the pointers written in my Rutter(Blue Notebook). You can download the resources via torrent or direct download (6.73MB). Also, you can join the mailing list at comp.lang.list. There’s a lot of spam there but there a few, great people who can help you in your Lisp endeavors.

Enjoy! :)

“But no one can read the program without understanding all your new utilities.”

5 October 2009

How To Install Common Lisp on Ubuntu

It’s been nearly two weeks since I started learning Lisp. I must say that before you start doing something, you need to know where to start. As my old friend Confucius told me, “A journey of a thousand miles, begins with a single step.” So there, I’ll be posting here how to get started with Lisp by setting up your own working environment.

Operating System:

I am running Ubuntu 9.04 Jaunty on top of my Windows 7 via Sun VirtualBox. You can download Sun Virtual box here and setup your virtual machine. If you’re already on Ubuntu then that’s fine, leave it as is. After all is being done already, just type the following:

  1. Type ’sudo apt-get install sbcl’ (or alternatively ’sudo apt-get install cmucl’)
  2. Type ’sbcl’ in the terminal. (or alternatively type ‘cmucl’)
  3. You will see an asterisk (*) if you have successfully installed it.
  4. You can also test it by typing, ‘(print “Hello World!”)’ in the terminal.

Example:

ridvan@ridvan-vm:~$ sudo apt-get install sbcl
(you will see some installation messages here, just continue installing)
                      ... ... .... ... ...

ridvan@ridvan-vm:~$ sbcl
This is SBCL 1.0.18.debian, an implementation of ANSI Common Lisp.
More information about SBCL is available at <http://www.sbcl.org/>.

SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses.  See the CREDITS and COPYING files in the
distribution for more information.
* (print "Hello World!")

"Hello World!"
"Hello World!"
*

You can actually choose which interpreter to use, either sbcl and cmucl. The two have pros and cons actually.

For the SBCL (Steel Bank Common Lisp), the advantage is you can make use of the ‘trace’ function properly. The drawback is that some I/O functions don’t seem to behave the way they should be.

Examples:
Farenheit to Celsius converter (f-to-c.lisp).
Power (power.lisp).

I/O functionality:

* (load "f-to-c.lisp")

T
* (f-to-c)

200
Please enter Fahrenheit temperature:
200 degrees Fahrenheit is 93.333336 degrees Celsius
280/3
*

Trace Function:

* (load "power.lisp")

T
* (trace power)

(POWER)
* (power 2 3)
  0: (POWER 2 3)
    1: (POWER 2 2)
      2: (POWER 2 1)
      2: POWER returned 2
    1: POWER returned 4
  0: POWER returned 8
8
*

For the CMUCL (Carnegie Mellon University Common Lisp), the advantage is that the I/O functions are behaving well whilst the ‘trace’ function does not. Even if your code is not tail-recursive, it does not show the step-by-step process of the recursive call.

I/O functionality:

* (load "f-to-c.lisp")

; Loading #p"/home/ridvan/Projects/lisp/f-to-c.lisp".
T
* (f-to-c)

Please enter Fahrenheit temperature: 200

200 degrees Fahrenheit is 93.333336 degrees Celsius
280/3
*

Trace Function:

* (load "power.lisp")

; Loading #p"/home/ridvan/Projects/lisp/power.lisp".
T
* (trace power)

(POWER)
* (power 2 3)

  0: (POWER 2 3)
  0: POWER returned 8
8
*

Now that you’ve seen some of my observations on both interpreters, it really depends to you which one you should use. But if you’re going to ask me, I’d say it depends. It depends on what you wanted to achieve. If you want to trace your recursions, go use sbcl. If you want to have clean and neat inputting, go use cmucl. Personally, I use SBCL more often since I trace my codes more often.

So there, setting up lisp on your working environment is very easy. Enjoy Lisp! :)