It is very easy to find examples on Internet of Common Lisp programs written as functional programming language as that is how many people write Common Lisp. They think functional programming and it became a part of the life. It is little bit more difficult to find imperative Common Lisp examples on Internet.

Personal imperative Common Lisp

When importing sets of data that require one time, single use programs, I may write it in imperative style. After that, program may be deleted. Those are usually smaller programs that handle single file in a weird non-standard format. Not even one function has to be defined for such program to import the data.

Of course, even the imperative programming paradigm in Common Lisp will call Common Lisp functions.

Here is one example, and I am not so sure if this can be said to be imperative programming as it is all enclosed into one let. I have just taken some of small snippets that I don’t use any more as they were written for one time processing.

(let* ((file (car *args*))
       (output (cadr *args*))
       (nonworking (caddr *args*))
       (lines (file-lines-to-list file)))
  (dolist (line lines)
    (let* ((s1 (search " " line))
	   (s2 (search " " line :start2 (1+ s1)))
	   (s3 (search " " line :start2 (1+ s2)))
	   (domain (substring line 0 s1))
	   (email (substring line (1+ s1) s2))
	   (ip (s6-dnsip4 domain)))
  ;; (format t "Found line:~%~A~%" line)
  (format t "Handling domain: ~A~%" domain)
  ;; (unless (y-or-n-p "Continue")
  ;; 	(exit))
  (if ip
      (with-open-file (o output :if-exists :append :if-does-not-exist :create :direction :output)
      	(format o "~A~%" line))
      (with-open-file (non nonworking :if-exists :append :if-does-not-exist :create :direction :output)
	(format non "~A~%" line))))))

Some truly imperative programming style would be something like this below where the state in program changes how the program runs:

(setq a 1)
(setq b 2
(setq c (+ a b))
(princ c)

IMHO imperative or procedural programming is also great to start learning Common Lisp.

Good book to read, and I read it too, and started programming in Common Lisp because of this book is the Practical Common Lisp by Peter Seibel.

In beginning I had problems of thinking in functional programming style. Surely I did functions in my Perl programming, but Perl was kind of a different language. I did have tension to program in imperative style in Perl. Even when I used Perl procedures, I felt I am programming in imperative style.

Then I have started looking into sources of LISP, Emacs Lisp and Scheme programs and I found them somehow silly. I must say I found the sources of LISP programs childish. As that is how it looked like to me somewhere end of 2015 when I started learning about LISP.

I could not believe that it looked so simple!

My surprise came from readability and ease of defining functions.

Of course that compared to the mess of Perl language that LISP looked childish simple! Perl programming looked ugly, not readable as compared to what I found in LISP programs.

Jut look at how the Perl mess looks like:

sub getxml {
	my $ua = LWP::UserAgent->new;
	$ua->agent($template_hash{'generator'});
	$ua -> timeout(10);
	my $request = HTTP::Request->new(GET => $xmllink);
	my $response = $ua -> request($request);
	if($response -> is_success) {
		parse_xml(${$response}{'_content'});
	} else {
		print "FAILED\n";
	}
}

sub parse_xml {
	my $xml = shift;
	my $p = XML::Bare->new(text => $xml);
	my $tree = $p->parse();
	print ${$tree->{prices}->{currency}[0]}{acess}{value};
	<STDIN>;
	print dd($tree);
}

Slowly it became clear that I am supposed to send some parameters to the function and that function will return something back to me, or it will do some actions like printing letters on the screen or sending SMS.

If I remember well I had difficulties to understand how people write LISP and Scheme, but then somewhere I read I should be making small functions, just enough to fit on screen that do simpler things and that they should be more or less reusable. And I got used to that advise. I don’t even know who recommended it, I just think it was Peter Norvig in his essays on LISP.

That is how I have started learning LISP.

And I was quite surprised that LISP’s eval loop works on command line, and that I got a PROMPT to evaluate any LISP function. So I have started developing programs from command line and it worked really well. But then people started giving me advise I should not be working from command line, I should be using GNU Emacs to evaluate LISP, as it helps in editing. I really did not get the point, as it worked so well on the REPL.

I have even found a way that when I make a new function that I can save it in the file. I could develop in LISP’s REPL and save the developed function into the file. What more one could want and expect?

In fact, I think the function saved itself, and here it is below. When it saves itself, the letters get upper cased:

(DEFUN SAVE-FUNCTION (F)
 "Saves the function in the file *my-function-dir*/function-name.lisp.
Invoke it as: (SAVE-FUNCTION 'FUNCTION-NAME) or (SAVE-FUNCTION \"FUNCTION-NAME\")"
 (LET
  ((FUNCTION-NAME (CAR (CADR (SYMBOL-PLIST (INTERN (STRING-UPCASE F))))))
   (FUNCTION-FILE
    (FORMAT NIL "~a/~a.lisp" *MY-FUNCTION-DIR*
     (STRING-DOWNCASE (SUBSTITUTE #\- #\? (IF (SYMBOLP F) (SYMBOL-NAME F) (SYMBOL-NAME (INTERN (STRING-UPCASE F)))))))))
  (WITH-OPEN-FILE (STR FUNCTION-FILE :DIRECTION :OUTPUT
 :IF-DOES-NOT-EXIST :CREATE) (PRINT FUNCTION-NAME STR))))

That meant I could stay forever in LISP’s REPL and keep saving functions, none of them get lost. Later I could just load them all and it would work again how I intended it.

Of course I have switched later to Emacs editing and using SLIME and other LISP tools. I still like running inferior LISP in Emacs and using straight evaluations without SLIME. I find it more stable and robust.

As of 2021-05-06 I am writing smaller functions in a childish style. The simpler it is, the better. Several smaller functions are using each other and making a whole program. It gives such a nice feelings.

Rarely a function is larger than few lines. One can see the example in this Emacs Lisp functio below, it creates a new temporary buffer in fundamental mode. But if I press the prefix key like C-u it will ask me for the mode, maybe I want SQL mode or maybe I want Emacs Lisp mode.

My functions are about always this big in average. If it becomes bigger than that, it will usually get split into multiple functions.

;;;; ━━━━━━━━━━━━━━━━━━━━━━━━━
;;;;   RCD TEMPORARY BUFFERS
;;;; ━━━━━━━━━━━━━━━━━━━━━━━━━

(defvar rcd-temp-buffer-mode-history nil)

(defun rcd-temp-buffer (&optional name mode)
  (interactive "p")
  (let* ((format "*RCD TEMPORARY BUFFER%s%s*")
	 (buffer (if name (format format ": " name) (format format "" ""))))
    (switch-to-buffer (generate-new-buffer "*RCD TEMPORARY BUFFER*"))
    (if current-prefix-arg
	(let* ((modes '("fundamental-mode" "emacs-lisp-mode" "sql-mode" "markdown-mode"
			"org-mode" "lisp-mode"))
	       (mode (completing-read "Mode: " modes nil t nil 'rcd-temp-buffer-mode-history)))
	  (funcall (intern mode)))
    (funcall (intern (or mode "fundamental-mode"))))))

To think in functional style, one should define functions that return some values, that may be used in other functions, higher functions, that end up in highest function calling the program.

If your functions are small enough and made to be reusable, after building many functions you may find yourself writing less code for marvelous results.

Let us say you wish to add, update, delete, copy entries in the address book.

  1. Maybe you would first start with listing of all fields in the database, like first name, last name, city, country. That would be one function. It returns the list. You would need to have function to display the list returned.

    (defun list-fields ()
      (let ((list "GIVE ME ALL FIELDS FROM DATABASE"))
         list))
  2. Other function would be maybe to edit value. Editing single value of any field. You would submit field to function and be able to edit it. Like (edit "Last name") could work to edit John Johnston’s last name. As if function is generic, you will be able to edit any field with it.

    (defun edit-field (field)
      (let ((edited-value (edit-with-editor field)))
        (update-value database field value)))
  3. Third one would be to update the value in the database. It would be sending the edited value into the database. Editing field would involve this function. One can see that send-to-database need to be another function.

    (defun update-field (field value)
      (let ((database-command (format nil "PLEASE UPDATE FIELD ~A WITH VALUE ~A" field value)))
        (send-to-database database-command)))
  4. Fourth could assign key bindings or menu.

  5. Fifth one could list all entries on the screen.

  6. Sixth could now call the listing of entries and call for key bindings.

User would then be faced with the screen, would be able to press key, and by keys invoke all other functions.

I truly hope that the article you read could help you understand how to think in functional programming style.

You may leave a comment or write to me by using my public inquiry email address: 2021-05-02@gnu.support.