peter
peter

Reputation: 177

Is It Better Practice To Use package-name:symbol In Code Or :use :package-name In A DEFPACKAGE?

This is I suspect, a matter of style and/or personal taste but I thought I'd ask anyway.

I have been in the habit of defining packages thus:

(defpackage :wibble
  (:use :cl :drakma)
  (:export :main))

Once I have executed IN-PACKAGE (:wibble, in this case), I can then use the symbols in DRAKMA unadorned:

(http-request ...

Then I recently read that seasoned Lisp hackers would rather not :use but:

(drakma:http-request ...

Just wondered what the consensus of opinion was on here and whether there were any pros or cons (not that type of CONS :) ) either way?

Cheers,

Peter

Upvotes: 6

Views: 577

Answers (4)

Svante
Svante

Reputation: 51501

As a rule of thumb, I :use packages that extend the general language, but use qualified symbols for packages that have some special application. For example, I'd always :use alexandria, but refer fully qualified to symbols from Hunchentoot. When in doubt, I use qualified names.

Upvotes: 4

Rainer Joswig
Rainer Joswig

Reputation: 139261

Good answers so far.

Another view is that a package and its symbols make up a language. If you think a symbol should be a part of this language, then you should make it available without the need to qualify it with another package - when programming in this language.

For example in the CLIM implementation there is a CLIM-LISP package which sets up the implementation language. It is a variant of the COMMON-LISP package. Then there are packages like CLIM-SYS (resources, processes, locks, ...), CLIM-UTILS (various utilities and extensions of Common Lisp) and CLIM itself. Now in a new package SILICA (an abstract window system) these four packages are used. The implementation of Silica thus is implemented in a language which is built as a union of two languages (the Common Lisp variant CLIM-LISP and the UI commands of CLIM) plus two utility packages which extend CLIM-LISP with some facilities.

In above example it makes sense to use the packages, since they are extending each other to form a new language and the implementation in that new package makes heavy use of those.

If you had a package which needs conflicting packages, then it would not make sense to use them. For example a package could use drawing commands tailored to a GUI and for Postscript output. They would have similar names. Using them both would lead to conflicts. You also want to make clear in the source code for the human reader from where these symbols are coming. Is it a line-drawing command from a postscript or a GTK+ library? Would be great if you can find it out easily - even though the function names are the same.

Upvotes: 6

Xach
Xach

Reputation: 11854

When you use a package, there are a couple subtle ways things might go wrong if the used package changes.

First, the package might export more symbols in the future. If, for example, the package exports a new symbol library:rhombus and you're already using that myapp::rhombus to name something, you are suddenly using the inherited symbol, with all possible attachments (e.g. classes, defuns, macros, etc), with sometimes strange results. If you use qualified symbol names, you will not get any more or any less than the symbols you want.

Second, the package might stop exporting symbols in the future. So if, for example, library:with-rhombus disappears, your call to (with-rhombus (42 42 42) ...) will suddenly get an error for an invalid function call (42 ...) rather than something that points directly to the source of the problem, the "missing" symbol. If you use qualified symbol names, you will get an error along the lines of Symbol WITH-RHOMBUS is not exported from the LIBRARY package which is clearer.

Importing symbols (with :import-from or :shadowing-import-from or import) is not without its own trouble. Importing works on any symbol, regardless of whether it's external or not. So it could be the case that the symbol is now library::rhombus, i.e. not intended for public consumption any more, but importing will still work with no errors.

Which option you use depends on your comfort level with the source package. Do you control it, and you will not make any conflicting changes without thorough testing? Go ahead and import or use to your heart's content. Otherwise, be careful about checking for unintended side-effects as library package interfaces change.

Upvotes: 13

Vsevolod Dyomkin
Vsevolod Dyomkin

Reputation: 9451

This is more a style issue, so it's impossible to categorize it in black and white, but here are the pros and cons:

  1. Using package-qualified symbols.

    Avoids symbol conflicts.

    Allows to clearly distinguish foreign symbols.

    Allows to easily search, replace, copy,... uses of a certain symbol from the external library (for refactoring, extracting the code to some other place etc.)

    Makes code uglier, but only when library names are too long. (For example, I add a nickname re to cl-pprce, and now the code using it is even better, than w/o qualification: think re:scan)

  2. Importing the whole package

    Basically, the opposite of the previous case. But I tend to use it with utility libraries, because using qualified names often beats their whole purpose of making code more concise and clear :)

  3. :import-from package symbol

    This is one option you've forgotten to mention. I think it may be useful, when you use one or too very distinct symbols from a certain package very frequently. It also allows to import unexported symbols.

Upvotes: 6

Related Questions