Lisp - Weird programming languages # 1

Page views: 0
Published on: 8/8/2025, 12:00:00 AM
Last editted on: 8/8/2025, 12:00:00 AM

Welcome to the first chapter of the weird programming languages series! In this chapter we are going to talk about Lisp - a mature, stable, functional and object-oriented programming language! The language first appeared at 1960, making it an ancient relic. However, the language still continue to exist, serving both as a general-purpose programming language and for specialized use cases.

Lisp has evolved into many dialects.

  • Emacs Lisp (Emacs, a text editor, uses a dialect of Lisp to customize and extend its functionality)
  • Common Lisp
  • Lisp Flavored Erlang (LFE)
  • and so on...

So what makes Lisp so "weird"...

Lisp

How to save the princess in lisp

(credits: toggl https://toggl.com/blog/save-princess-8-programming-languages)

It's the absurd amount of parentheses.

You will understand if you take a look at the following example,

(defun process-data (data)
  (let ((processed
          (remove-if
            #'null
            (mapcar
              #'(lambda (item)
                  (when (valid-item-p item)
                    (transform-item item)))
              data))))
    (sort processed #'item-compare)))

(credits: https://dev.to/this-is-learning/could-parentheses-be-a-reason-lisp-is-hard-to-read-481l)

One issue, that is pointed out by many developers, is the lack of readability in Lisp.

Is it really unreadable though? Or maybe it's unreadable because we don't understand it's philosophy.

A programming language brings three mechanisms to bear against software complexity: Primitive expressions, Means of combination, and Means of abstraction

An effective programming language must provide a means of abstraction that can describe the essence of a compound computational model, and hide any spurious complexities introduced by a particular choice of primitive expressions or means of combination. Lisp provides this means of abstraction, in conjunction with primitive expressions and means of combination introducing minimal spurious complexities. Its underlying model of data and execution subdues the artificial complexities of the computer, and its uniform, extensible syntax provides the means of abstraction to best express the conceptual essence of any computational model. (from The Philosophy of Lisp)

Lisp encourages a functional style of programming, allowing the programmer to describe what a procedure should accomplish in terms of conceptual expressions, rather than focusing solely on the step-by-step mechanics of how to achieve it.

Now you may look at these amazing and beautiful works of art, created with Lisp.

#+(or)
(defun indexed-pattern-designs ((pattern stencil))
  (with-slots (array) pattern
    (let ((designs (make-array (* (pattern-height pattern)
                                  (pattern-width pattern)))))
      (dotimes (i (length designs))
        (setf (aref designs i) (make-opacity (row-major-aref array i))))
      array)))

(from McCLIM source code)

Following is an example of SxQL, a SQL generator for common lisp. Notice how the beautiful syntax allows us to write clean and clear SQL.

(select (:title :author :year)
  (from :books)
  (where (:and (:>= :year 1995)
               (:< :year 2010)))
  (order-by (:desc :year)))

(from https://lisp-lang.org/)

Syntax

The syntax is just going to be a lot of parentheses. Jokes aside, it's pretty simple to start with.

Here's how we can do a Hello World program with Lisp

Hello World

; first lisp program
; this is a comment
(print "Hello world!")

The following resources are awesome if you want to learn more about Lisp (Common Lisp) syntax.

Variables

; use defvar, or defparameter to create global scoped variables
; we use the *var* convention to declare global variables. 
; (note: you can declare them without the * as well)
(defparameter *name* "seniru")
(defparameter *x* 5)
(defparameter *y* 10)

(print *name*) ; outputs seniru
(print (+ *x* *y*)) ;outputs 15 (the result of x + y)

(
 ; we are inside a block
 ; use let to create local variables
     let ((n 5)
         (m 3))
 
     (print (- n m)) ; outputs 2 (the result of n - m)
 )

(print (- n m)) ; error: *** - EVAL: variable N has no value

Conditionals

(print (if (= 5 (+ 3 2)) ; if 5 == (3 + 2)
           "they are equal" ; then clause
           "they are not equal" ; else clause
           ))
; outputs "they are equal"

; cond statements gives us something similar to "switch" statements
(print
 (cond ((> 2 2) (error "wrong!"))
       ((< 2 2) (error "wrong again!"))
       (t "correct")))
; outputs "correct"

Iterations / Loops

There are many ways to iterate in Common Lisp. I think the most used method is the loop macro. I had a hard time understanding how to use it - because there's so many ways to use it. Go checkout The Common Lisp Cookbook – Loop, iteration, mapping, and the loop documentation to learn more about these in depth. The easiest way to do a normal C like loop is the do macro, according to my understanding. The other method is advanced and offers complex iteration styles, which will not be covered in this article.

(do ((n 0 (+ n 1)))  ; n = 0; n++
    ((>= n 5)) ; stop condition (n >= 5)
    (print (* n n)))
; outputs: 0 1 4 9 16

Functions

Functions have the following syntax

(defun name(params) body)

With that in mind, let's try a simple task that generates the fibonnaci series. We will be using the recursive approach here.

(defun fib(n)
    (if (<= n 1)
    n
    (+ (fib (- n 1)) (fib (- n 2)))))

; first 5 results of the fibonnaci series
(do ((n 0 (+ n 1)))  ; n = 0; n++
    ((>= n 10)) ; stop condition (n >= 10)
    (print (fib n)))

; output: 0 1 1 2 3 5 8 13 21 34

Palindrome checker

Can we do a Palindrome checker with Lisp? We probably can. However, it'd be challenging, as this is the first day of my life writing Lisp code. I'd make sure to document the challenges I had to face, and the workarounds - so that you can learn from my experience.

Here we go!

(defun is-palindrome(str)
    (let ((str-len (length str))
          (str (string-downcase str)))
    (if (<= str-len 1)
        t ; t stands for true
        (if (string-equal (char str 0) (char str (- str-len 1)))
            (is-palindrome (subseq str 1 (- str-len 1)))
            nil
            ))))

(print (is-palindrome "RaceCar"))

There it is! Overall it wasn't too hard to implement it. I had to keep track of the parenthesis though. Sometimes it gets a little confusing because everything needs parentheses. I tried to go with the philosophy of the language, by trying to be expressive. I'm not too sure if the snippet above me is too expressive though. Maybe because I'm a newbie to the language.

Conclusion

I'd say it's a fun language to learn. And certainly something for you, if you need a change. It can get annoying sometimes but it could get better with practice I guess. Again, I'm not a lisp expert. The language has a great documentation for methods. Kind of hard to pick up syntax because there were not too much guides on them. "Official" guides weren't too straightforward.

Did I have fun with it? Yes! I think the language is beautiful more than it's weird. I hope I inspired you to give it some try too! And hopefully I did my best to cover the best of this language.

If you want to see more of this kind, feel free to check out this post, where I have listed out all the chapters of this series

Thanks for reading! See you soon with another chapter...

Replies

No replies yet

Create a reply