Learning Lisp

The Road To Lisp

Beginning of Bag Project

Posted by j1p on May 5, 2006

So I started working on implementing the Bag project in Lisp.

I've got most of the basics of the class done, in the following code:

 (defclass bag ()
  ((itemlist
    :accessor get-bag
    :initform ()
    :initarg :itemlist
    :documentation "A list of items in the bag")
   (max-weight
    :accessor get-bag-max-weight
    :initform 20 :type integer
    :initarg :max-weight
    :documentation "The maximum weight that the bag can contain")))

(defvar *list-of-bags*
  '()
  "List of Bags")

(defun make-bag (&optional (itemlist ())(max-weight 20))
  "Makes an instance of class bag and pushes it into *list-of-bags*"
  (setf *list-of-bags*
    (cons
     (make-instance 'bag :max-weight max-weight :itemlist itemlist)
     *list-of-bags*)))

(defmethod bag-weight ((bag bag))
  (eval (cons '+ (get-bag bag))))

(defmethod add-item ((bag bag) (item integer))
  (cons item (get-bag bag)))

I still need to implement the function to go through a file, and put all integers in the file into the first bag that it will fit in, and the function to print out the bag. I'm not familiar with reading from files in Lisp, but I assume it should be relatively simple. I've skimmed through the chapter on files and file-io of Practical Common Lisp, and it mentions two functions, read-char, read-line, and read, and it looks like the one that will be most helpful to me will be read. The loops to go through and print/pack the bags will probably use a FIRST of a NTHCDR of *list-of-bags*.

Please, if you have any suggestions/fixes for what I have, let me know, im just learning and don't want to start up any bad habits. For example, I haven't exactly seen the reason to have defgeneric's instead of defmethod's, but I'm sure there is one.

Posted in Bag Project, Lisp | 5 Comments »

Re: Don’t Study, Do.

Posted by j1p on May 3, 2006

I think the Lisp bug has bitten me.

After an uneventful morning, consisting of daydreaming through class and a quick lunch, I rushed to get to work on time. Now, I really do enjoy working here, I tend to look forward to the 3 hours a day I get to spend on a computer, hacking away(normally at html, ColdFusion, or CSS) without being interrupted by neighbors, etc, but I'd rather be doing some other things. I get to work, and to my surprise my 3 co-workers all seemed to have taken the day off. I got through all the webteam stuff in 30 minutes, so I figure I might as well read up a bit on Lisp.

While browsing technorati, I came across a post, How To Advance in InfoSec: Don't Study, Do. While this post has little to do with Lisp in general, it is extremely relevant to what I'm doing here. Here's a quote straight from the post(actually the only part that even mentions Lisp):

Don’t read three books in a row on Lisp. Take a program you’ve written in a previous language and redo it in Lisp. Use your three books as a reference.

That was exactly what I was doing, I checked out 3 books on Lisp, and was reading through them like a tutorial. I need some real experience working with Lisp, making it do something I want it to do, not just what they tell me it can do.

So, I'm going to try to rewrite my first CS102 assignment from Java to Lisp. Here are the details as posted by my professor.

Specifications

  1. You need to create a class called Bag that contains an array of items. You may assume that the items are all integers (the weights of the various items in pounds) and that the capacity of the bag is twenty pounds. Your private variables will include this array of integers, a count of how many items are in the array, and any other data you feel you will need. The methods for the class should include the any constructors that you will need, any query functions (such as examining the weight currently held in the bag), and a method to insert a new item into the bag. You may, of course, include any other methods that you feel you need.
  2. Your input will be a list of integers. You may read it in from the screen or from a text file (a text file is probably easier). If you read it in from a text file, be sure to prompt the user for the name of the file that is to be used for the input. If you input the weights from the screen, be sure to give the user sufficient prompts. If any bad data (such as a character) is in the input, ignore it and proceed to the next input.
  3. If your input is: 15 13 4 9 6 1 , for example, your output should be of the form:

    Bag 1: 15 4 1

    Bag 2: 13 6

    Bag 3: 9

  4. You should create a second class for packing the bags that contains a method called pack(), which reads in your data and packs them into the bags. You will need a method to print your results, which calls a print method in the bag class. Your main method should be very short, essentially calling pack() and print().

  5. Be sure to include comments in all of your methods

Alright, so this looks like it is going to be much simpler in Lisp than in Java, for the fact that practically all it is is list manipulation, Lisp's specialty. I have no need to make the Bag class contain an array of items, it can simply be a List of items in Lisp.

To make this work as close to the specifications as I can, I am going to need to learn more about CLOS, though most of the methods for the classes look like they will be pretty simple.

I have a 10 page paper to write for class tomorrow, but I'll probably hold that off until after I get home and use SLIME to write up some preliminary functions that will help for the final Lisp-version of Bag.

Posted in Bag Project, Learning, Lisp | Leave a Comment »

Lisp Web Applications

Posted by j1p on May 3, 2006

After a bunch of reading on implementations of Lisp solutions, and thinking a bit about how I would benefit the most from learning Lisp, I have decided I should look at it in the perspective of web-based applications.

It seems that any program I could develop(not that I am in any way ready to develop a distributable program) would be limited to Linux machines, which is not exactly the best way to reach users. I will, of course, learn the basics that would necessary to develop these applications, but I think I will take on the web-based perspective.

After realizing this, I looked at a few solutions for Lisp on the web. Things such as the UnCommon Web, TBNL, and Araneida. You may remember the question I posed at the end of the last post, about which Common Lisp implementation a beginner Lisper(is that the right term?) should use. With these solutions being some of the most common possibilities, I chose SBCL, for a variety of reasons. For one, these Lisp Web Servers seem to integrate very well with SBCL. Another reason is SBCL seems a powerful, popular CL implementation, with features such as threading.

I plan to set up some kind of local test server running one, or a combination of these solutions on my Ubuntu box in the next two weeks, as my semester at University is ending. Speaking of school, after next year I will have fulfilled the prerequisites to the AI and Robotics classes, both of which touch on Lisp, and are taught by a very knowledgeable professor.

Now, back to my road to learning the skills I actually need to complete any of my various dreams of hacking in Lisp:

At work this morning I sat down and read through the first few parts of The CLOS Perspective, which was my first introduction to object orientated programming in Lisp. Unfortunately, the book is not very focused on "teaching" how to program with CLOS, but by the few code snippets in the first few sections, it looked pretty simple, and similar to defining functions, with a little more added. I'll have to find a better book on teaching CLOS, or an online tutorial of the sort.

I've read through the parts of Steele's book that correspond to the points I've learned through Winston and Horn's Lisp. In Lisp, I've finished Chapters 2 and 3. I've learned all about association lists, some more advanced mathematical functions (round, expt, sqrt, abs, max, min) by finishing chapter 2, and believe I've mastered the (simple) list manipulation functions.

Here are the rest of the sample problems from Chapter 2:

Problem 2-8: Evaluate the following forms

  1. (length '(plato socrates aristotle))
  2. (length '((plato) (socrates) (aristotle)))
  3. (length '((plato socrates aristotle)))
  4. (reverse '(plato socrates aristotle))
  5. (reverse '((plato) (socrates) (aristotle)))
  6. (reverse '((plato socrates aristotle)))

Problem 2-9: Evaluate the following forms

  1. (length '((car chevrolet) (drink coke) (cereal wheaties)))
  2. (reverse '((car chevrolet) (drink coke) (cereal wheaties)))
  3. (append '((car chevrolet) (drink coke)) (reverse '((car chevrolet) (drink coke)))) — hard to format correctly, sorry!

Problem 2-10: Evaluate the following forms

  1. (/ (+ 3 1) (- 3 1))
  2. (* (max 3 4 5) (min 3 4 5))
  3. (min (max 3 1 4) (max 2 7 1))

Chapter Two Summary (main points)

  • LISP means symbol manipulation
  • LISP procedures and data are symbolic expressions
  • Lists are like bowls
  • FIRST and REST take lists apart
  • Quoting stops evaluation
  • Some "old timers" use CARs and CDRs
  • SETF assigns values to symbols
  • SETF accepts multiple symbol-value pairs
  • Certain atoms evaluate to themselves (t and nil)
  • CONS, APPEND, and LIST construct lists
  • CONS, APPEND, and LIST do not alter symbol values
  • NTHCDR, BUTLAST, and LAST shorten lists
  • LENGTH and REVERSE work on top-level elements
  • ASSOC looks for indexed sublists
  • LISP offers integers, ratios, and floating point numbers, among others
  • A few primitives for numbers round out a basic repertoire

Chapter 2 was basically a run-down of what I had already learned through the first few chapters of online tutorials, so it didn't challenge me much, and Chapter 3 was also mostly the same. Chapter 3, titles Procedure Definition and Binding, introduced functions, and the Lisp primitives; defun and let.

I don't have much time to cover Chapter 3 tonight, as I have 3 papers and 4 finals in the next two weeks, and its getting late. I'll try to post about chapter 3 and anything I read tomorrow by Thursday.

A question for you readers(if you exist): Which setup of a Lisp webserver would you recommend me. I have set up a few Apache2 servers before, so I have some experience in the area, but would prefer a not-impossible set-up, and decent feature-set. As I am just learning, I obviously don't need features that would only benefit the most advanced of applications, but it would be nice to have some power while building my skills.

Answers to sample problems in last post(please correct me if I get some of the wrong, I am just learning):

Problem 2-1:

  1. Atom
  2. List(of the atoms THIS, IS, AN, ATOM)
  3. List(of the atoms THIS, IS, AN, EXPRESSION)
  4. Neither(ill formed parenthesis)
  5. List(of the atoms LIST, 3)
  6. List(of the atom /, and Lists (+ 3 1) (- 3 1)
  7. Neither(ill formed parenthesis)
  8. List(of a List of a Empty List)
  9. List(of two empty Lists)
  10. Neither(closing parenthesis don't match opening parenthesis)
  11. Neither(ill formed parenthesis)
  12. Neither(no closing parenthesis)

Problem 2-2

  1. P
  2. (K P H)
  3. (A B)
  4. (C D)
  5. (C D)
  6. (B)
  7. (D)
  8. B

Problem 2-3

  1. D
  2. E
  3. (A B)
  4. This gave me an error when I put it into SBCL, The value REST is not of type LIST.
  5. FIRST
  6. (FIRST (FIRST (REST (REST ((A B) (C D) (E F))))))

Problem 2-4 (assume *list* is set to the list in question.

  1. (first (rest (rest *list*)))
  2. (first (first (rest *list*)))
  3. (first (first (rest (rest *list*))))
  4. (first (first (first (rest (rest *list*)))))
  5. (first (first (rest (rest *list*))))
  6. (first (rest (first *list*)))

Problem 2-5

  1. (A B C)
  2. ((A B C) NIL)
  3. ((A B C))

Problem 2-6

  1. (HAMMER SCREWDRIVER)
  2. (PLIERS HAMMER SCREWDRIVER)
  3. (HAMMER SCREWDRIVER)
  4. (PLIERS HAMMER SCREWDRIVER)
  5. (PLIERS HAMMER SCREWDRIVER)
  6. (SAW WRENCH PLIERS HAMMER SCREWDRIVER)
  7. (PLIERS HAMMER SCREWDRIVER)
  8. (SAW WRENCH PLIERS HAMMER SCREWDRIVER)
  9. (SAW WRENCH PLIERS HAMMER SCREWDRIVER)

Problem 2-7

  • (NIL)

Posted in Learning, Lisp | 2 Comments »

Use the Library

Posted by j1p on April 24, 2006

Instead of just using online resources like Peter Seibel's Practical Common Lisp [1], I headed down to my University's Library and took out 3 books on Common Lisp. I was originally looking to get a copy of Paul Graham's ANSI Common Lisp[2], but they didn't have it.

So instead I picked up Guy L. Steele's Common Lisp: The Language[3], Winston and Horn's Lisp[4], and Andreas Paepcke's Object-Oriented Programming: The CLOS Perspective[5]. These books may be a bit outdated, but should be good for getting my feet wet with Common Lisp. So far I've only read through Lisp's 1st chapter, and half of the second chapter. The first chapter involved no code, only explanations of lists, uses of Lisp in a real-world environment, why to learn Lisp(especially Common Lisp), and debunked a few myths about Lisp. Nothing I haven't read elsewhere.

The second chapter finally got into real code. It introduced primitives, procedures provided by the Lisp implementation, like arithmitic operators, cons, list, append, first(car), rest(cdr), and setf. Further along in the chapter it goes into push, nthcdr, butlast, last, length, reverse, ASSOC, round, exp, expt, and so on.

For anyone also learning I'll provide the sample problems I've come across so far:

Problem 2-1: Identify if the following are atoms, lists, or neither:

  1. ATOM
  2. (THIS IS AN ATOM)
  3. (THIS IS AN EXPRESSION)
  4. ((A B) (C D)) 3 (3)
  5. (LIST 3)
  6. (/ (+ 3 1) (- 3 1))
  7. )(
  8. ((()))
  9. (() ())
  10. ((())
  11. ())(
  12. ((ABC

Problem 2-2: Evaluate the following forms:

  1. (first '(p h w))
  2. (rest '(b k p h))
  3. (first '((a b) (c d)))
  4. (rest '((a b) (c d)))
  5. (first (rest '((a b) (c d))))
  6. (rest (first '((a b) (c d))))
  7. (rest (first (rest '((a b) (c d)))))
  8. (first (rest (first '((a b) (c d)))))

Problem 2-3: Evaluate the following forms:

  1. (first (rest (first (rest '((a b) (c d) (e f))))))
  2. (first (first (rest (rest '((a b) (c d) (e f))))))
  3. (first (first (rest '(rest ((a b) (c d) (e f))))))
  4. (first (first '(rest (rest ((a b) (c d) (e f))))))
  5. (first '(first (rest (rest ((a b) (c d) (e f))))))
  6. '(first (first (rest (rest ((a b) (c d) (e f))))))

Problem 2-4: Write a sequence of first's and rest's that will return the symbol PEAR out of the following expressions. (not the list containing only the atom PEAR, (PEAR), but only the symbol PEAR, PEAR)

  1. (apple orange pear grapefruit)
  2. ((apple orange) (pear grapefruit))
  3. (((apple) (orange) (pear) (grapefruit)))
  4. (apple (orange) ((pear)) (((grapefruit))))
  5. ((((apple))) ((orange)) (pear) grapefruit)
  6. ((((apple) orange) pear) grapefruit)

Hint: First returns a element, while Rest always returns a list.

Problem 2-5: Evaluate the following forms:

  1. (append '(a b c) '( ))
  2. (list '(a b c)'( ))
  3. (cons '(a b c) '( ))

Problem 2-6: Evaluate the following forms in the order given

  • (setf tools (list 'hammer 'screwdriver))
  • (cons 'pliers tools)
  • tools
  • (setf tools (cons 'pliers tools))
  • tools
  • (append '(saw wrench) tools)
  • tools
  • (setf tools (append '(saw wrench) tools))
  • tools

Problem 2-7: Evaluate the following form:

  • (cons (first nil) (rest nil))

I had some trouble on some parts of 2-4, where my sequences would result in the list containing the symbol pear, (PEAR), but that's easily solved by throwing another first on the front of the sequence.

As I continue reading I'll try to keep putting in the example problems, as long as they don't get too involved, and the answers will be in the next post.

One of the problems, well, maybe not so much a problem, but a point of conflict I have run into is which implementation of Common Lisp I should use. Currently, I am running Ubuntu Linux, so I have lots of options to choose from: SBCL, CMUCL, CLISP, Allegro Personal 7.0, and more. Perhaps my next post will deal with the differences between different implementations, in the eyes of a "newbie."

Posted in Learning, Lisp | 10 Comments »