All notes tagged with lisp.

July 9, 2024

lisp

Rich Comment Blocks in Common Lisp

In Clojure, “Rich Comment Blocks” serve as both a playground and a log during development. Named after Clojure’s creator, Rich Hickey, these blocks offer a unique approach to REPL-driven development.

Stuart Halloway, in his talk “Running with Scissors,” quipped:

These comments are rich because they provide rich detail about the development process and because they were written by a person named Rich.

Rich Comment Blocks look like this:

(comment
  (println "foo"))

When the program runs, it ignores the top-level form. However, during development, you can evaluate each line individually, making it an invaluable tool for experimentation and debugging.

As a Common Lisp user, I initially missed this feature. While Common Lisp does have the #+nil reader macro that can be used for similar purposes, it’s not quite as flexible as Clojure’s comment form. The #+nil macro looks like this:

#+nil
(print "This won't be evaluated when the file is loaded")

However, I wanted something closer to Clojure’s Rich Comment Blocks, so I created my own comment macro in Common Lisp:

(defmacro comment (&body body)
  (declare (ignore body)))

This simple macro brings the power of Rich Comment Blocks to Common Lisp, offering more flexibility than the #+nil reader macro. It allows you to wrap multiple expressions and even nested forms, which can be selectively evaluated during development.

Give it a try - you might find it as useful as I do.

June 28, 2024

emacs lisp

From Python to Emacs Lisp

Ever feel like your brilliant blog ideas evaporate faster than spilled coffee on a hot keyboard?

If you’re like me, the lower the barrier to creating a note for your blog, the better. I started with a Python script to streamline my blog writing process, but it wasn’t quite hitting the mark. It required me to open the terminal, run the command, and then open the file in Emacs. The experience felt clunky.

Then it hit me: I’m using Emacs, why the heck am I doing this in Python.

I decided to port my Python script to Emacs Lisp, and not only was it easier to write, but the overall experience also improved significantly. It prompts you with a few questions and opens a buffer for you to start writing.

For reference, here’s the code that I ended up writing.

