InterviewPitch
Lisp interview questions

Lisp Interview Questions with Answers

Most Asked Lisp Interview Questions for Software Engineer Roles

100+ QuestionsDetailed AnswersCode ExamplesUpdated for 2026

Introduction

This page provides a complete collection of Lisp Interview Questions and Answers designed for software developers, programmers, AI engineers, functional programming enthusiasts, and candidates preparing for technical interviews. Lisp is one of the oldest and most influential programming languages. It introduced concepts such as symbolic computation, functional programming, recursion, garbage collection, and dynamic typing. Lisp is widely known for its importance in artificial intelligence, language research, and advanced software development. This interview guide covers beginner, intermediate, and advanced Lisp concepts including Lisp syntax, lists, atoms, S-expressions, recursion, functional programming, macros, lambda expressions, evaluation models, Common Lisp, Scheme, and real-world programming scenarios.

Why Lisp?

  • Pioneered functional programming and recursion – a foundational language in computer science
  • Powerful macro system – allows metaprogramming and code-as-data (homoiconicity)
  • Symbolic computation – ideal for AI, natural language processing, and research
  • Dynamic and interactive development – REPL-driven programming for rapid prototyping
  • Multiple dialects – Common Lisp, Scheme, Clojure provide flexibility for different domains
  • Influenced many modern languages – concepts adopted in Python, Ruby, JavaScript, and more
  • Strong community and rich ecosystem for academic and industry applications

Most Asked Lisp Interview Questions

Beginner
1. What is Lisp?

Lisp is a family of programming languages with a long history, designed for symbolic computation and artificial intelligence. It is known for its unique syntax, powerful macro system, and support for functional programming.

  • Symbolic computation: Designed for manipulating symbols
  • Functional programming: First-class functions
  • Macros: Powerful meta-programming capabilities
  • Garbage collection: Automatic memory management
  • REPL: Interactive development environment
lisp
;; Hello World in Lisp
(format t "Hello, World!")
Beginner
2. How to declare variables in Lisp?

Variables in Lisp are declared using defvar (global), defparameter (global mutable), and let (local).

  • defvar: Global variable (mutable)
  • defparameter: Global variable (mutable)
  • let: Local variable
  • Dynamic typing: Variables can hold any type
  • setf: Used to assign values
lisp
;; Variables in Lisp
(defparameter *mutable-var* "Hello")  ; Mutable variable (global)
(defvar *immutable-var* "World")       ; Immutable variable (global)
(let ((local-var "Local"))            ; Local variable
  (format t local-var))

;; Type inference and dynamic typing
(setf *mutable-var* "Updated")
(format t *mutable-var*)
Beginner
3. What are the data types in Lisp?

Lisp has a rich set of data types including numbers, characters, strings, symbols, lists, arrays, and hash tables.

  • Numbers: Integers, floats, ratios
  • Booleans: t and nil
  • Characters: #\A
  • Strings: "Hello Lisp"
  • Symbols: hello-symbol
  • Lists: (1 2 3 4 5)
  • Arrays: make-array
lisp
;; Data Types in Lisp
;; Numbers
(defparameter *int-num* 10)
(defparameter *float-num* 3.14)
(defparameter *ratio-num* 1/2)

;; Booleans
(defparameter *is-active* t)  ; t for true
(defparameter *is-inactive* nil) ; nil for false

