Log in

Naming functions with keywords

I used to have a collection of miscellaneous utilities in a project named ZPB (after my initials). They weren't functions I used in actual source code, just little REPL conveniences, inspired in part by Rob Warnock's great suggestion to Use the Lisp environment to make your life easier!!

Even though the package prefix was short (zpb), I typed the stuff often enough that the prefix in the repl was annoying, but I didn't really want inherit everything with use-package, either. What to do?

Lately I've taken to sticking the functions in my startup file and naming them after keywords. For example:

(defun :go (&optional (thing *))
  "View THING with some appropriate viewer."
  ;; On my Mac laptop, I use "open" instead.
  (sb-ext:run-program "gnome-open" (list (princ-to-string thing))
                      :search t)

With this in my startup file, I can do something like this:

* (url-of-interest object)

* (:go)
URL is opened in Chrome

These functions are short, easy to type, and always available in any REPL context regardless of the editor settings or current package. In addition to :go, I also have :file-string, :file-vector, :file-lines, :bits, :hex, :make-project, and a few others.

Do you define any shortcuts like this?


I've got a package with an awfully long name and a one-letter nickname ("I" for "interactive).

(i:show-weather) is not much longer than (:show-weather), and the former has an advantage when SLIME completion is used (=always, for me).
Very neat!

I've also recently discovered such possibility and experimented with using it in a certain DSL, but later decided to go for ordinary symbols.
I have
(defun :asd (system)
  (format t "Loading system: ~a~%" system)
  (and (asdf:oos 'asdf:load-op system :verbose nil)

(defmacro :dbg (x &optional tag)
  `(let ((results (multiple-value-list ,x)))
     (format *debug-io* "~&~@[~a ~]~{~s~^, ~}~%" ,tag results)
     (finish-output *debug-io*)
     (values-list results)))

Mine are mostly for debugging.

(:BREAK ) breaks, displays the values, and the returns them.

(:BREAKPOINT ) is a named breakpoint. There are a few associated functions to turn named breakpoints on and off.

There have been others, but those have survived the longest.

Inspiring idea

Under Windows, you can do this:

(defun :go (&optional (thing *))
"View THING with some appropriate viewer."
#+:WIN32 (sb-ext:run-program "cmd" (list "/c" "start" (princ-to-string thing)) :search t)

I also started to experiment with (:mail) via mailto:// but that requires url-encoding of the body text and I'm not sure yet how much stuff I'm willing to pull into my minimal environment.

How about (:tweet) for twitter?

(:cut) to copy to the clipboard?

Perhaps we could start to define a "standard" set that's somehow installable via Quicklisp?

Lot's of possibilities!

zeal couple of useful ones

some :keyword functions I use frequently are :printv (based on printv from gbbopen) and :break , :break/print , :break/inspect etc.

I've always worried that defining functions on keywords was somehow not kosher -- although it never stopped me from indulging myself for the really really useful ones like the above. Is it actually an officially sanctioned practice?

Re: zeal couple of useful ones

I've only heard, anecdotally, of problems on LispWorks, which issues a continuable error when you use a keyword as the name in DEFUN.
(defun :go (&optional (thing *))

Whoa. Keyword-named functions, that makes sense, but using * to provide a default argument? Very slick.