(defun pet/write-blog ()
  "Create a new blog note or post."
  (interactive)
  (let* ((is-note (y-or-n-p "Do you want to write a note? "))
         (title (read-string "What is the title? "))
         (tags (read-string "Do you want to tag it? "))
         (filename (concat (pet--slugify title) ".md"))
         (dir-type (if is-note "note" "post"))
         (path (expand-file-name
                filename
                (expand-file-name
                 (concat "content/" dir-type "s") pet/blog-directory)))
         (date (format-time-string "%Y-%m-%d"))
         (replacements
          `(("${title}" . ,title)
            ("${date}" . ,date)
            ("${type}" . ,dir-type)
            ("${taxonomies}" . ,(format (if is-note "tags: [%s]" "categories: [%s]") tags))
            ("${tags}" . ,tags))))
    (find-file path)
    (insert pet/blog-frontmatter) ;; insert template for frontmatter
    (goto-char (point-min)) ;; beginning of buffer, so we can replace the title
    (pet--replace-strings replacements)
    (goto-char (point-max))))

(defun pet--slugify (s)
  "Create a slug from string S."
  (replace-regexp-in-string "^-\\|-$" ""
    (replace-regexp-in-string
     "[^a-z0-9]+" "-" (downcase s))))

(defun pet--replace-strings (replacement-list)
  "Replace multiple strings in the current buffer.

REPLACEMENT-LIST is an alist where each element is a cons cell (SEARCH
. REPLACE).  For each pair, all occurrences of SEARCH are replaced with
REPLACE."
  (save-excursion
    (dolist (rep replacement-list)
      (goto-char (point-min))
      (while (search-forward (car rep) nil t)
        (replace-match (cdr rep) t t)))))

Now it’s just one command pet/write-blog to start writing a new note, just like the one you are reading right now.

December 10, 2023

clojure mac lisp

Clojure on MacOS

To install the latest version of Clojure on MacOS, you first need to install Java, after which you can install Clojure.

To install Java, I use Temurin and pick the latest LTS (Long-Term Support) version.

Assuming you already have Homebrew:

brew install temurin
brew install clojure/tools/clojure

This will also install rlwrap which makes sure that you can use the arrow keys in the REPL.

I also use neil for some common aliases, for example, to create a new project.

brew install babashka/brew/neil

Now you can run the neil new command to create a new Clojure repository.

June 10, 2022

lisp quicklisp

How to install Quicklisp

Before starting, make sure you have installed SBCL. Then, get the quicklisp file, which lets you bootstrap and install Quicklisp.

cd ~/downloads
curl -O http://beta.quicklisp.org/quicklisp.lisp
sbcl --load quicklisp.lisp

Now you are in the REPL, and you can install Quicklisp. By default, it will be installed in ~/quicklisp, but I like to keep my home directory clean and install it in ~/.local/share/quicklisp. Thus the :path argument.

(quicklisp-quickstart:install :path "~/.local/share/quicklisp/")

I also prefer Quicklisp to be available when I start SBCL, so I add it to my init file:

(ql:add-to-init-file)

That’s it! Happy Lisping!

May 10, 2022

lisp asdf

Switch the current working directory in the REPL

If you start a REPL in the wrong directory, you can switch it by using UIOP.

UIOP is the portability layer of ASDF, supplying an abstraction on top of different implementations or OS’es.

For example, to change to a new project do:

(uiop:chdir "~/lisp/fangorn/")

Make your own packages available to Quicklisp

In Lisp it’s quite common to have your own helper libraries, which are packaged as ASDF packages. To be able to use your libraries in other projects, you need to let ASDF know how to find them.

First create the directory ~/.config/common-lisp/source-registry.conf.d/

There create a file with any name of your choice but with the type conf, for instance 50-petar-lisp.conf.

In this file, add the following line to tell ASDF to recursively scan all the subdirectories under /home/petar/lisp/ for .asd files: (:tree "/home/petar/lisp/").

May 9, 2022

lisp

Template for a new Common Lisp Project

To easily start a new Common Lisp project, I’m making use of the CL-Project from the famed Lisper Eitaro Fukamachi.

You can either install it through roswell with ros install cl-project or through the use of Quicklisp with (ql:quickload :cl-project).

The benefit of install it through Roswell is that you also get a binary.

To create a project through the REPL:

(cl-project:make-project #p"lisp/cl-sample/"
  :author "Eitaro Fukamachi"
  :email "[email protected]"
  :license "LLGPL"
  :depends-on '(:clack :cl-annot))

Or by using the binary:

make-project /home/user/common-lisp/sample \
    --name sample \
    --description "sample project." \
    --author "Your name" --license LLGPL \
    --depends-on alexandria split-sequence`

November 15, 2021

lisp ai

From Lisp to Python, but why Peter?

Peter Norvig is a well-known educator on AI and used to be one of the key figures in the Lisp movement.

His books used to use Lisp in their exercises, but he switched to Python at some point. Today, I came across the Lex Fridman podcast, where he interviewed Peter Norvig and asked him why he made that change.

He gives a surprisingly simple answer at the 43-minute mark.

I was expecting deeper reasons, but his students were having difficulty grasping Lisp, and a questionnaire showed that Python mimicked the pseudocode from the book the most. That’s it.

In the short amount of time he had to educate them on AI, he could not spare the time to educate them on Lisp.

Coincidentally, I also came across this gem at smuglispweeny blog:

At ILC 2002 former Lisp giant now Python advocate Peter Norvig was for some reason allowed to give the keynote address like Martin Luther leading Easter Sunday mass at the Vatican and pitching Protestantism because in his talk Peter bravely repeated his claim that Python is a Lisp.

When he finished Peter took questions and to my surprise called first on the rumpled old guy who had wandered in just before the talk began and eased himself into a chair just across the aisle from me and a few rows up.

This guy had wild white hair and a scraggly white beard and looked hopelessly lost as if he had gotten separated from the tour group and wandered in mostly to rest his feet and just a little to see what we were all up to. My first thought was that he would be terribly disappointed by our bizarre topic and my second thought was that he would be about the right age, Stanford is just down the road, I think he is still at Stanford – could it be?

“Yes, John?” Peter said.

I won’t pretend to remember Lisp inventor John McCarthy’s exact words which is odd because there were only about ten but he simply asked if Python could gracefully manipulate Python code as data.

“No, John, it can’t,” said Peter and nothing more, graciously assenting to the professor’s critique, and McCarthy said no more though Peter waited a moment to see if he would and in the silence a thousand words were said.