When is 'require' required?

Discussion of Common Lisp
Post Reply
lispamour
Posts: 18
Joined: Wed Jun 02, 2010 12:29 am

When is 'require' required?

Post by lispamour » Sat Dec 25, 2010 10:11 pm

Hello all! I've been away from this board for some time. Last time, I was in the middle of learning lisp by reading PCL. I had gotten about 2/3 of the way through, before I realized that I didn't really like the style of the book. So I switched to Paul Graham's ACL, and worked through all the exercises in each chapter. For Lisp beginners, I think I would recommend ACL over PCL: ACL is written very well and could be used as a textbook for an introductory class, while PCL seems somewhat scattershot and unfocused with too much emphasis on explaining a large set of APIs.

Right now, I'm in the middle of reading On Lisp, which is a good book, but quite a bit dryer than ACL. The lack of exercises and practice problems really affects the exposition of the material. I'm also practicing writing some Cocoa programs in Lisp using Clozure's Cocoa bridge. Here, I've encountered a simple problem, which I can't seem to work around.

To get the Cocoa bridge working, when I start up Clozure, I first have to type

Code: Select all

(require :nib)
in my Clozure Listener at the toplevel prompt.

I then load and compile the source file helloworld.lisp which loads a Cocoa NIB file called hello.nib that I created using Interface Builder

Code: Select all

(defpackage :hello-world
  (:export main))

(in-package :hello-world)

(require :nib)   ; Where does this go?

(defun main ()
  (iu:load-nibfile (truename "ip:HelloWorld;hello.nib")))
and execute in the Listener

Code: Select all

(hello-world:main)
Suppose, though, I want to avoid having to type (require :nib) in the Listener, and somehow have that command get incorporated into the helloworld.lisp source file, so that I can simply load and compile helloworld.lisp in a single step, before executing (hello-world:main) in the Listener; how do I go about doing this?

If I leave out the (require :nib) altogether, then I get the error message:

Code: Select all

Read error between positions 83 and 124 in helloworld.lisp.
> Error: Reader error on #<BASIC-FILE-CHARACTER-INPUT-STREAM ("helloworld.lisp"/8 ISO-8859-1) #x302001546C3C>, near position 124, within " ()
>          (iu:load-nibfi":
>        Reference to unknown package "IU".
> While executing: CCL::SIGNAL-READER-ERROR, in process Listener(6).
> Type cmd-. to abort, cmd-\ for a list of available restarts.
> Type :? for other options.
1 > 
Evidently, the NIB package contains the definitions for the iu:load-nibfile function and the like. I've tried including (require :nib) within the helloworld.lisp source file, before and also after the (defpackage :hello-world) specification, but I still get the same type of error message.

How should I organize my source files in lisp? Do I need defsystem or asdf-install to load in package prerequisites, or can this be done without these tools?

ramarren
Posts: 613
Joined: Sun Jun 29, 2008 4:02 am
Location: Warsaw, Poland
Contact:

Re: When is 'require' required?

Post by ramarren » Sun Dec 26, 2010 2:22 am

REQUIRE is deprecated. This doesn't actually matter that much, since a new version of CL standard is unlikely, which means it won't be removed, but the reason why it is deprecated is because it is underspecified. It is fine to use from the listener, but do not use it in code for anything more than toy examples, and even then it is better to just use ASDF or Quicklisp (which actually uses ASDF, but will also download systems it knows from the internet if they are not installed).

The problem you encountered with REQUIRE, which would actually be the same if you included ASDF/Quicklisp loading function directly in the file, is because they are functions. It would work if you LOADed the file, which evaluates expressions in the file one by one, but compilation just compiles the file without executing it, which means that REQUIRE side effects do not occur. You can make the dependencies loading occur at compile time as well using EVAL-WHEN.

That is generally not recommended. Usually you would just define a system definition file using ASDF. There is quickproject, which will create a project skeleton quickly.

nuntius
Posts: 538
Joined: Sat Aug 09, 2008 10:44 am
Location: Newton, MA

Re: When is 'require' required?

Post by nuntius » Sun Dec 26, 2010 8:06 pm

I personally believe the semantics of REQUIRE were much better than those of ASDF/Quicklisp load operations. The former is an underspecified API; the latter is an imperfect implementation that couples too much stuff.

EVAL-WHEN is just fine for a single-file app. A loader file (or ASDF system definition) are generally standard for larger projects. ASDF's main benefits over a plain loader file are portably finding libraries and compiling files before loading. As the current leader in free CL land, ASDF compatibility is also good when releasing a project.

lispamour
Posts: 18
Joined: Wed Jun 02, 2010 12:29 am

Re: When is 'require' required?

Post by lispamour » Wed Dec 29, 2010 10:00 pm

Ramarren wrote:
The problem you encountered with REQUIRE, which would actually be the same if you included ASDF/Quicklisp loading function directly in the file, is because they are functions. It would work if you LOADed the file, which evaluates expressions in the file one by one, but compilation just compiles the file without executing it, which means that REQUIRE side effects do not occur. You can make the dependencies loading occur at compile time as well using EVAL-WHEN.
Thanks. I looked through some sample code, and found an example of EVAL-WHEN

Code: Select all

(eval-when (:compile-toplevel :load-toplevel :execute)
  (require :nib))
which works for the Clozure code.
That is generally not recommended. Usually you would just define a system definition file using ASDF. There is quickproject, which will create a project skeleton quickly.
I'm intrigued by this. Can you show an example of an ASDF file which accomplishes the same as the EVAL-WHEN code?

nuntius
Posts: 538
Joined: Sat Aug 09, 2008 10:44 am
Location: Newton, MA

Re: When is 'require' required?

Post by nuntius » Wed Dec 29, 2010 10:47 pm

An ASDF load-op put inside your source file will have the same issues as require; it will need to be in an EVAL-WHEN block.

The win is to move these dependencies out of the source file and into a loader file. ASDF is a framework for writing such files.

Post Reply