;; Characters
(defparameter *char* #\A)

;; Strings
(defparameter *str* "Hello Lisp")

;; Symbols
(defparameter *sym* 'hello-symbol)

;; Lists
(defparameter *list* '(1 2 3 4 5))

;; Arrays
(defparameter *array* (make-array 5 :initial-contents '(1 2 3 4 5)))

;; Type checking
(typep 10 'integer) ; t
Beginner
4. How to define functions in Lisp?

Functions in Lisp are defined using the defun macro. They support optional parameters, multiple return values, and higher-order functions.

  • Basic: (defun name (params) body)
  • Documentation: Strings after params
  • Optional params: &optional
  • Multiple return values: (values)
  • Higher-order: Functions as arguments
lisp
;; Functions in Lisp
;; Basic function
(defun add (a b)
  (+ a b))

;; Function with documentation
(defun subtract (a b)
  "Subtract b from a"
  (- a b))

;; Default parameters not directly supported in Common Lisp
;; But can be simulated
(defun greet (&optional (name "Guest"))
  (format nil "Hello, ~a!" name))

;; Function with multiple return values
(defun divide (a b)
  (values (/ a b) (mod a b)))

;; Higher-order function
(defun operate (a b operation)
  (funcall operation a b))

;; Lambda expression
(defparameter *multiply* (lambda (a b) (* a b)))

;; Usage
(format t "~a" (add 5 3))
(format t "~a" (subtract 10 4))
(format t "~a" (greet "Alice"))
(format t "~a" (operate 6 7 *multiply*))
Beginner
5. What are arrays in Lisp?

Arrays in Lisp are created with make-array and accessed with aref. Vectors are one-dimensional arrays.

  • Creation: (make-array size)
  • Access: (aref arr index)
  • Modify: (setf (aref arr index) value)
  • Vectors: #(1 2 3)
  • Operations: array-dimension
lisp
;; Arrays in Lisp
;; Array creation
(defparameter *numbers* (make-array 5 :initial-contents '(1 2 3 4 5)))
(defparameter *strings* (make-array 3 :initial-contents '("Apple" "Banana" "Orange")))

;; Access and modify
(aref *numbers* 2) ; Access element (0-indexed)
(setf (aref *numbers* 2) 10) ; Modify element

;; Array operations
(array-dimension *numbers* 0) ; Size
(array-dimensions *numbers*) ; Dimensions

;; Iteration
(dotimes (i (length *numbers*))
  (format t "~a " (aref *numbers* i)))

;; Vector (1D array)
(defparameter *vector* #(1 2 3 4 5))

;; Map over array
(map 'vector (lambda (x) (* x 2)) *numbers*)

;; Lists vs Arrays
(defparameter *list* '(1 2 3)) ; List
(defparameter *array-2* (make-array 3 :initial-contents '(1 2 3))) ; Array
Beginner
6. What are collections in Lisp?

Lisp collections include lists, sets, and hash tables. Lists are the most common and versatile collection type.

  • Lists: (list 1 2 3)
  • Sets: (remove-duplicates)
  • Maps: make-hash-table
  • Operations: filter, map, reduce
  • Modification: push, pop
lisp
;; Collections in Lisp
;; Lists
(defparameter *immutable-list* '(1 2 3 4 5))
(defparameter *mutable-list* (list 1 2 3))
(setf (cdr (cdr *mutable-list*)) (list 4)) ; Modify list

;; Sets (using lists)
(defparameter *set* (remove-duplicates '(1 2 3 3))) ; (1 2 3)

;; Hash tables (maps)
(defparameter *immutable-map* '((key1 . value1) (key2 . value2)))
(defparameter *mutable-map* (make-hash-table))
(setf (gethash 'key1 *mutable-map*) "value1")
(setf (gethash 'key2 *mutable-map*) "value2")

;; Collection operations
(defparameter *numbers* '(1 2 3 4 5 6))
(defparameter *evens* (remove-if-not #'evenp *numbers*))
(defparameter *doubled* (mapcar (lambda (x) (* x 2)) *numbers*))
(defparameter *sum* (reduce #'+ *numbers*))
(defparameter *exists* (some (lambda (x) (> x 10)) *numbers*))
(defparameter *all-even* (every #'evenp *numbers*))

(format t "~a" *evens*)
(format t "~a" *doubled*)
(format t "~a" *sum*)
Beginner
7. What are structs (data classes) in Lisp?

Structs in Lisp are defined with defstruct and provide accessor functions, constructors, and copying.

  • Definition: (defstruct person name age city)
  • Constructor: (make-person :name "Alice")
  • Accessors: (person-name obj)
  • Copy: (copy-person obj)
  • Default values: (city "Unknown")
lisp
;; Structs (Data Classes) in Lisp
;; Define structure similar to data class
(defstruct person
  name
  age
  (city "Unknown"))

;; Usage
(defparameter *person1* (make-person :name "Alice" :age 25 :city "NYC"))
(defparameter *person2* (copy-person *person1*)) ; Copy
(setf (person-age *person2*) 26) ; Modify copy

;; Accessors
(person-name *person1*)
(person-age *person1*)
(person-city *person1*)

(format t "~a" *person1*)
Beginner
8. What are sealed classes in Lisp?

Lisp uses CLOS (Common Lisp Object System) for object-oriented programming. Sealed classes can be simulated using generic functions and classes.

  • Generic functions: defgeneric
  • Classes: defclass
  • Methods: defmethod
  • Polymorphism: Based on class types
  • Multi-methods: Multiple dispatch
lisp
;; Sealed Classes in Lisp (using CLOS)
;; Define generic function
(defgeneric handle-result (result))

;; Define classes
(defclass success ()
  ((data :initarg :data :accessor data)))

(defclass error ()
  ((message :initarg :message :accessor message)))

(defclass loading ()
  ())

;; Implement methods
(defmethod handle-result ((result success))
  (format t "Success: ~a" (data result)))

(defmethod handle-result ((result error))
  (format t "Error: ~a" (message result)))

(defmethod handle-result ((result loading))
  (format t "Loading..."))

;; Sealed interfaces simulation
(defgeneric area (shape))

(defclass circle ()
  ((radius :initarg :radius :accessor radius)))

(defclass rectangle ()
  ((width :initarg :width :accessor width)
   (height :initarg :height :accessor height)))

(defclass point ()
  ())

(defmethod area ((shape circle))
  (* pi (expt (radius shape) 2)))

(defmethod area ((shape rectangle))
  (* (width shape) (height shape)))

(defmethod area ((shape point))
  0)

;; Usage
(handle-result (make-instance 'success :data "Data loaded"))
(format t "~a" (area (make-instance 'circle :radius 5.0)))
Beginner
9. What is null safety in Lisp?

Lisp uses nil to represent null values. Null safety is achieved through conditional checks and functions that handle nil gracefully.

  • nil: Represents null/false
  • Conditionals: when, if
  • Safe functions: when, unless
  • Elvis operator: Custom implementation
  • Type checking: typep
lisp
;; Null Safety in Lisp
;; Lisp doesn't have built-in null safety like Kotlin
;; But we can implement patterns

;; Sentinel values
(defparameter *unset* :unset)

;; Safe access function
(defun safe-length (list)
  (if list (length list) 0))

;; Safe call pattern
(defun safe-call (obj &optional default)
  (if obj (funcall obj) default))

;; Elvis operator equivalent
(defun elvis (value default)
  (if value value default))

;; Safe casting
(defun safe-type (obj type)
  (if (typep obj type) obj nil))

;; Let function for null checks
(defun process-string (str)
  (when str
    (format t "String is: ~a" str)
    (format t "Length: ~a" (length str))))

;; Usage
(process-string "Hello")
(process-string nil)
(elvis nil "default")
(safe-type 10 'integer)
Beginner
10. What are control flow statements in Lisp?

Lisp provides control flow through if, cond, loop, dotimes, and do.

  • If-else: (if condition then else)
  • Cond: (cond ((condition) result) ...)
  • Loop: (loop for i from 1 to 10)
  • Dotimes: (dotimes (i 5) body)
  • Do: (do ((i 0 (1+ i))) ((>= i 5)))
lisp
;; Control Flow in Lisp
;; If-else expression
(defparameter *age* 25)
(defparameter *status* (if (< *age* 18) "Minor" "Adult"))
(format t *status*)

;; Cond (switch replacement)
(defparameter *grade* 'A)
(defparameter *result* (cond
                         ((eq *grade* 'A) "Excellent")
                         ((eq *grade* 'B) "Good")
                         ((eq *grade* 'C) "Fair")
                         (t "Needs Improvement")))
(format t *result*)

;; Cond with ranges
(defparameter *score* 85)
(defparameter *grade2* (cond
                         ((<= 90 *score* 100) "A")
                         ((<= 80 *score* 89) "B")
                         ((<= 70 *score* 79) "C")
                         (t "F")))

;; For loop (using dotimes)
(dotimes (i 5)
  (format t "~a " i))

;; For loop with step
(loop for i from 1 to 10 by 2
      do (format t "~a " i))

;; For loop down to
(loop for i from 10 downto 1
      do (format t "~a " i))

;; While loop
(defparameter *i* 0)
(loop while (< *i* 5)
      do (format t "~a " *i*)
         (incf *i*))

;; Do-while loop
(loop do (format t "~a " *i*)
         (decf *i*)
      while (> *i* 0))
Beginner
11. What are classes and inheritance in Lisp?

CLOS provides a powerful object system with classes, inheritance, and multiple dispatch. Classes are defined with defclass.

  • Class: (defclass person () ((name)))
  • Inheritance: (defclass dog (animal) ((breed)))
  • Generic functions: defgeneric
  • Methods: defmethod
  • Interfaces: Simulated via generic functions
lisp
;; Classes and Inheritance in Lisp (CLOS)
;; Base class
(defclass animal ()
  ((name :initarg :name :accessor name)))

;; Generic function
(defgeneric make-sound (animal))

;; Derived class
(defclass dog (animal)
  ((breed :initarg :breed :accessor breed)))

(defmethod make-sound ((animal animal))
  (format t "Animal sound"))

(defmethod make-sound ((dog dog))
  (format t "Woof!"))

;; Abstract class simulation
(defclass vehicle ()
  ((started :initform nil :accessor started)))

(defgeneric start (vehicle))

(defmethod start ((vehicle vehicle))
  (setf (started vehicle) t)
  (format t "Started"))

;; Interface simulation (using generic functions)
(defgeneric fly (obj))
(defgeneric land (obj))
(defgeneric swim (obj))

(defclass duck ()
  ())

(defmethod fly ((duck duck))
  (format t "Flying"))

(defmethod land ((duck duck))
  (format t "Landing..."))

(defmethod swim ((duck duck))
  (format t "Swimming"))

;; Usage
(defparameter *dog* (make-instance 'dog :name "Rex" :breed "German Shepherd"))
(make-sound *dog*)
(name *dog*)

(defparameter *duck* (make-instance 'duck))
(fly *duck*)
(swim *duck*)
Intermediate
12. What are properties in Lisp?

Properties in Lisp are implemented as slots in CLOS. They can have getters, setters, and validation.

  • Slots: (name :initarg :name :accessor name)
  • Getters/Setters: defmethod
  • Validation: Custom setters
  • Lazy initialization: Check and compute
  • Transformation: String manipulation in setters
lisp
;; Properties in Lisp (using CLOS)
(defclass person ()
  ((name :initarg :name :accessor name
         :initform "")
   (age :initarg :age :accessor age
        :initform 0)
   (email :initarg :email :accessor email
          :initform "")
   (address :initarg :address :accessor address
            :initform nil)
   (expensive-data :initform nil)))

;; Lazy initialization
(defun get-expensive-data (obj)
  (unless (slot-value obj 'expensive-data)
    (format t "Computing expensive data...")
    (setf (slot-value obj 'expensive-data) "Expensive Result"))
  (slot-value obj 'expensive-data))

;; Property with validation
(defmethod (setf age) (new-value (obj person))
  (when (>= new-value 0)
    (setf (slot-value obj 'age) new-value)))

;; Property with transformation
(defmethod (setf name) (new-value (obj person))
  (setf (slot-value obj 'name) (string-trim " " new-value)))

(defmethod name ((obj person))
  (string-upcase (slot-value obj 'name)))

;; Usage
(defparameter *person* (make-instance 'person))
(setf (name *person*) "  Alice  ")
(format t "~a" (name *person*)) ; ALICE
(setf (age *person*) 25)
(format t "~a" (get-expensive-data *person*))
Intermediate
13. What are companion objects in Lisp?

Lisp uses packages to organize code. Packages can serve as companion objects with shared constants and functions.

  • Package: defpackage
  • Constants: defparameter
  • Factory functions: defun create
  • Exports: :export
  • Usage: Package-qualified symbols
lisp
;; Companion Objects in Lisp (using packages)
;; Define package as companion
(defpackage :my-class
  (:use :cl)
  (:export :tag :counter :create))

(in-package :my-class)

(defparameter *tag* "MyClass")
(defparameter *counter* 0)

(defun create ()
  (incf *counter*)
  (make-instance 'my-class))

;; Define class
(defclass my-class ()
  ())

;; Usage
(in-package :cl)
(print my-class::*tag*)
(my-class::create)
(my-class::create)
Intermediate
14. How to handle exceptions in Lisp?

Lisp uses handler-case and handler-bind for exception handling. Custom exceptions are defined with define-condition.

  • Handler-case: (handler-case body (error (e) ...))
  • Custom exceptions: define-condition
  • Unwind-protect: unwind-protect for finally
  • Signaling: error
  • Restarts: restart-case
lisp
;; Exception Handling in Lisp
;; Handler-case (try-catch)
(defun divide (a b)
  (handler-case
      (/ a b)
    (division-by-zero ()
      (format t "Division by zero!")
      0)))

;; Handler-bind for more control
(defun divide-safe (a b)
  (handler-case
      (/ a b)
    (error (e)
      (format t "Error: ~a" e)
      0)))

;; Custom exception
(define-condition invalid-age-exception (error)
  ((age :initarg :age :accessor age)
   (message :initarg :message :accessor message
            :initform "Invalid age"))
  (:report (lambda (c stream)
             (format stream "~a: ~a" 
                     (message c) (age c)))))

(defun validate-age (age)
  (if (or (< age 0) (> age 150))
      (error 'invalid-age-exception :age age)
      age))

;; Unwind-protect (finally)
(defun read-file ()
  (let ((file (open "test.txt" :if-does-not-exist nil)))
    (unwind-protect
         (if file
             (read-line file)
             (format t "File not found"))
      (when file
        (close file)
        (format t "Closing resources...")))))

;; Usage
(format t "~a" (divide 10 2))
(format t "~a" (divide 10 0))
(handler-case
    (validate-age 200)
  (invalid-age-exception (e)
    (format t "~a" e)))
Intermediate
15. What are lambda expressions in Lisp?

Lambdas are anonymous functions created with lambda. They are first-class and can be passed as arguments.

  • Syntax: (lambda (x) (* x x))
  • Calling: (funcall lambda arg)
  • Higher-order: Functions accepting lambdas
  • Function reference: #'function-name
  • Closures: Captures lexical scope
lisp
;; Lambda Expressions in Lisp
;; Basic lambda
(defparameter *square* (lambda (x) (* x x)))

;; Lambda with multiple parameters
(defparameter *doubled* (lambda (x) (* x 2)))

;; Higher-order functions
(defun perform-operation (x y operation)
  (funcall operation x y))

;; Lambda with multiple lines
(defparameter *complex-operation* 
  (lambda (x)
    (let ((y (* x 2)))
      (+ y 10))))

;; Function reference
(defun multiply (x y)
  (* x y))

;; Returning lambda from function
(defun get-operation (type)
  (cond
    ((eq type 'add) (lambda (a b) (+ a b)))
    ((eq type 'subtract) (lambda (a b) (- a b)))
    (t (lambda (a b) 0))))

;; Usage
(format t "~a" (funcall *square* 5))
(format t "~a" (perform-operation 10 20 (lambda (x y) (* x y))))
(defparameter *add* (get-operation 'add))
(format t "~a" (funcall *add* 5 3))
Intermediate
16. What are scope functions in Lisp?

Lisp uses let, progn, and with-* macros for scope management and block execution.

  • let: Local variable binding
  • progn: Sequence of expressions
  • with-*: Resource management
  • apply: Apply function to arguments
  • take-if: Conditional filtering
lisp
;; Scope Functions in Lisp
;; let - execute block
(defun process-person (person)
  (when person
    (let ((name (getf person :name))
          (age (getf person :age)))
      (format t "Name: ~a" name)
      (setf (getf person :age) 26)
      person)))

;; let with local functions
(defun process-with-scope ()
  (let ((numbers '(1 2 3 4 5))
        (sum 0))
    (dolist (n numbers)
      (incf sum n))
    sum))

;; apply - configure object
(defun update-person (person)
  (apply #'make-instance 'person
         :name (getf person :name)
         :age (1+ (getf person :age))
         :city "SF"))

;; also - perform additional operations
(defun process-list (lst)
  (progn
    (format t "Before: ~a" lst)
    (append lst '(4))
    (format t "After: ~a" lst)
    lst))

;; take-if equivalent
(defun take-if (predicate value)
  (if (funcall predicate value) value nil))

;; Usage
(process-person '(:name "Alice" :age 25 :city "NYC"))
(process-with-scope)
(take-if (lambda (x) (>= x 18)) 25)
Intermediate
17. What are extension functions in Lisp?

Lisp uses generic functions and wrapper functions to add functionality to existing types without modification.

  • Generic functions: defgeneric
  • Wrapper functions: Helper functions
  • Type-specific: defmethod
  • Extension: Adding methods to classes
  • Composition: Building on existing functions
lisp
;; Extension Functions in Lisp
;; Since Lisp doesn't have extension functions directly,
;; we use generic functions or wrapper functions

;; Using wrapper functions
(defun string-is-email (str)
  (and (find #@ str) (find #. str)))

(defun string-add-prefix (str prefix)
  (concatenate 'string prefix str))

(defun int-is-even (n)
  (evenp n))

(defun int-is-odd (n)
  (oddp n))

;; List extension
(defun list-second-or-null (lst)
  (if (>= (length lst) 2)
      (nth 1 lst)
      nil))

;; String extension
(defun string-word-count (str)
  (length (split-string str " ")))

;; Generic extension using CLOS
(defgeneric is-even (obj))

(defmethod is-even ((obj integer))
  (evenp obj))

;; Usage
(string-is-email "test@example.com")
(string-add-prefix "Hello" "Greeting: ")
(int-is-even 5)
(string-word-count "Hello World")
(list-second-or-null '(1 2 3))
(is-even 4)
Intermediate
18. What are type aliases in Lisp?

Lisp doesn't have type aliases directly, but macros and defparameter can be used to create aliases.

  • defparameter: Create aliases
  • Macros: defmacro for aliases
  • Function types: Store in variables
  • Complex types: Use structures or hash tables
  • Readability: Improve code clarity
lisp
;; Type Aliases in Lisp
;; Lisp doesn't have type aliases directly
;; Using defparameter to create aliases

;; Function type alias
(defparameter *operation* nil) ; Used as a placeholder

;; Or using macros
(defmacro defalias (alias type)
  `(defparameter ,alias ,type))

;; Usage
(defparameter *add* (lambda (a b) (+ a b)))
(defparameter *multiply* (lambda (a b) (* a b)))

(defun execute (op a b)
  (funcall op a b))

;; For complex types
(defparameter *users* (make-hash-table))
(setf (gethash "user1" *users*) '("Alice" . 25))
(setf (gethash "user2" *users*) '("Bob" . 30))

;; Usage
(format t "~a" (execute *add* 5 3))
(format t "~a" (execute *multiply* 5 3))
(format t "~a" (car (gethash "user1" *users*)))
Intermediate
19. What are inline functions in Lisp?

Lisp macros serve as inline functions, expanding at compile time. Functions can also be declared inline with declaim.

  • Macros: defmacro
  • declaim: (declaim (inline function-name))
  • Performance: Reduced overhead
  • Reified types: Type checking at compile time
  • Use cases: Performance-critical code
lisp
;; Inline Functions in Lisp
;; Lisp macros serve a similar purpose to inline functions
;; They expand at compile time

;; Inline macro
(defmacro measure-time (&body body)
  `(let ((start (get-universal-time)))
     ,@body
     (format t "Time: ~a seconds" (- (get-universal-time) start))))

;; Noinline equivalent - functions are always noinline in Lisp
(defun regular-function ()
  (format t "Regular function"))

;; Reified type parameter equivalent
(defmacro is-type (value type)
  `(typep ,value ,type))

;; Usage
(measure-time
 (sleep 1))

(format t "~a" (is-type "Hello" 'string))
(format t "~a" (is-type "Hello" 'integer))

;; Filter by type
(defun filter-by-type (lst type)
  (remove-if-not (lambda (x) (typep x type)) lst))

(defparameter *mixed* (list 1 "Hello" 3.14 "World"))
(defparameter *strings* (filter-by-type *mixed* 'string))
(format t "~a" *strings*)
Intermediate
20. What are higher-order functions in Lisp?

Higher-order functions take functions as arguments or return functions. They are central to functional programming in Lisp.

  • Parameter: (defun apply-op (a b op) (funcall op a b))
  • Return: Functions that return lambdas
  • Composition: compose function
  • Callbacks: Used in event-driven code
  • Functional programming: Core concept
lisp
;; Higher-Order Functions in Lisp
;; Function that takes a function as parameter
(defun apply-operation (a b operation)
  (funcall operation a b))

;; Function that returns a function
(defun get-multiplier (factor)
  (lambda (x) (* x factor)))

;; Function composition
(defun compose (f g)
  (lambda (x) (funcall f (funcall g x))))

;; Higher-order function with multiple lambdas
(defun process (value transform filter)
  (if (funcall filter value)
      (funcall transform value)
      nil))

;; Usage with lambda
(defparameter *result* (apply-operation 10 20 (lambda (a b) (+ a b))))
(format t "~a" *result*)

(defparameter *double* (get-multiplier 2))
(format t "~a" (funcall *double* 5))

(defparameter *square* (lambda (x) (* x x)))
(defparameter *add-ten* (lambda (x) (+ x 10)))
(defparameter *square-then-add-ten* (compose *add-ten* *square*))
(format t "~a" (funcall *square-then-add-ten* 5))

;; Using with named function
(defun add (a b) (+ a b))
(format t "~a" (apply-operation 10 20 #'add))
Advanced
21. What are coroutines in Lisp?

Lisp doesn't have built-in coroutines, but they can be simulated using threads, closures, or custom implementations.

  • Threads: sb-thread:make-thread
  • Closures: Stateful functions
  • Suspending: Custom continuation passing
  • Structured concurrency: Thread management
  • Dispatchers: Thread pools
lisp
;; Coroutines in Lisp (simulated with threads)
;; Lisp doesn't have built-in coroutines like Kotlin
;; Using threads as an alternative

;; Basic thread
(defun fetch-data ()
  (sleep 1)
  "Data loaded")

;; Launch thread
(defun main-launch ()
  (let ((thread (sb-thread:make-thread
                 (lambda ()
                   (sleep 2)
                   (format t "Thread completed")))))
    (sb-thread:join-thread thread)))

;; Async/await simulation
(defun async-fetch ()
  (sb-thread:make-thread #'fetch-data))

(defun await-result (thread)
  (sb-thread:join-thread thread))

;; Parallel tasks
(defun parallel-tasks ()
  (let* ((task1 (async-fetch))
         (task2 (async-fetch))
         (results (list (await-result task1) (await-result task2))))
    (format t "Results: ~a" results)))

;; Timeout
(defun with-timeout (seconds fn)
  (let ((thread (sb-thread:make-thread fn)))
    (sleep seconds)
    (if (sb-thread:thread-alive-p thread)
        (progn
          (sb-thread:terminate-thread thread)
          (format t "Timed out!"))
        (sb-thread:join-thread thread))))

;; Usage
(main-launch)
(async-fetch)
(parallel-tasks)
Advanced
22. What are flows in Lisp?

Lisp uses streams and custom functions to simulate flows. Streams can be filtered, mapped, and collected.

  • Streams: Stateful functions
  • Operators: map, filter
  • StateFlow: State management
  • SharedFlow: Shared streams
  • Collect: Collection of stream values
lisp
;; Flows in Lisp (simulated with streams)
;; Lisp doesn't have built-in flows like Kotlin
;; Using streams and custom functions

;; Simple stream
(defun make-number-stream (n)
  (let ((i 1))
    (lambda ()
      (if (<= i n)
          (prog1 i (incf i))
          nil))))

;; Stream operators
(defun stream-filter (stream pred)
  (lambda ()
    (loop
      (let ((val (funcall stream)))
        (if (null val)
            (return nil)
            (if (funcall pred val)
                (return val)))))))

(defun stream-map (stream fn)
  (lambda ()
    (let ((val (funcall stream)))
      (if (null val)
          nil
          (funcall fn val)))))

(defun stream-collect (stream)
  (loop for val = (funcall stream)
        while val
        collect val))

;; Usage
(defparameter *numbers* (make-number-stream 5))
(defparameter *filtered* (stream-filter *numbers* (lambda (x) (evenp x))))
(defparameter *mapped* (stream-map *filtered* (lambda (x) (format nil "Number: ~a" x))))
(format t "~a" (stream-collect *mapped*))

;; State simulation
(defparameter *state* 0)
(defun get-state () *state*)
(defun set-state (val) (setf *state* val))
(defun increment () (incf *state*))
Advanced
23. What are channels in Lisp?

Channels can be implemented using queues and threads for communication between different threads.

  • Queue: defclass queue
  • Send/Receive: queue-enqueue, queue-dequeue
  • Buffered: Queue capacity
  • Producer/Consumer: Patterns for communication
  • Close: Notify when done
lisp
;; Channels in Lisp (using queues)
;; Lisp doesn't have built-in channels like Kotlin
;; Using queues and threads

;; Simple queue implementation
(defclass queue ()
  ((items :initform '() :accessor items)
   (lock :initform (sb-thread:make-mutex) :accessor lock)))

(defun queue-enqueue (queue item)
  (sb-thread:with-mutex ((lock queue))
    (setf (items queue) (append (items queue) (list item)))))

(defun queue-dequeue (queue)
  (sb-thread:with-mutex ((lock queue))
    (let ((item (car (items queue))))
      (setf (items queue) (cdr (items queue)))
      item)))

(defun queue-size (queue)
  (length (items queue)))

;; Basic channel
(defun basic-channel ()
  (let ((queue (make-instance 'queue)))
    (sb-thread:make-thread
     (lambda ()
       (queue-enqueue queue "Hello")
       (queue-enqueue queue "World")))
    (loop for i from 1 to 2
          do (format t "~a" (queue-dequeue queue)))))

;; Buffered channel
(defun buffered-channel ()
  (let ((queue (make-instance 'queue)))
    (sb-thread:make-thread
     (lambda ()
       (dotimes (i 5)
         (queue-enqueue queue i)
         (format t "Sent: ~a" i))))
    (dotimes (i 5)
      (sleep 0.1)
      (format t "Received: ~a" (queue-dequeue queue)))))
Advanced
24. What are sealed classes and enum classes?

Lisp uses CLOS classes and generic functions to implement similar patterns. Enums are typically represented as symbols or keyword arguments.

  • Enum: defparameter *colors* '(:red :green :blue)
  • Sealed: Classes with specific methods
  • Properties: Slots with values
  • Subclasses: Inheritance hierarchy
  • Polymorphism: Generic functions
lisp
;; Sealed Classes and Enum Classes in Lisp
;; Enum simulation
(defparameter *colors* '(:red :green :blue))

(defparameter *status-codes* '((:success . 200)
                               (:error . 500)
                               (:loading . 100)))

;; Sealed class simulation using generic functions
(defclass ui-state ()
  ())

(defclass success (ui-state)
  ((data :initarg :data :accessor data)))

(defclass error (ui-state)
  ((message :initarg :message :accessor message)))

(defclass loading (ui-state)
  ())

(defclass idle (ui-state)
  ())

(defgeneric handle-state (state))

(defmethod handle-state ((state success))
  (format t "Data: ~a" (data state)))

(defmethod handle-state ((state error))
  (format t "Error: ~a" (message state)))

(defmethod handle-state ((state loading))
  (format t "Loading..."))

(defmethod handle-state ((state idle))
  (format t "Idle"))

;; Payment classes
(defclass payment () ())

(defclass cash (payment)
  ((amount :initarg :amount :accessor amount)))

(defclass credit-card (payment)
  ((number :initarg :number :accessor number)
   (expiry :initarg :expiry :accessor expiry)))

(defclass paypal (payment)
  ((email :initarg :email :accessor email)))

(defgeneric handle-payment (payment))

(defmethod handle-payment ((payment cash))
  (format t "Cash amount: ~a" (amount payment)))

(defmethod handle-payment ((payment credit-card))
  (format t "Card: ~a" (number payment)))

(defmethod handle-payment ((payment paypal))
  (format t "PayPal: ~a" (email payment)))
Advanced
25. What are generics in Lisp?

Lisp is dynamically typed, so generics aren't needed. However, type checking and constraints can be implemented with typep.

  • Dynamic typing: Values can be any type
  • Type checking: typep
  • Constraints: Validation in functions
  • Variance: Not applicable
  • Polymorphism: Generic functions
lisp
;; Generics in Lisp
;; Lisp is dynamically typed, so generics are less needed
;; But we can implement some patterns

;; Generic class using CLOS
(defclass box ()
  ((value :initarg :value :accessor value)))

;; Generic function
(defun swap (first second)
  (values second first))

;; Generic with constraints
(defun sum-numbers (items)
  (apply #'+ items))

;; Variance - using classes
(defclass producer ()
  ((produce :initarg :produce :accessor produce)))

(defclass consumer ()
  ((consume :initarg :consume :accessor consume)))

;; Invariant
(defclass transformer ()
  ((transform :initarg :transform :accessor transform)))

;; Generic function with type checking
(defun process-sequence (seq)
  (mapcar (lambda (x) (format nil "~a" x)) seq))

;; Usage
(defparameter *box* (make-instance 'box :value "Hello"))
(value *box*)

(multiple-value-bind (a b) (swap 1 2)
  (format t "~a, ~a" a b))

(sum-numbers '(1 2 3 4 5))
Advanced
26. What is delegation in Lisp?

Delegation in Lisp is implemented using composition and forwarding methods. Classes can delegate to other objects.

  • Composition: Using instance variables
  • Forwarding: Methods that call delegates
  • Lazy initialization: Compute on demand
  • Observable: Custom delegation patterns
  • Vetoable: Validation before delegation
lisp
;; Delegation in Lisp
;; Class delegation using composition
(defclass repository ()
  ())

(defgeneric get-data (repo))
(defgeneric save-data (repo data))

(defclass database-repository (repository)
  ())

(defmethod get-data ((repo database-repository))
  "Data from database")

(defmethod save-data ((repo database-repository) data)
  (format t "Saving to database: ~a" data))

;; Delegation
(defclass cached-repository (repository)
  ((delegate :initarg :delegate :accessor delegate)
   (cache :initform nil :accessor cache)))

(defmethod get-data ((repo cached-repository))
  (or (cache repo)
      (let ((data (get-data (delegate repo))))
        (setf (cache repo) data)
        data)))

;; Property delegation (lazy)
(defclass lazy-property ()
  ((expensive-value :initform nil :accessor expensive-value)))

(defun get-expensive-value (obj)
  (unless (slot-value obj 'expensive-value)
    (format t "Computing...")
    (setf (slot-value obj 'expensive-value) "Result"))
  (slot-value obj 'expensive-value))

;; Observable property
(defclass observable-property ()
  ((name :initform "Initial" :accessor name)))

(defgeneric set-name (obj value))

(defmethod set-name ((obj observable-property) value)
  (let ((old (name obj)))
    (setf (slot-value obj 'name) value)
    (format t "~a -> ~a" old value)))

;; Usage
(defparameter *db* (make-instance 'database-repository))
(defparameter *cached* (make-instance 'cached-repository :delegate *db*))
(get-data *cached*)
(get-data *cached*)

(defparameter *lazy* (make-instance 'lazy-property))
(get-expensive-value *lazy*)
(get-expensive-value *lazy*)
Advanced
27. What are object declarations and singletons?

Lisp implements singletons using closures or packages. A closure can encapsulate private state and provide controlled access.

  • Closure: Function with private state
  • Package: Namespace with global state
  • Thread-safe: Locking mechanisms
  • Global access: Through exported symbols
  • Initialization: Automatic on load
lisp
;; Object Declarations and Singletons in Lisp
;; Singleton using closure
(defun make-app-config ()
  (let ((api-url "https://api.example.com")
        (timeout 5000))
    (lambda (command &optional value)
      (cond
        ((eq command 'get-api-url) api-url)
        ((eq command 'get-timeout) timeout)
        ((eq command 'print-config) 
         (format t "API URL: ~a~%Timeout: ~a" api-url timeout))
        (t nil)))))

(defparameter *app-config* (make-app-config))

;; Singleton using package
(defpackage :app-config
  (:use :cl)
  (:export :api-url :timeout :print-config))

(in-package :app-config)
(defparameter *api-url* "https://api.example.com")
(defparameter *timeout* 5000)
(defun print-config ()
  (format t "API URL: ~a~%Timeout: ~a" *api-url* *timeout*))

(in-package :cl)

;; Usage
(funcall *app-config* 'get-api-url)
(funcall *app-config* 'print-config)
app-config::*api-url*
Advanced
28. How to create DSL in Lisp?

Lisp macros are perfect for creating DSLs. They allow custom syntax and compile-time code generation.

  • Macros: defmacro
  • Builder pattern: Configure with macros
  • Lambdas: For custom syntax
  • Scope functions: with-* macros
  • Type-safe builders: HTML, XML, etc.
lisp
;; DSL (Domain Specific Language) in Lisp
;; HTML DSL
(defmacro html (&body body)
  `(with-output-to-string (*standard-output*)
     ,@body))

(defmacro body (&body body)
  `(progn
     (format t "<body>")
     ,@body
     (format t "</body>")))

(defmacro h1 (text)
  `(format t "<h1>~a</h1>" ,text))

(defmacro p (text)
  `(format t "<p>~a</p>" ,text))

;; Builder pattern
(defclass user-builder ()
  ((name :initform "" :accessor name)
   (age :initform 0 :accessor age)
   (email :initform "" :accessor email)))

(defun build-user (builder)
  (list :name (name builder)
        :age (age builder)
        :email (email builder)))

;; User creation function
(defun user (&rest args)
  (let ((builder (make-instance 'user-builder)))
    (dolist (arg args)
      (cond
        ((eq (car arg) :name) (setf (name builder) (cdr arg)))
        ((eq (car arg) :age) (setf (age builder) (cdr arg)))
        ((eq (car arg) :email) (setf (email builder) (cdr arg)))))
    (build-user builder)))

;; Usage
(html
 (body
  (h1 "Welcome to Lisp DSL")
  (p "This is a paragraph")
  (p "Another paragraph")))

(user :name "Alice" :age 25 :email "alice@example.com")
Advanced
29. What are annotations in Lisp?

Lisp uses metadata and macros for annotations. Functions can have metadata attached using get and setf.

  • Metadata: (setf (get symbol 'annotations) value)
  • Macros: defmacro for custom annotations
  • Reflection: Inspecting metadata
  • Repeatable: Multiple annotations
  • Usage: get to retrieve
lisp
;; Annotations in Lisp (using meta-programming)
;; Lisp doesn't have built-in annotations like Kotlin
;; Using macros and metadata

;; Custom annotation macro
(defmacro defannotated (name &rest body)
  `(progn
     (defparameter ,name
       (list :annotations ',(car body) :value ,(cadr body)))))

;; Using metadata
(defun annotate (obj &rest annotations)
  (setf (get obj 'annotations) annotations))

(defun get-annotations (obj)
  (get obj 'annotations))

;; Example usage
(defun annotated-method ()
  (format t "Annotated method"))

(annotate 'annotated-method :value "test")

;; Reflection simulation
(defun read-annotations (symbol)
  (get symbol 'annotations))

;; Repeatable annotations
(defun add-annotation (symbol annotation)
  (push annotation (get symbol 'annotations)))

(add-annotation 'annotated-method :permission "read")
(add-annotation 'annotated-method :permission "write")

;; Usage
(annotated-method)
(read-annotations 'annotated-method)
Advanced
30. How to use reflection in Lisp?

Lisp provides reflection through CLOS and the Meta-Object Protocol (MOP). Classes, slots, and methods can be inspected at runtime.

  • Class: class-name, class-of
  • Slots: class-slots
  • Methods: generic-function-methods
  • Call: funcall for dynamic calls
  • Constructors: make-instance
lisp
;; Reflection in Lisp
;; Reflection capabilities using CLOS and meta-object protocol

;; Class for reflection examples
(defclass person ()
  ((name :initarg :name :accessor name)
   (age :initarg :age :accessor age)
   (city :initarg :city :accessor city
         :initform "Unknown")))

(defmethod greet ((obj person))
  (format nil "Hello, my name is ~a" (name obj)))

(defmethod update-age ((obj person) new-age)
  (setf (age obj) new-age))

;; Basic reflection
(defun basic-reflection ()
  (let ((person (make-instance 'person :name "Alice" :age 25)))
    (format t "Class: ~a" (class-name (class-of person)))
    (format t "Slots: ~a" (closer-mop:class-slots (class-of person)))))

;; Accessing slots
(defun access-slots ()
  (let ((person (make-instance 'person :name "Alice" :age 25)))
    (dolist (slot (closer-mop:class-slots (class-of person)))
      (let ((name (closer-mop:slot-definition-name slot)))
        (format t "~a = ~a" name (slot-value person name))))))

;; Calling functions
(defun call-functions ()
  (let ((person (make-instance 'person :name "Alice" :age 25)))
    (format t "~a" (greet person))
    (update-age person 30)
    (format t "Updated age: ~a" (age person))))

;; Create instance
(defun create-instance ()
  (make-instance 'person :name "Bob" :age 30 :city "NYC"))
Advanced
31. What are coroutine contexts and dispatchers?

Threads in Lisp can be used with different priorities and thread-local storage for context management.

  • Threads: sb-thread:make-thread
  • Context: *thread-local*
  • Dispatcher: Thread pools
  • Custom context: Named threads
  • Thread-local: make-hash-table
lisp
;; Coroutine Context and Dispatchers in Lisp
;; Using threads with different priorities

;; Different dispatchers simulation
(defun dispatcher-example ()
  (let ((threads '()))
    ;; Default
    (push (sb-thread:make-thread
           (lambda () (format t "Default: ~a" (sb-thread:thread-name sb-thread:*current-thread*))))
          threads)
    ;; IO
    (push (sb-thread:make-thread
           (lambda () (format t "IO: ~a" (sb-thread:thread-name sb-thread:*current-thread*))))
          threads)
    ;; Main (current thread)
    (format t "Main: ~a" (sb-thread:thread-name sb-thread:*current-thread*))
    (dolist (thread threads)
      (sb-thread:join-thread thread))))

;; Custom context
(defun custom-context ()
  (sb-thread:make-thread
   (lambda ()
     (format t "Context: Custom"))))

;; ThreadLocal simulation
(defparameter *thread-local* (make-hash-table))

(defun get-thread-local ()
  (gethash (sb-thread:thread-name sb-thread:*current-thread*) *thread-local*))

(defun set-thread-local (value)
  (setf (gethash (sb-thread:thread-name sb-thread:*current-thread*) *thread-local*) value))

(defun thread-local-example ()
  (set-thread-local "Main")
  (let ((thread (sb-thread:make-thread
                 (lambda ()
                   (set-thread-local "IO")
                   (format t "ThreadLocal: ~a" (get-thread-local))))))
    (sb-thread:join-thread thread))
  (format t "ThreadLocal restored: ~a" (get-thread-local)))
Advanced
32. How to handle shared mutable state in coroutines?

Lisp uses locks and mutexes for synchronization. sb-thread:with-mutex ensures thread-safe operations.

  • Mutex: sb-thread:make-mutex
  • Atomic: sb-thread:with-mutex
  • Single-threaded: Using thread pools
  • Actor: State encapsulation
  • Channels: Communication between threads
lisp
;; Shared Mutable State in Coroutines (Lisp)
;; Using locks for synchronization

;; Counter with mutex
(defclass counter-with-mutex ()
  ((value :initform 0 :accessor value)
   (lock :initform (sb-thread:make-mutex) :accessor lock)))

(defun increment-counter (counter)
  (sb-thread:with-mutex ((lock counter))
    (incf (value counter))))

(defun get-counter-value (counter)
  (value counter))

;; Using atomic operations
(defclass counter-with-atomic ()
  ((value :initform 0 :accessor value)))

(defun increment-atomic (counter)
  (sb-thread:with-mutex ((lock counter))
    (incf (value counter))))

;; Single-threaded dispatcher
(defclass counter-with-single-thread ()
  ((value :initform 0 :accessor value)
   (lock :initform (sb-thread:make-mutex) :accessor lock)))

(defun increment-single (counter)
  (sb-thread:with-mutex ((lock counter))
    (incf (value counter))))

;; Usage
(defun counter-example ()
  (let ((counter (make-instance 'counter-with-mutex)))
    (loop for i from 1 to 1000
          do (sb-thread:make-thread
              (lambda ()
                (dotimes (j 100)
                  (increment-counter counter)))))
    (sleep 5)
    (format t "Final count: ~a" (get-counter-value counter))))
Advanced
33. What are flow operators and transformations?

Lisp streams can be transformed using functions like mapcar, remove-if-not, and custom stream operators.

  • filter: remove-if-not
  • map: mapcar
  • buffer: Custom buffering
  • conflate: Drop intermediate values
  • collect latest: Latest value processing
lisp
;; Flow Operators and Transformations in Lisp
;; Stream transformations using functions

;; Simple stream
(defun make-number-stream (n)
  (let ((i 0))
    (lambda ()
      (if (< i n)
          (prog1 i (incf i))
          nil))))

;; Basic flow transformation
(defun flow-transform-example ()
  (let ((stream (make-number-stream 10)))
    (loop for val = (funcall stream)
          while val
          when (evenp val)
            do (format t "Number ~a" val))))

;; Flow with buffer
(defun flow-buffer-example ()
  (let ((stream (make-number-stream 5)))
    (loop for val = (funcall stream)
          while val
          do (format t "~a" val))))

;; Flow with conflate (drop intermediate values)
(defun flow-conflate-example ()
  (let ((stream (make-number-stream 10)))
    (loop for val = (funcall stream)
          while val
          do (progn
               (sleep 0.1)
               (format t "~a" val)))))

;; Flow with collect latest
(defun flow-collect-latest-example ()
  (let ((stream (make-number-stream 10)))
    (loop for val = (funcall stream)
          while val
          do (progn
               (format t "Processing ~a" val)
               (sleep 0.1)
               (format t "Done ~a" val)))))

;; FlatMap (flattening streams)
(defun flow-flatmap-example ()
  (let ((stream (make-number-stream 3)))
    (loop for val = (funcall stream)
          while val
          do (loop for letter in '(a b)
                   do (format t "~a-~a" val letter)))))
Advanced
34. What are coroutine scopes and lifecycle?

Thread management in Lisp provides lifecycle control. Threads can be created, joined, and terminated.

  • Scope: Custom thread managers
  • Lifecycle: sb-thread:make-thread
  • GlobalScope: Application-wide threads
  • SupervisorJob: Independent job hierarchy
  • Cancellation: Thread termination
lisp
;; Coroutine Scopes and Lifecycle in Lisp
;; Using thread pools and managers

;; Custom scope with job
(defclass my-scope ()
  ((threads :initform '() :accessor threads)
   (cancelled :initform nil :accessor cancelled)))

(defun scope-launch (scope fn)
  (push (sb-thread:make-thread fn) (threads scope)))

(defun scope-cancel (scope)
  (setf (cancelled scope) t)
  (dolist (thread (threads scope))
    (sb-thread:terminate-thread thread)))

;; Lifecycle-aware scope
(defclass lifecycle-scope (my-scope)
  ())

(defun launch-when-created (scope fn)
  (scope-launch scope fn))

(defun on-destroy (scope)
  (scope-cancel scope))

;; GlobalScope vs CoroutineScope
(defun scope-comparison ()
  ;; GlobalScope - runs until complete
  (sb-thread:make-thread
   (lambda ()
     (sleep 1)
     (format t "GlobalScope")))

  ;; CoroutineScope - tied to parent
  (let ((scope (make-instance 'my-scope)))
    (scope-launch scope
                  (lambda ()
                    (sleep 1)
                    (format t "CoroutineScope")))
    (sleep 2)
    (scope-cancel scope)))

;; Scope with timeout
(defun timeout-scope (seconds fn)
  (let ((thread (sb-thread:make-thread fn)))
    (sleep seconds)
    (if (sb-thread:thread-alive-p thread)
        (progn
          (sb-thread:terminate-thread thread)
          (format t "Timed out")
          nil)
        (sb-thread:join-thread thread))))
Advanced
35. What are SharedFlow and StateFlow?

Lisp can implement state and shared flows using observers and state management patterns with closures or classes.

  • StateFlow: defclass state-flow
  • SharedFlow: defclass shared-flow
  • Replay: Store last N values
  • Update: state-flow-update
  • Combine: combine-flows
lisp
;; SharedFlow and StateFlow in Lisp
;; Using observers and state management

;; StateFlow simulation
(defclass state-flow ()
  ((value :initform nil :accessor value)
   (observers :initform '() :accessor observers)))

(defun state-flow-update (flow new-value)
  (setf (value flow) new-value)
  (dolist (observer (observers flow))
    (funcall observer new-value)))

(defun state-flow-observe (flow callback)
  (push callback (observers flow)))

;; SharedFlow simulation
(defclass shared-flow ()
  ((events :initform '() :accessor events)
   (replay :initarg :replay :accessor replay)
   (replayed :initform '() :accessor replayed)
   (observers :initform '() :accessor observers)))

(defun shared-flow-emit (flow event)
  (push event (events flow))
  (setf (replayed flow) (cons event (replayed flow)))
  (when (> (length (replayed flow)) (replay flow))
    (setf (replayed flow) (subseq (replayed flow) 0 (replay flow))))
  (dolist (observer (observers flow))
    (funcall observer event)))

;; Distinct until changed
(defun distinct-example (flow)
  (let ((last-value nil))
    (state-flow-observe flow
                        (lambda (value)
                          (unless (equal value last-value)
                            (setf last-value value)
                            (format t "~a" value))))))

;; Combine flows
(defun combine-flows (flow1 flow2)
  (let ((result (make-instance 'state-flow)))
    (state-flow-observe flow1
                        (lambda (value)
                          (state-flow-update result
                                             (+ value (value flow2)))))
    (state-flow-observe flow2
                        (lambda (value)
                          (state-flow-update result
                                             (+ (value flow1) value))))))
Advanced
36. How to handle exceptions in coroutines?

Lisp uses handler-case and handler-bind for exception handling in threads.

  • Try-catch: handler-case
  • ExceptionHandler: Custom handlers
  • SupervisorJob: Isolate failures
  • Flow catch: handler-case
  • SupervisorScope: handler-case
lisp
;; Coroutine Exception Handling in Lisp
;; Using handler-case and handler-bind

;; Try-catch in thread
(defun try-catch-example ()
  (handler-case
      (sb-thread:make-thread
       (lambda ()
         (error "Error")))
    (error (e)
      (format t "Caught: ~a" e))))

;; Exception handler
(defun exception-handler ()
  (handler-case
      (sb-thread:make-thread
       (lambda ()
         (error "Test")))
    (error (e)
      (format t "Handler caught: ~a" e))))

;; Supervisor job for child isolation
(defun supervisor-example ()
  (let ((threads '()))
    ;; Child 1
    (push (sb-thread:make-thread
           (lambda ()
             (handler-case
                 (progn
                   (sleep 0.1)
                   (error "Child 1 error"))
               (error (e)
                 (format t "Child 1 caught: ~a" e)))))
          threads)
    ;; Child 2
    (push (sb-thread:make-thread
           (lambda ()
             (sleep 0.2)
             (format t "Child 2 still running")))
          threads)
    (dolist (thread threads)
      (sb-thread:join-thread thread))))

;; Flow exception handling
(defun flow-exception ()
  (handler-case
      (progn
        (format t "~a" 1)
        (error "Flow error"))
    (error (e)
      (format t "Flow caught: ~a" e)
      (format t "-1"))))

;; Supervisor scope
(defun supervisor-scope-example ()
  (let ((threads '()))
    (push (sb-thread:make-thread
           (lambda ()
             (error "Error")))
          threads)
    (push (sb-thread:make-thread
           (lambda ()
             (sleep 0.1)
             (format t "Still running")))
          threads)
    (dolist (thread threads)
      (sb-thread:join-thread thread))))
Advanced
37. What are channel producers and consumer patterns?

Lisp can implement producer-consumer patterns using queues and threads.

  • Producer-consumer: Single producer, single consumer
  • Fan-out: Multiple consumers
  • Fan-in: Multiple producers
  • Pipelines: Chained operations
  • Buffer: Queue capacity
lisp
;; Channel Producers and Consumer Patterns in Lisp
;; Using queues for producer-consumer patterns

;; Producer-Consumer pattern
(defun producer-consumer ()
  (let ((queue (make-instance 'queue)))
    ;; Producer
    (sb-thread:make-thread
     (lambda ()
       (dotimes (i 20)
         (queue-enqueue queue i)
         (format t "Produced: ~a" i)
         (sleep 0.1))))
    ;; Consumer
    (sb-thread:make-thread
     (lambda ()
       (dotimes (i 20)
         (let ((val (queue-dequeue queue)))
           (when val
             (format t "Consumed: ~a" val)
             (sleep 0.15))))))))

;; Fan-out pattern
(defun fan-out-example ()
  (let ((queue (make-instance 'queue)))
    ;; Producer
    (sb-thread:make-thread
     (lambda ()
       (dotimes (i 20)
         (queue-enqueue queue i))))
    ;; Multiple consumers
    (dotimes (id 3)
      (sb-thread:make-thread
       (lambda ()
         (dotimes (i 20)
           (let ((val (queue-dequeue queue)))
             (when val
               (format t "Consumer ~a: ~a" id val)
               (sleep 0.1)))))))))

;; Fan-in pattern
(defun fan-in-example ()
  (let ((queue (make-instance 'queue)))
    ;; Multiple producers
    (dotimes (id 3)
      (sb-thread:make-thread
       (lambda ()
         (dotimes (i 5)
           (queue-enqueue queue (format nil "Producer ~a: ~a" id i))
           (sleep 0.05)))))
    ;; Single consumer
    (sb-thread:make-thread
     (lambda ()
       (dotimes (i 15)
         (format t "~a" (queue-dequeue queue)))))))
Advanced
38. How to handle thread cancellation?

Lisp threads support cancellation through sb-thread:terminate-thread and cooperative cancellation using flags.

  • Check flag: when cancelled (return)
  • Cancel: sb-thread:terminate-thread
  • Finally: unwind-protect
  • NonCancellable: Custom flag
  • Timeout: sleep and termination
lisp
;; Coroutine Cancellation in Lisp
;; Thread termination and cooperative cancellation

;; Cooperative cancellation
(defun cooperative-cancellation ()
  (let ((cancelled nil))
    (sb-thread:make-thread
     (lambda ()
       (dotimes (i 100)
         (when cancelled (return))
         (format t "Working: ~a" i)
         (sleep 0.05))))

    (sleep 0.2)
    (setf cancelled t)))

;; Cancellation with finally
(defun cancellation-finally ()
  (let ((cancelled nil))
    (sb-thread:make-thread
     (lambda ()
       (unwind-protect
           (dotimes (i 100)
             (when cancelled (return))
             (format t "Processing: ~a" i)
             (sleep 0.1))
         (format t "Cleaning up")
         (sleep 0.1)
         (format t "Cleanup done"))))
    (sleep 0.25)
    (setf cancelled t)))

;; Cancellation with timeout
(defun cancellation-timeout ()
  (let ((thread (sb-thread:make-thread
                 (lambda ()
                   (dotimes (i 10)
                     (sleep 0.2)
                     (format t "Iteration: ~a" i))))))
    (sleep 1)
    (sb-thread:terminate-thread thread)
    (format t "Timed out")))

;; Custom cancellation check
(defun custom-cancellation ()
  (let ((cancelled nil))
    (sb-thread:make-thread
     (lambda ()
       (let ((i 0))
         (loop while (and (not cancelled) (< i 1000))
               do (when (= (mod i 100) 0)
                    (format t "Still running: ~a" i))
                  (incf i)
                  (sleep 0.001)))))
    (sleep 0.1)
    (setf cancelled t)))
Advanced
39. How to test threads?

Lisp testing frameworks like fiveam or lisp-unit can test threaded code with assertions.

  • runTest: Custom test runner
  • advanceTimeBy: sleep for timing
  • advanceUntilIdle: Wait for threads
  • TestDispatcher: Custom thread management
  • Assertions: assert
lisp
;; Testing Coroutines in Lisp
;; Using unit testing frameworks

;; Basic test function
(defun test-coroutine ()
  (let ((result nil))
    (sb-thread:make-thread
     (lambda ()
       (sleep 1)
       (setf result "Success")))
    (sleep 1.5)
    (assert (equal result "Success") () "Test failed")))

;; Test with delay
(defun test-with-delay ()
  (let ((result nil))
    (sb-thread:make-thread
     (lambda ()
       (sleep 1)
       (setf result "Done")))
    ;; Simulate advance time
    (sleep 1)
    (assert (equal result "Done") () "Test failed")))

;; Test multiple coroutines
(defun test-multiple-coroutines ()
  (let ((results '()))
    (sb-thread:make-thread
     (lambda ()
       (sleep 0.5)
       (push "Task 1" results)))
    (sb-thread:make-thread
     (lambda ()
       (sleep 0.3)
       (push "Task 2" results)))
    (sleep 1)
    (assert (equal results '("Task 2" "Task 1")) () "Test failed")))

;; Test flow
(defun test-flow ()
  (let ((values '()))
    (dotimes (i 2)
      (push i values))
    (assert (equal values '(1 0)) () "Test failed")))

;; Time control test
(defun time-control-test ()
  (let ((counter 0)
        (running t))
    (sb-thread:make-thread
     (lambda ()
       (loop while running
             do (sleep 1)
                (incf counter))))
    (sleep 3)
    (setf running nil)
    (assert (<= counter 4) () "Test failed")))
Advanced
40. What is Lisp Multiplatform?

Lisp implementations can be ported across platforms. Feature flags (#+sbcl, #+clisp) handle platform-specific code.

  • Feature flags: #+sbcl, #+clisp
  • Platform-specific: Different implementations
  • Serialization: format
  • Cross-platform: Portable code
  • Implementation: SBCL, CLISP, CCL, ABCL
lisp
;; Lisp Multiplatform (different implementations)
;; Using feature flags and different implementations

;; Platform-specific code
(defun platform-name ()
  #+sbcl "SBCL"
  #+clisp "CLISP"
  #+ccl "CCL"
  #+abcl "ABCL"
  #-(or sbcl clisp ccl abcl) "Unknown")

(defun greet ()
  (format nil "Hello from ~a" (platform-name)))

;; Platform-specific class simulation
(defclass platform ()
  ())

(defmethod get-version ((obj platform))
  #+sbcl "2.2.0"
  #+clisp "2.49"
  #+ccl "1.12"
  #+abcl "1.8.0"
  #-(or sbcl clisp ccl abcl) "Unknown")

;; Platform info
(defclass platform-info ()
  ())

(defun get-info ()
  (format nil "~a version ~a" 
          (greet) (get-version (make-instance 'platform))))

;; Multiplatform with serialization
(defun encode-user (user)
  (format nil "~a~%~a~%~a" 
          (getf user :id)
          (getf user :name)
          (getf user :email)))

(defun decode-user (data)
  (let ((lines (split-string data #Newline)))
    (list :id (parse-integer (first lines))
          :name (second lines)
          :email (third lines))))
Coding Round
41. Reverse a string

Reverse a string using reverse or manual iteration.

  • Built-in: (reverse str)
  • Manual: (with-output-to-string ...)
  • Complexity: O(n) time
lisp
;; Reverse a string
(defun reverse-string (str)
  (reverse str))
(format t "~a" (reverse-string "hello")) ; "olleh"

;; Using loop
(defun reverse-string-loop (str)
  (with-output-to-string (s)
    (do ((i (1- (length str)) (1- i)))
        ((< i 0))
      (write-char (char str i) s))))
Coding Round
42. Check palindrome

Check if a string is a palindrome using reverse or two-pointer approach.

  • Method: (string= cleaned (reverse cleaned))
  • Two-pointer: Compare from both ends
  • Case insensitive: string-downcase
  • Ignore non-alphanumeric: remove-if-not #'alphanumericp
lisp
;; Check palindrome
(defun is-palindrome (str)
  (let ((cleaned (string-downcase 
                  (remove-if-not #'alphanumericp str))))
    (string= cleaned (reverse cleaned))))
(format t "~a" (is-palindrome "racecar")) ; t
(format t "~a" (is-palindrome "hello")) ; nil

;; Two-pointer approach
(defun is-palindrome-two-pointer (str)
  (let ((cleaned (string-downcase 
                  (remove-if-not #'alphanumericp str)))
        (left 0)
        (right (1- (length str))))
    (loop while (< left right)
          do (if (char/= (char cleaned left) (char cleaned right))
                 (return nil)
                 (progn (incf left) (decf right))))))
Coding Round
43. Find max in array

Find maximum value using reduce #'max or manual iteration.

  • Built-in: (reduce #'max arr)
  • Manual: Iterate and track max
  • Empty array: Handle with error
  • Complexity: O(n) time
lisp
;; Find max in array
(defun find-max (arr)
  (if (null arr)
      (error "Empty array")
      (reduce #'max arr)))
(format t "~a" (find-max '(1 5 3 9 2))) ; 9

;; Manual implementation
(defun find-max-manual (arr)
  (let ((max-val (car arr)))
    (dolist (num (cdr arr))
      (when (> num max-val)
        (setf max-val num)))
    max-val))
Coding Round
44. Remove duplicates

Remove duplicates using remove-duplicates or manual set implementation.

  • Built-in: (remove-duplicates arr)
  • Manual: Track seen elements
  • Complexity: O(n²) or O(n)
lisp
;; Remove duplicates
(defun remove-duplicates-list (arr)
  (remove-duplicates arr))
(format t "~a" (remove-duplicates-list '(1 2 2 3 3 4))) ; (1 2 3 4)

;; Using set
(defun remove-duplicates-set (arr)
  (coerce (make-hash-table) 'list))
Coding Round
45. Merge arrays

Merge arrays using append or manual concatenation.

  • Built-in: (append arr1 arr2)
  • Alternative: (concatenate 'list arr1 arr2)
  • Unique: remove-duplicates
lisp
;; Merge arrays
(defun merge-arrays (arr1 arr2)
  (append arr1 arr2))
(format t "~a" (merge-arrays '(1 2) '(3 4))) ; (1 2 3 4)

;; Alternative
(defun merge-arrays-plus (arr1 arr2)
  (append arr1 arr2))
Coding Round
46. Convert string to number

Convert using parse-integer or safe conversion.

  • toInt: (parse-integer str)
  • Safe: handler-case
  • Error handling: Return nil on failure
lisp
;; Convert string to number
(defun string-to-number (str)
  (parse-integer str))
(format t "~a" (string-to-number "42")) ; 42

;; Safe conversion
(defun string-to-number-safe (str)
  (handler-case
      (parse-integer str)
    (error () nil)))
Coding Round
47. Loop through map

Iterate through alist using dolist or mapc.

  • dolist: (dolist (pair alist) ...)
  • mapc: (mapc (lambda (pair) ...) alist)
  • Keys: mapcar #'car
  • Values: mapcar #'cdr
lisp
;; Loop through map (alist)
(defun loop-map (alist)
  (dolist (pair alist)
    (format t "~a => ~a" (car pair) (cdr pair))))

;; Alternative
(defun loop-map-alternate (alist)
  (mapc (lambda (pair)
          (format t "~a => ~a" (car pair) (cdr pair)))
        alist))

(loop-map '((name . "Alice") (age . 25) (city . "NYC")))
Coding Round
48. Delay function execution

Delay using sleep or threads.

  • Sleep: (sleep (/ delay-ms 1000))
  • Thread: sb-thread:make-thread
  • Async: sb-thread:make-thread
lisp
;; Delay function execution
(defun delayed-execution (delay-ms fn)
  (sleep (/ delay-ms 1000))
  (funcall fn))

;; Example usage
(delayed-execution 2000
                   (lambda ()
                     (format t "After 2 seconds")))

;; Using threads
(defun delayed-execution-thread (delay-ms fn)
  (sb-thread:make-thread
   (lambda ()
     (sleep (/ delay-ms 1000))
     (funcall fn))))
Coding Round
49. HTTP GET request

Make HTTP GET using drakma:http-request or url-request.

  • Drakma: (drakma:http-request url)
  • URL-Request: (url-request:url-request url)
  • Stream reading: read-line
lisp
;; HTTP GET request
(defun fetch-data (url)
  (let ((stream (drakma:http-request url)))
    (when stream
      (with-output-to-string (s)
        (do ((line (read-line stream nil nil)
                   (read-line stream nil nil)))
            ((null line))
          (write-line line s))))))

;; Alternative using URL-REQUES
(defun fetch-data-url (url)
  (let ((stream (url-request:url-request url)))
    (if stream
        (with-output-to-string (s)
          (do ((line (read-line stream nil nil)
                     (read-line stream nil nil)))
              ((null line))
            (write-line line s)))
        nil)))
Coding Round
50. Create a promise-like Deferred

Create a Deferred using threads and state management.

  • Thread: sb-thread:make-thread
  • await: sb-thread:join-thread
  • Error handling: handler-case
lisp
;; Create a promise-like Deferred
(defun create-deferred (should-resolve)
  (let ((thread nil)
        (result nil))
    (setf thread (sb-thread:make-thread
                  (lambda ()
                    (sleep 1)
                    (if should-resolve
                        (setf result "Success!")
                        (error "Failed!")))))
    (lambda ()
      (sb-thread:join-thread thread)
      result)))

;; Usage
(defparameter *deferred* (create-deferred t))
(handler-case
    (format t "~a" (funcall *deferred*))
  (error (e)
    (format t "Caught: ~a" e)))
Coding Round
51. Factorial

Calculate factorial using recursion or iteration.

  • Recursive: (if (<= n 1) 1 (* n (factorial (- n 1))))
  • Iterative: do loop
  • Edge cases: 0! = 1
lisp
;; Factorial
(defun factorial (n)
  (if (<= n 1)
      1
      (* n (factorial (- n 1)))))
(format t "~a" (factorial 5)) ; 120

;; Iterative version
(defun factorial-iterative (n)
  (do ((i 2 (1+ i))
       (result 1 (* result i)))
      ((> i n) result)))
Coding Round
52. Fibonacci

Calculate Fibonacci using recursion, iteration, or memoization.

  • Recursive: (if (<= n 1) n (+ (fib (- n 1)) (fib (- n 2))))
  • Iterative: do loop
  • Memoization: memoize
lisp
;; Fibonacci
(defun fibonacci (n)
  (if (<= n 1)
      n
      (+ (fibonacci (- n 1)) (fibonacci (- n 2)))))
(format t "~a" (fibonacci 8)) ; 21

;; Iterative version
(defun fibonacci-iterative (n)
  (do ((a 0 b)
       (b 1 (+ a b))
       (i 2 (1+ i)))
      ((> i n) b)))
Coding Round
53. FizzBuzz

FizzBuzz using cond for modular arithmetic.

  • When expression: cond
  • Order: Check 15 first
  • Range: dotimes
lisp
;; FizzBuzz
(defun fizzbuzz (n)
  (dotimes (i n)
    (let ((num (1+ i)))
      (cond
        ((zerop (mod num 15)) (format t "FizzBuzz"))
        ((zerop (mod num 3)) (format t "Fizz"))
        ((zerop (mod num 5)) (format t "Buzz"))
        (t (format t "~a" num))))))
(fizzbuzz 15)
Coding Round
54. Find missing number

Find missing number using formula or XOR.

  • Formula: (- total sum)
  • XOR method: XOR all numbers and indices
  • Edge cases: Empty array
lisp
;; Find missing number
(defun find-missing (arr)
  (let* ((n (1+ (length arr)))
         (total (/ (* n (1+ n)) 2))
         (sum (reduce #'+ arr)))
    (- total sum)))
(format t "~a" (find-missing '(1 2 4 5 6))) ; 3
Coding Round
55. Find duplicates

Find duplicates using a set or hash table.

  • Set method: Track seen elements
  • Filter: remove-if
  • Group by: group-by simulation
lisp
;; Find duplicates
(defun find-duplicates (arr)
  (let ((seen '())
        (duplicates '()))
    (dolist (item arr)
      (if (member item seen)
          (push item duplicates)
          (push item seen)))
    duplicates))
(format t "~a" (find-duplicates '(1 2 3 2 4 3))) ; (3 2)
Coding Round
56. Sum of array

Calculate sum using reduce or manual iteration.

  • Built-in: (reduce #'+ arr)
  • Manual: dolist
  • Empty array: Returns 0
lisp
;; Sum of array
(defun sum-array (arr)
  (reduce #'+ arr))
(format t "~a" (sum-array '(1 2 3 4 5))) ; 15

;; Manual implementation
(defun sum-array-manual (arr)
  (let ((sum 0))
    (dolist (num arr)
      (incf sum num))
    sum))
Coding Round
57. Average of array

Calculate average using sum divided by length.

  • Method: (/ (reduce #'+ arr) (length arr))
  • Empty array: Handle with if check
  • Precision: Returns rational
lisp
;; Average of array
(defun average-array (arr)
  (/ (reduce #'+ arr) (length arr)))
(format t "~a" (average-array '(1 2 3 4 5))) ; 3

;; Manual implementation
(defun average-array-manual (arr)
  (/ (sum-array-manual arr) (length arr)))
Coding Round
58. Sort array ascending

Sort using sort with #'<.

  • Non-mutating: (sort (copy-seq arr) #'<)
  • Mutating: (sort arr #'<)
  • Complexity: O(n log n)
lisp
;; Sort array ascending
(defun sort-ascending (arr)
  (sort (copy-seq arr) #'<))
(format t "~a" (sort-ascending '(5 2 8 1 9))) ; (1 2 5 8 9)

;; In-place sorting
(defun sort-ascending-in-place (arr)
  (sort arr #'<))
Coding Round
59. Sort array descending

Sort descending using sort with #'>.

  • Non-mutating: (sort (copy-seq arr) #'>)
  • Mutating: (sort arr #'>)
  • Complexity: O(n log n)
lisp
;; Sort array descending
(defun sort-descending (arr)
  (sort (copy-seq arr) #'>))
(format t "~a" (sort-descending '(5 2 8 1 9))) ; (9 8 5 2 1)

;; In-place sorting
(defun sort-descending-in-place (arr)
  (sort arr #'>))
Coding Round
60. Flatten nested array

Flatten using recursion or mapcan.

  • Recursive: Check if listp
  • mapcan: (mapcan #'flatten-array arr)
  • Complexity: O(n) time
lisp
;; Flatten nested array
(defun flatten-array (arr)
  (cond
    ((null arr) nil)
    ((listp (car arr)) 
     (append (flatten-array (car arr)) 
             (flatten-array (cdr arr))))
    (t (cons (car arr) (flatten-array (cdr arr))))))
(format t "~a" (flatten-array '(1 (2 (3 4) 5) 6))) ; (1 2 3 4 5 6)

;; Using recursion
(defun flatten-array-recursive (arr)
  (if (atom arr)
      (list arr)
      (mapcan #'flatten-array-recursive arr)))
Coding Round
61. Chunk array

Split array into chunks using loop with by.

  • Method: (loop for i from 0 by size ...)
  • Subseq: (subseq arr i (min (+ i size) ...))
  • Use case: Batch processing
lisp
;; Chunk array
(defun chunk-array (arr size)
  (loop for i from 0 below (length arr) by size
        collect (subseq arr i (min (+ i size) (length arr)))))
(format t "~a" (chunk-array '(1 2 3 4 5 6) 2)) ; ((1 2) (3 4) (5 6))

;; Manual implementation
(defun chunk-array-manual (arr size)
  (let ((result '()))
    (do ((i 0 (+ i size)))
        ((>= i (length arr)))
      (push (subseq arr i (min (+ i size) (length arr))) result))
    (reverse result)))
Coding Round
63. Quick sort

Quick sort using pivot-based partitioning.

  • Algorithm: Choose pivot, partition, recurse
  • Time: O(n log n) average
  • Implementation: Functional style
lisp
;; Quick sort
(defun quick-sort (arr)
  (if (<= (length arr) 1)
      arr
      (let* ((pivot (car arr))
             (rest (cdr arr))
             (left (remove-if-not (lambda (x) (< x pivot)) rest))
             (right (remove-if (lambda (x) (< x pivot)) rest)))
        (append (quick-sort left) (list pivot) (quick-sort right)))))

(format t "~a" (quick-sort '(5 3 8 4 2 7 1 6)))
Coding Round
64. Merge sort

Merge sort using divide-and-conquer.

  • Algorithm: Divide, sort, merge
  • Time: O(n log n)
  • Space: O(n) auxiliary space
lisp
;; Merge sort
(defun merge-sort (arr)
  (if (<= (length arr) 1)
      arr
      (let* ((mid (floor (length arr) 2))
             (left (subseq arr 0 mid))
             (right (subseq arr mid)))
        (merge-lists (merge-sort left) (merge-sort right)))))

(defun merge-lists (left right)
  (cond
    ((null left) right)
    ((null right) left)
    ((<= (car left) (car right))
     (cons (car left) (merge-lists (cdr left) right)))
    (t (cons (car right) (merge-lists left (cdr right))))))
Coding Round
65. Bubble sort

Bubble sort with early termination.

  • Algorithm: Compare adjacent, swap
  • Time: O(n²) worst case
  • Optimization: Stop if no swaps
lisp
;; Bubble sort
(defun bubble-sort (arr)
  (let ((sorted (copy-seq arr)))
    (do ((i 0 (1+ i)))
        ((= i (1- (length sorted))))
      (do ((j 0 (1+ j)))
          ((= j (- (length sorted) 1 i)))
        (when (> (nth j sorted) (nth (1+ j) sorted))
          (rotatef (nth j sorted) (nth (1+ j) sorted)))))
    sorted))

;; Optimized bubble sort
(defun bubble-sort-optimized (arr)
  (let ((sorted (copy-seq arr)))
    (do ((i 0 (1+ i)))
        ((= i (1- (length sorted))))
      (let ((swapped nil))
        (do ((j 0 (1+ j)))
            ((= j (- (length sorted) 1 i)))
          (when (> (nth j sorted) (nth (1+ j) sorted))
            (rotatef (nth j sorted) (nth (1+ j) sorted))
            (setf swapped t)))
        (unless swapped (return sorted))))
    sorted))
Coding Round
66. Intersection of arrays

Find common elements using remove-if-not or hash set.

  • Filter: (remove-if-not (lambda (x) (member x arr2)) arr1)
  • Set: make-hash-table
  • Complexity: O(n²) or O(n)
lisp
;; Intersection of arrays
(defun intersection-arrays (arr1 arr2)
  (remove-if-not (lambda (x) (member x arr2)) arr1))
(format t "~a" (intersection-arrays '(1 2 3 4) '(3 4 5 6))) ; (3 4)

;; Using set for efficiency
(defun intersection-set (arr1 arr2)
  (let ((set2 (make-hash-table)))
    (dolist (item arr2)
      (setf (gethash item set2) t))
    (remove-if-not (lambda (x) (gethash x set2)) arr1)))
Coding Round
67. Union of arrays

Combine arrays with unique elements using remove-duplicates.

  • Method: (remove-duplicates (append arr1 arr2))
  • Set: make-hash-table
  • Complexity: O(n log n)
lisp
;; Union of arrays
(defun union-arrays (arr1 arr2)
  (remove-duplicates (append arr1 arr2)))
(format t "~a" (union-arrays '(1 2 3) '(3 4 5))) ; (1 2 3 4 5)

;; Using set
(defun union-set (arr1 arr2)
  (remove-duplicates (append arr1 arr2)))
Coding Round
68. Difference of arrays

Find elements in first array not in second.

  • Difference: (remove-if (lambda (x) (member x arr2)) arr1)
  • Symmetric: append differences
  • Set: Use hash set for efficiency
lisp
;; Difference of arrays
(defun difference-arrays (arr1 arr2)
  (remove-if (lambda (x) (member x arr2)) arr1))
(format t "~a" (difference-arrays '(1 2 3 4) '(3 4 5 6))) ; (1 2)

;; Symmetric difference
(defun symmetric-difference (arr1 arr2)
  (append (difference-arrays arr1 arr2)
          (difference-arrays arr2 arr1)))
Coding Round
69. Group by property

Group objects by property using hash tables.

  • Method: make-hash-table
  • Grouping: push items into groups
  • Complexity: O(n) time
lisp
;; Group by property
(defun group-by-property (items key)
  (let ((groups (make-hash-table :test 'equal)))
    (dolist (item items)
      (let ((key-value 
             (if (equal key "type")
                 (type item)
                 (name item))))
        (push item (gethash key-value groups))))
    groups))

;; Usage
(defstruct item type name)
(defparameter *data* 
  (list (make-item :type "fruit" :name "apple")
        (make-item :type "fruit" :name "banana")
        (make-item :type "veg" :name "carrot")))

(defun print-groups (groups)
  (maphash (lambda (key value)
             (format t "~a: ~a" key value))
           groups))
Coding Round
70. Deep clone object

Deep clone by recursively copying structures.

  • Method: cond for different types
  • Lists: mapcar
  • Hash tables: maphash
lisp
;; Deep clone object
(defun deep-clone (obj)
  (cond
    ((null obj) nil)
    ((atom obj) obj)
    ((listp obj) (mapcar #'deep-clone obj))
    ((hash-table-p obj)
     (let ((new (make-hash-table :test (hash-table-test obj))))
       (maphash (lambda (key value)
                  (setf (gethash key new) (deep-clone value)))
                obj)
       new))
    (t obj)))

;; Usage
(defstruct user name address)
(defstruct address city zip)

(defparameter *original* 
  (make-user :name "Alice" 
             :address (make-address :city "NYC" :zip "10001")))
(defparameter *cloned* (deep-clone *original*))
Coding Round
71. Immutable update

Perform immutable updates on nested alists.

  • Method: acons for updates
  • Path: Dot notation for nested access
  • Use case: Functional programming
lisp
;; Immutable update
(defun update-immutable (obj path value)
  (let ((parts (split-string path ".")))
    (if (= (length parts) 1)
        (acons (car parts) value obj)
        (let* ((first (car parts))
               (rest (concatenate 'string (cdr parts) "."))
               (nested (cdr (assoc first obj))))
          (acons first 
                 (update-immutable nested rest value)
                 obj)))))

(defparameter *state* '((user (name "Alice") (age 25))))
(defparameter *new-state* (update-immutable *state* "user.age" 26))
Coding Round
72. Pipe function

Pipe composes functions from left to right.

  • Method: (pipe fns...)
  • Implementation: dolist with funcall
  • Direction: Left to right
lisp
;; Pipe function
(defun pipe (&rest fns)
  (lambda (value)
    (let ((result value))
      (dolist (fn fns)
        (setf result (funcall fn result)))
      result)))

(defun double (x) (* x 2))
(defun add-ten (x) (+ x 10))
(defun square (x) (* x x))

(defparameter *process* (pipe #'double #'add-ten #'square))
(format t "~a" (funcall *process* 5)) ; 400
Coding Round
73. Compose function

Compose functions from right to left.

  • Method: (compose fns...)
  • Implementation: dolist with funcall
  • Direction: Right to left
lisp
;; Compose function
(defun compose (&rest fns)
  (lambda (value)
    (let ((result value))
      (dolist (fn (reverse fns))
        (setf result (funcall fn result)))
      result)))

(defparameter *process2* (compose #'square #'add-ten #'double))
(format t "~a" (funcall *process2* 5)) ; 400
Coding Round
74. Memoization

Cache function results based on arguments.

  • Method: make-hash-table
  • Key: Arguments as key
  • Trade-off: Memory for speed
lisp
;; Memoization
(defun memoize (fn)
  (let ((cache (make-hash-table :test 'equal)))
    (lambda (arg)
      (multiple-value-bind (value found) (gethash arg cache)
        (if found
            value
            (let ((result (funcall fn arg)))
              (setf (gethash arg cache) result)
              result))))))

(defvar *fibonacci-memo* 
  (memoize (lambda (n)
             (if (<= n 1)
                 n
                 (+ (funcall *fibonacci-memo* (- n 1))
                    (funcall *fibonacci-memo* (- n 2)))))))

(format t "~a" (funcall *fibonacci-memo* 10))
Coding Round
75. Once function

Ensure a function is called only once.

  • Method: Use flag and closure
  • Implementation: Track if called
  • Use case: Initialization
lisp
;; Once function
(defun once (fn)
  (let ((called nil)
        (result nil))
    (lambda ()
      (unless called
        (setf called t)
        (setf result (funcall fn)))
      result)))

(defparameter *initialize* 
  (once (lambda ()
          (format t "Initialized")
          '(id 1 name "App"))))

(funcall *initialize*) ; Prints "Initialized"
(funcall *initialize*) ; Returns cached result
Coding Round
76. Debounce with leading edge

Debounce with leading edge executes immediately then waits.

  • Method: Track last call time
  • Implementation: last-call and timer
  • Use case: Save actions, API calls
lisp
;; Debounce with leading edge
(defun debounce-leading (delay-ms fn)
  (let ((last-call 0)
        (timer nil))
    (lambda ()
      (let ((now (/ (get-internal-real-time) 1000)))
        (if (< (- now last-call) (/ delay-ms 1000))
            (progn
              (when timer
                (sb-thread:terminate-thread timer))
              (setf timer 
                    (sb-thread:make-thread
                     (lambda ()
                       (sleep (/ delay-ms 1000))
                       (setf last-call (/ (get-internal-real-time) 1000))
                       (funcall fn)))))
            (progn
              (setf last-call now)
              (funcall fn)))))))
Coding Round
77. Throttle with leading edge

Throttle with leading edge executes at most once per time period.

  • Method: Track last call time
  • Implementation: Check time difference
  • Use case: Scroll events
lisp
;; Throttle with leading edge
(defun throttle-leading (delay-ms fn)
  (let ((last-call 0))
    (lambda ()
      (let ((now (/ (get-internal-real-time) 1000)))
        (when (>= (- now last-call) (/ delay-ms 1000))
          (setf last-call now)
          (funcall fn))))))
Coding Round
78. Deep equal

Deep equality comparison for nested structures.

  • Method: Recursive comparison
  • Lists: every
  • Hash tables: maphash
lisp
;; Deep equal
(defun deep-equal (obj1 obj2)
  (cond
    ((eq obj1 obj2) t)
    ((or (null obj1) (null obj2)) nil)
    ((and (listp obj1) (listp obj2))
     (and (= (length obj1) (length obj2))
          (every #'deep-equal obj1 obj2)))
    ((and (hash-table-p obj1) (hash-table-p obj2))
     (and (= (hash-table-count obj1) (hash-table-count obj2))
          (maphash (lambda (key value)
                     (and (deep-equal value (gethash key obj2))
                          t))
                   obj1)))
    (t (equal obj1 obj2))))
Coding Round
79. Observable pattern

Observable pattern for event notification.

  • Observable: Maintains subscribers
  • Subscribe: Add callback
  • Notify: Call all subscribers
lisp
;; Observable pattern
(defclass observable ()
  ((subscribers :initform '() :accessor subscribers)))

(defgeneric subscribe (observable callback))
(defgeneric notify (observable data))

(defmethod subscribe ((obs observable) callback)
  (push callback (subscribers obs))
  (lambda () (setf (subscribers obs) 
                   (remove callback (subscribers obs)))))

(defmethod notify ((obs observable) data)
  (dolist (callback (subscribers obs))
    (funcall callback data)))

;; Usage
(defparameter *obs* (make-instance 'observable))
(defparameter *unsubscribe* 
  (subscribe *obs* (lambda (data)
                     (format t "Received: ~a" data))))
(notify *obs* "Hello") ; Received: Hello
(funcall *unsubscribe*)
(notify *obs* "World") ; Nothing happens
Coding Round
80. Singleton pattern

Singleton pattern using closure.

  • Method: Closure with private state
  • Thread-safe: Single-threaded
  • Global access: Through variable
lisp
;; Singleton pattern
(defvar *singleton* 
  (let ((data (make-hash-table)))
    (lambda (command &rest args)
      (case command
        (:set (setf (gethash (car args) data) (cadr args)))
        (:get (gethash (car args) data))
        (t nil)))))

;; Usage
(funcall *singleton* :set "name" "Alice")
(funcall *singleton* :get "name") ; Alice
Coding Round
81. Factory pattern

Factory pattern using functions.

  • Method: create-user function
  • Benefits: Decouples creation
  • Classes: CLOS classes
lisp
;; Factory pattern
(defclass user () ())
(defclass admin (user) 
  ((name :initarg :name :accessor name)))
(defclass guest (user)
  ((name :initarg :name :accessor name)))
(defclass regular-user (user)
  ((name :initarg :name :accessor name)))

(defun create-user (type name)
  (case type
    (:admin (make-instance 'admin :name name))
    (:guest (make-instance 'guest :name name))
    (t (make-instance 'regular-user :name name))))

;; Usage
(create-user :admin "Alice")
Coding Round
82. Strategy pattern

Strategy pattern using generic functions.

  • Interface: defgeneric
  • Context: Uses strategy
  • Benefits: Runtime switching
lisp
;; Strategy pattern
(defgeneric pay (strategy amount))

(defclass credit-card-strategy () ())
(defclass paypal-strategy () ())
(defclass crypto-strategy () ())

(defmethod pay ((strategy credit-card-strategy) amount)
  (format t "Paid $~a with Credit Card" amount))

(defmethod pay ((strategy paypal-strategy) amount)
  (format t "Paid $~a with PayPal" amount))

(defmethod pay ((strategy crypto-strategy) amount)
  (format t "Paid $~a with Crypto" amount))

(defclass payment-context ()
  ((strategy :initarg :strategy :accessor strategy)))

(defgeneric execute-payment (context amount))

(defmethod execute-payment ((context payment-context) amount)
  (pay (strategy context) amount))

;; Usage
(defparameter *context* 
  (make-instance 'payment-context :strategy (make-instance 'credit-card-strategy)))
(execute-payment *context* 100)
(setf (strategy *context*) (make-instance 'paypal-strategy))
(execute-payment *context* 50)
Coding Round
83. Observer pattern

Observer pattern using CLOS.

  • Subject: Maintains observers
  • Observer: Receives updates
  • Benefits: Loose coupling
lisp
;; Observer pattern
(defclass observer ()
  ())

(defgeneric update (observer data))

(defclass subject ()
  ((observers :initform '() :accessor observers)
   (state :initform "" :accessor state)))

(defmethod set-state ((subj subject) new-state)
  (setf (state subj) new-state)
  (notify-observers subj))

(defmethod attach ((subj subject) (obs observer))
  (push obs (observers subj)))

(defmethod detach ((subj subject) (obs observer))
  (setf (observers subj) (remove obs (observers subj))))

(defmethod notify-observers ((subj subject))
  (dolist (obs (observers subj))
    (update obs (state subj))))

(defclass concrete-observer ()
  ((name :initarg :name :accessor name)))

(defmethod update ((obs concrete-observer) data)
  (format t "~a received: ~a" (name obs) data))

;; Usage
(defparameter *subject* (make-instance 'subject))
(defparameter *observer1* (make-instance 'concrete-observer :name "Observer1"))
(defparameter *observer2* (make-instance 'concrete-observer :name "Observer2"))
(attach *subject* *observer1*)
(attach *subject* *observer2*)
(set-state *subject* "Hello World")
Coding Round
84. Decorator pattern

Decorator pattern using wrapper functions.

  • Component: Base class
  • Decorator: Wraps component
  • Benefits: Flexible extension
lisp
;; Decorator pattern
(defclass coffee ()
  ((cost :initarg :cost :accessor cost)
   (description :initarg :description :accessor description)))

(defun milk-decorator (coffee)
  (make-instance 'coffee
                 :cost (+ (cost coffee) 2.0)
                 :description (concatenate 'string (description coffee) ", Milk")))

(defun sugar-decorator (coffee)
  (make-instance 'coffee
                 :cost (+ (cost coffee) 1.0)
                 :description (concatenate 'string (description coffee) ", Sugar")))

;; Usage
(defparameter *coffee* (make-instance 'coffee :cost 5.0 :description "Coffee"))
(setf *coffee* (milk-decorator *coffee*))
(setf *coffee* (sugar-decorator *coffee*))
(format t "~a" (description *coffee*)) ; Coffee, Milk, Sugar
(format t "~a" (cost *coffee*)) ; 8.0
Coding Round
85. Command pattern

Command pattern using classes.

  • Command: Encapsulates request
  • Invoker: Executes commands
  • Benefits: Undo/redo
lisp
;; Command pattern
(defgeneric execute (command))
(defgeneric undo (command))

(defclass add-command ()
  ((receiver :initarg :receiver :accessor receiver)
   (value :initarg :value :accessor value)))

(defmethod execute ((cmd add-command))
  (push (value cmd) (receiver cmd)))

(defmethod undo ((cmd add-command))
  (setf (receiver cmd) 
        (remove (value cmd) (receiver cmd))))

;; Usage
(defparameter *receiver* '(1 2 3))
(defparameter *cmd* (make-instance 'add-command :receiver *receiver* :value 4))
(execute *cmd*)
(format t "~a" *receiver*) ; (4 1 2 3)
(undo *cmd*)
(format t "~a" *receiver*) ; (1 2 3)
Coding Round
86. Memento pattern

Memento pattern for state restoration.

  • Originator: Creates/restores mementos
  • Memento: Stores state
  • Caretaker: Manages mementos
lisp
;; Memento pattern
(defclass memento ()
  ((state :initarg :state :accessor state)))

(defclass originator ()
  ((state :initform "" :accessor state)))

(defmethod save-state ((obj originator))
  (make-instance 'memento :state (state obj)))

(defmethod restore-state ((obj originator) (memento memento))
  (setf (state obj) (state memento)))

(defclass caretaker ()
  ((mementos :initform '() :accessor mementos)))

(defmethod add-memento ((obj caretaker) memento)
  (push memento (mementos obj)))

(defmethod get-memento ((obj caretaker) index)
  (nth index (mementos obj)))

;; Usage
(defparameter *originator* (make-instance 'originator))
(defparameter *caretaker* (make-instance 'caretaker))

(setf (state *originator*) "State 1")
(add-memento *caretaker* (save-state *originator*))
(setf (state *originator*) "State 2")
(add-memento *caretaker* (save-state *originator*))
(setf (state *originator*) "State 3")

(restore-state *originator* (get-memento *caretaker* 0))
(format t "~a" (state *originator*)) ; State 1
Coding Round
87. Mediator pattern

Mediator pattern for centralized communication.

  • Mediator: Encapsulates communication
  • Colleague: Communicates through mediator
  • Benefits: Loose coupling
lisp
;; Mediator pattern
(defclass mediator ()
  ((colleagues :initform '() :accessor colleagues)))

(defmethod register ((med mediator) colleague)
  (push colleague (colleagues med)))

(defmethod send-message ((med mediator) message sender)
  (dolist (col (colleagues med))
    (unless (eq col sender)
      (receive-message col message))))

(defclass colleague ()
  ((name :initarg :name :accessor name)
   (mediator :initarg :mediator :accessor mediator)))

(defmethod initialize-instance :after ((col colleague) &key)
  (register (mediator col) col))

(defmethod send-message ((col colleague) message)
  (send-message (mediator col) message col))

(defmethod receive-message ((col colleague) message)
  (format t "~a received: ~a" (name col) message))

;; Usage
(defparameter *mediator* (make-instance 'mediator))
(defparameter *alice* (make-instance 'colleague :name "Alice" :mediator *mediator*))
(defparameter *bob* (make-instance 'colleague :name "Bob" :mediator *mediator*))
(send-message *alice* "Hello Bob!")
Coding Round
88. Chain of Responsibility

Chain of Responsibility using classes.

  • Handler: Processes or forwards
  • Chain: Linked list of handlers
  • Benefits: Decoupling
lisp
;; Chain of Responsibility
(defclass handler ()
  ((next-handler :initform nil :accessor next-handler)))

(defgeneric set-next (handler next))
(defgeneric handle (handler request))

(defmethod set-next ((handler handler) next)
  (setf (next-handler handler) next)
  next)

(defclass auth-handler (handler)
  ())

(defmethod handle ((handler auth-handler) request)
  (if (getf request :token)
      (progn
        (format t "Authentication passed")
        (let ((next (next-handler handler)))
          (when next (handle next request))))
      (format t "Authentication failed")))

(defclass logger-handler (handler)
  ())

(defmethod handle ((handler logger-handler) request)
  (format t "Logging request: ~a" (getf request :url))
  (let ((next (next-handler handler)))
    (when next (handle next request))))

;; Usage
(defparameter *auth* (make-instance 'auth-handler))
(defparameter *logger* (make-instance 'logger-handler))
(set-next *auth* *logger*)
(handle *auth* '(:token "valid" :url "/api"))
Coding Round
89. State pattern

State pattern using classes.

  • Context: Maintains state
  • State: Defines behavior
  • Benefits: Clean state management
lisp
;; State pattern
(defgeneric handle-state (state))

(defclass ready-state ()
  ())

(defclass processing-state ()
  ())

(defclass completed-state ()
  ())

(defmethod handle-state ((state ready-state))
  (format t "Ready: Waiting for input"))

(defmethod handle-state ((state processing-state))
  (format t "Processing: Working on task"))

(defmethod handle-state ((state completed-state))
  (format t "Completed: Task finished"))

(defclass context ()
  ((state :initform (make-instance 'ready-state)
          :accessor state)))

(defmethod request ((ctx context))
  (handle-state (state ctx)))

;; Usage
(defparameter *context* (make-instance 'context))
(request *context*) ; Ready: Waiting for input
(setf (state *context*) (make-instance 'processing-state))
(request *context*) ; Processing: Working on task
(setf (state *context*) (make-instance 'completed-state))
(request *context*) ; Completed: Task finished
Coding Round
90. Proxy pattern

Proxy pattern using classes.

  • Subject: Real object
  • Proxy: Controls access
  • Benefits: Access control
lisp
;; Proxy pattern
(defclass real-subject ()
  ())

(defmethod request ((obj real-subject))
  (format t "RealSubject: Handling request"))

(defclass proxy ()
  ((real-subject :initform nil :accessor real-subject)))

(defmethod request ((obj proxy))
  (when (check-access obj)
    (unless (real-subject obj)
      (setf (real-subject obj) (make-instance 'real-subject)))
    (request (real-subject obj))
    (log-access obj)))

(defmethod check-access ((obj proxy))
  (format t "Proxy: Checking access")
  t)

(defmethod log-access ((obj proxy))
  (format t "Proxy: Logging access"))

;; Usage
(defparameter *proxy* (make-instance 'proxy))
(request *proxy*)
Coding Round
91. Flyweight pattern

Flyweight pattern for sharing objects.

  • Flyweight: Shared object
  • Factory: Manages flyweights
  • Benefits: Memory optimization
lisp
;; Flyweight pattern
(defclass flyweight ()
  ((shared-state :initarg :shared-state :accessor shared-state)))

(defmethod operation ((obj flyweight) unique-state)
  (format t "Shared: ~a, Unique: ~a" 
          (shared-state obj) unique-state))

(defclass flyweight-factory ()
  ((flyweights :initform (make-hash-table :test 'equal)
               :accessor flyweights)))

(defmethod get-flyweight ((factory flyweight-factory) shared-state)
  (or (gethash shared-state (flyweights factory))
      (setf (gethash shared-state (flyweights factory))
            (make-instance 'flyweight :shared-state shared-state))))

;; Usage
(defparameter *factory* (make-instance 'flyweight-factory))
(defparameter *fw1* (get-flyweight *factory* "state1"))
(defparameter *fw2* (get-flyweight *factory* "state1"))
(defparameter *fw3* (get-flyweight *factory* "state2"))
(operation *fw1* "unique1")
(operation *fw2* "unique2")
(operation *fw3* "unique3")
Coding Round
92. Bridge pattern

Bridge pattern using CLOS.

  • Abstraction: High-level interface
  • Implementation: Low-level operations
  • Benefits: Separation of concerns
lisp
;; Bridge pattern
(defgeneric operation-impl (impl))

(defclass concrete-implementation-a ()
  ())

(defmethod operation-impl ((impl concrete-implementation-a))
  (format t "ConcreteImplementationA: Operation"))

(defclass concrete-implementation-b ()
  ())

(defmethod operation-impl ((impl concrete-implementation-b))
  (format t "ConcreteImplementationB: Operation"))

(defclass abstraction ()
  ((impl :initarg :impl :accessor impl)))

(defmethod operation ((abst abstraction))
  (format t "Abstraction: Additional logic")
  (operation-impl (impl abst)))

;; Usage
(defparameter *impl-a* (make-instance 'concrete-implementation-a))
(defparameter *impl-b* (make-instance 'concrete-implementation-b))
(defparameter *abstraction1* (make-instance 'abstraction :impl *impl-a*))
(defparameter *abstraction2* (make-instance 'abstraction :impl *impl-b*))
(operation *abstraction1*)
(operation *abstraction2*)
Coding Round
93. Adapter pattern

Adapter pattern using wrapper classes.

  • Target: Expected interface
  • Adaptee: Existing interface
  • Adapter: Bridges interfaces
lisp
;; Adapter pattern
(defclass target ()
  ())

(defmethod request ((obj target))
  (format t "Target: Request"))

(defclass adaptee ()
  ())

(defmethod specific-request ((obj adaptee))
  (format t "Adaptee: Specific Request"))

(defclass adapter ()
  ((adaptee :initarg :adaptee :accessor adaptee)))

(defmethod request ((obj adapter))
  (specific-request (adaptee obj)))

;; Usage
(defparameter *adaptee* (make-instance 'adaptee))
(defparameter *adapter* (make-instance 'adapter :adaptee *adaptee*))
(request *adapter*)
Coding Round
94. Facade pattern

Facade pattern using composition.

  • Facade: Simplified interface
  • Subsystem: Complex components
  • Benefits: Simplified interface
lisp
;; Facade pattern
(defclass subsystem-a ()
  ())

(defmethod operation-a ((obj subsystem-a))
  (format t "SubsystemA: Operation"))

(defclass subsystem-b ()
  ())

(defmethod operation-b ((obj subsystem-b))
  (format t "SubsystemB: Operation"))

(defclass facade ()
  ((subsystem-a :initform (make-instance 'subsystem-a) :accessor subsystem-a)
   (subsystem-b :initform (make-instance 'subsystem-b) :accessor subsystem-b)))

(defmethod operation ((obj facade))
  (operation-a (subsystem-a obj))
  (operation-b (subsystem-b obj))
  (format t "Facade: Complex operation"))

;; Usage
(defparameter *facade* (make-instance 'facade))
(operation *facade*)
Coding Round
95. Composite pattern

Composite pattern using classes.

  • Component: Interface for all
  • Leaf: Individual object
  • Composite: Container
lisp
;; Composite pattern
(defgeneric operation (component))

(defclass leaf ()
  ((name :initarg :name :accessor name)))

(defmethod operation ((obj leaf))
  (format t "Leaf ~a: Operation" (name obj)))

(defclass composite ()
  ((name :initarg :name :accessor name)
   (children :initform '() :accessor children)))

(defmethod add ((obj composite) component)
  (push component (children obj)))

(defmethod remove ((obj composite) component)
  (setf (children obj) (remove component (children obj))))

(defmethod operation ((obj composite))
  (format t "Composite ~a: Operation" (name obj))
  (dolist (child (children obj))
    (operation child)))

;; Usage
(defparameter *leaf1* (make-instance 'leaf :name "A"))
(defparameter *leaf2* (make-instance 'leaf :name "B"))
(defparameter *composite* (make-instance 'composite :name "Root"))
(add *composite* *leaf1*)
(add *composite* *leaf2*)
(operation *composite*)
Coding Round
96. Visitor pattern

Visitor pattern using generic functions.

  • Visitor: Defines operations
  • Element: Accepts visitors
  • Benefits: Adding operations without modifying
lisp
;; Visitor pattern
(defgeneric accept (element visitor))
(defgeneric visit (visitor element))

(defclass element-a ()
  ())

(defmethod accept ((obj element-a) visitor)
  (visit visitor obj))

(defclass element-b ()
  ())

(defmethod accept ((obj element-b) visitor)
  (visit visitor obj))

(defclass visitor ()
  ())

(defmethod visit ((visitor visitor) (element element-a))
  (format t "Visiting ElementA"))

(defmethod visit ((visitor visitor) (element element-b))
  (format t "Visiting ElementB"))

;; Usage
(defparameter *visitor* (make-instance 'visitor))
(defparameter *element-a* (make-instance 'element-a))
(defparameter *element-b* (make-instance 'element-b))
(accept *element-a* *visitor*)
(accept *element-b* *visitor*)
Coding Round
97. Iterator pattern

Iterator pattern using classes.

  • Iterator: Traverses collection
  • Aggregate: Creates iterator
  • Benefits: Uniform traversal
lisp
;; Iterator pattern
(defclass iterator ()
  ((collection :initarg :collection :accessor collection)
   (index :initform 0 :accessor index)))

(defgeneric next (iterator))
(defgeneric has-next (iterator))

(defmethod next ((it iterator))
  (if (has-next it)
      (let ((result (nth (index it) (collection it))))
        (incf (index it))
        result)
      nil))

(defmethod has-next ((it iterator))
  (< (index it) (length (collection it))))

(defclass custom-collection ()
  ((items :initform '() :accessor items)))

(defmethod add ((col custom-collection) item)
  (push item (items col)))

(defmethod get-iterator ((col custom-collection))
  (make-instance 'iterator :collection (items col)))

;; Usage
(defparameter *collection* (make-instance 'custom-collection))
(add *collection* "A")
(add *collection* "B")
(add *collection* "C")
(defparameter *iterator* (get-iterator *collection*))
(loop while (has-next *iterator*)
      do (format t "~a" (next *iterator*)))
Coding Round
98. Template Method pattern

Template Method using generic functions.

  • AbstractClass: Defines template
  • ConcreteClass: Implements steps
  • Benefits: Code reuse
lisp
;; Template Method pattern
(defclass abstract-class ()
  ())

(defgeneric template-method (obj))
(defgeneric step1 (obj))
(defgeneric step2 (obj))
(defgeneric step3 (obj))

(defmethod template-method ((obj abstract-class))
  (step1 obj)
  (step2 obj)
  (step3 obj))

(defmethod step1 ((obj abstract-class))
  (format t "Step 1"))

(defmethod step3 ((obj abstract-class))
  (format t "Step 3"))

(defclass concrete-class (abstract-class)
  ())

(defmethod step2 ((obj concrete-class))
  (format t "Concrete Step 2"))

;; Usage
(defparameter *concrete* (make-instance 'concrete-class))
(template-method *concrete*)
Coding Round
99. Builder pattern

Builder pattern using classes.

  • Builder: Constructs parts
  • Director: Orchestrates construction
  • Product: Constructed object
lisp
;; Builder pattern
(defclass product ()
  ((parts :initform '() :accessor parts)))

(defmethod add-part ((obj product) part)
  (push part (parts obj)))

(defmethod list-parts ((obj product))
  (format t "~a" (parts obj)))

(defclass builder ()
  ((product :initform (make-instance 'product) :accessor product)))

(defmethod reset ((obj builder))
  (setf (parts (product obj)) '()))

(defmethod build-step-a ((obj builder))
  (add-part (product obj) "Part A"))

(defmethod build-step-b ((obj builder))
  (add-part (product obj) "Part B"))

(defmethod get-result ((obj builder))
  (product obj))

(defclass director ()
  ((builder :initarg :builder :accessor builder)))

(defmethod build-minimal ((obj director))
  (build-step-a (builder obj)))

(defmethod build-full ((obj director))
  (build-step-a (builder obj))
  (build-step-b (builder obj)))

;; Usage
(defparameter *builder* (make-instance 'builder))
(defparameter *director* (make-instance 'director :builder *builder*))
(build-minimal *director*)
(defparameter *product* (get-result *builder*))
(list-parts *product*)
Coding Round
100. Prototype pattern

Prototype pattern for cloning objects.

  • Prototype: Cloneable object
  • Clone: Creates a copy
  • Benefits: Performance
lisp
;; Prototype pattern
(defclass prototype ()
  ((name :initarg :name :accessor name)
   (nested :initarg :nested :accessor nested)))

(defmethod clone ((obj prototype))
  (make-instance 'prototype
                 :name (name obj)
                 :nested (copy-list (nested obj))))

(defmethod deep-clone ((obj prototype))
  (make-instance 'prototype
                 :name (name obj)
                 :nested (deep-copy (nested obj))))

(defun deep-copy (obj)
  (cond
    ((null obj) nil)
    ((atom obj) obj)
    ((listp obj) (mapcar #'deep-copy obj))
    ((hash-table-p obj)
     (let ((new (make-hash-table :test (hash-table-test obj))))
       (maphash (lambda (key value)
                  (setf (gethash key new) (deep-copy value)))
                obj)
       new))
    (t obj)))

;; Usage
(defparameter *original* 
  (make-instance 'prototype :name "Original" :nested '((value . 42))))
(defparameter *copy* (clone *original*))
(setf (name *copy*) "Copy")
(setf (cdr (assoc 'value (nested *copy*))) 99)
(format t "~a" (name *original*)) ; Original
(format t "~a" (cdr (assoc 'value (nested *original*)))) ; 42 (shallow copy)

(defparameter *deep-copy* (deep-clone *original*))
(setf (cdr (assoc 'value (nested *deep-copy*))) 100)
(format t "~a" (cdr (assoc 'value (nested *original*)))) ; 42 (deep copy)