Skip to content

Instantly share code, notes, and snippets.

@catsocks
Last active October 2, 2020 16:33
Show Gist options
  • Save catsocks/66aa0f7edb55b121179273226ed256ac to your computer and use it in GitHub Desktop.
Save catsocks/66aa0f7edb55b121179273226ed256ac to your computer and use it in GitHub Desktop.
inzanozulu's Common Lisp tutorial
;;;; Code that I wrote following the Common Lisp tutorial by inzanozulu on
;;;; Youtube.
;;;;
;;;; Use the SBCL Common Lisp compiler and Emacs with the SLIME third-party
;;;; package to interactively evaluate this code.
;;;;
;;;; Most of this code is also valid Emacs Lisp code which the built-in Lisp
;;;; Interaction mode in Emacs can interactively evaluate.
;;; Lisp stands for list processing and a Lisp program is made up of forms
;;; which can either be an atom (number, string, symbol, ...) or a list of
;;; forms.
#\A ; A character
#\space ; space character
#\newline ; newline character
() ; empty list which is equal to nil
(if t ; t denotes true value
(princ "True")
(princ "False"))
(if nil
(princ "False")
(princ "True"))
(let (var) ; nil variable var
(princ var)) ; print var and return nil
(let ((x 5) (y 3)) ; declaration of two variables
(princ x)
(terpri) ; equivalent to printing #\newline or \n in e.g. C
(princ y)
(terpri)
(+ x y)) ; return the sum of x and y
(let (var (x 5) (y 7)) ; var is nil
(princ (* x y))
var) ; return nil
(let ; symbols are bound in parallel
((x 5) (y x)) ; ilegal
y)
(let* ; symbols are bound sequentially
((x 5) (y x)) ; legal
y)
(let (x)
(princ x) ; prints nil
(terpri)
(setq x 5) ; setq (set quoted) lets you change the value of an existing var.
(princ x) ; prints 5
(terpri)
(+ 1332 x))
;;; Rule of thumb for comments:
;;;; Comment at the beginning of the file
;;; Comment outside a function
;; Comment inside a (or a) function
; Comment at the end of a line of code
#|
Multi
-line
Comment
|#
(defun square (x) ; define function (or define fun!)
(princ x)
(* x x))
(square 2) ; 4
(defun mult (x y)
(* x y))
(mult 2 4)
;;; The quote function will return the expression given to it as argument
;;; without evaluating it.
(quote x) ; return the symbol x and not the value which it may represent
(quote (0 1 2 3 4 5)) ; a regular list with unevaluated contents
;;; ' is a macro that quotes the expression following it
'x
'(0 1 2 3 4 5)
(quote 5)
(quote #\a)
(quote #(5 0 6)) ; a vector which is a fixed-width list
;;; Comparison of a C enumeration to symbols in Lisp.
;;; enum lang {
;;; PORTUGUESE,
;;; ENGLISH,
;;; };
;;;
;;; void do_greeting(enum lang l) {
;;; if (l == PORTUGUESE) {
;;; printf("Oi!");
;;; } else if (l == ENGLISH) {
;;; printf("Hi!");
;;; }
;;; }
(defun do-greeting (lang)
(if (eq lang 'pt) ; could also use cond here
(princ "Oi!")
(if (eq lang 'en)
(princ "Hi!"))))
(do-greeting 'pt)
(do-greeting 'en)
;; Lists in Lisp are linked-lists i.e. a list of pairs.
(car ; car returns the first element of a list (or pair)
'(a b c)) ; 'a
(cdr ; cdr returns the second element of a list (or pair)
'(a b c)) ; '(b c)
(car (cdr ())) ; ()
(defun sum (nums) ; return 0 if nums equals nil or the sum
(if (null nums) 0
(+ (car nums)
(sum (cdr nums)))))
(sum ()) ; 0
(sum '(0 1 2 3)) ; 6
(defun my-length (list) ; my implementation of the existing length func.
(if (null list) 0
(+ 1 (my-length (cdr list))))) ; we can count 1 but dunno about rest
(defun print-list (list)
(if (not (null list)) ; same thing as (if list but more synctatically correct
(progn ; same as (let () or curly braces in C
(princ (car list))
(print-list (cdr list)))))
(print-list '("A" "B")) ; prints AB and returns nil
(defun sum-numbers (list) ; sum all numbers in a list ignoring other values
(cond ((null list) 0)
((numberp (car list)) ; p in numberp stands for predicate
(+ (car list) (sum-numbers (cdr list))))
((symbolp (car list))
(sum-numbers (cdr list)))
(t ; practically the same as (listp (car list)) or an else statement
(+ (sum-numbers (car list)) (sum-numbers (cdr list))))))
(sum-numbers '(((1 5) 'a 1) ()))
;;; Recursive implementation of some common and existing functions below.
;;; Implementation of the subsetp function which returns true if every element
;;; in l1 is also in l2 and nil otherwise.
(defun my-subsetp (l1 l2)
(if (null l1) t
(and (member (car l1) l2)
(my-subsetp (cdr l1) l2))))
(my-subsetp '(c) '(c a t)) ; T
(my-subsetp '(a t) '(c a t)) ; T
(my-subsetp '(c) '(d o g)) ; NIL
;;; Implementation of the existing delete function, returning a new list
;;; without all occurrances of the item obj.
(defun my-delete (obj list)
(cond ((null list) nil)
((listp (car list))
(cons (my-delete obj (car list))
(my-delete obj (cdr list))))
((eq obj (car list)) ; if the obj equals the first element of the list
(my-delete obj (cdr list))) ; cont. contructing a new list without it
(t
;; Construct a new pair with the first element of the list as the first
;; value and the result of subsequent my-delete calls as the second
;; value. Remember that lists are made up of pairs in Lisp.
(cons (car list)
(my-delete obj (cdr list))))))
(my-delete 'e '(a b e c)) ; (a b c)
(my-delete 'e '((e a) b e c)) ; ((a) b c)
(my-delete 'e '(a b)) ; (a b)
;;; My implementation of a function which inserts item A before all
;;; occurances of item B in a list.
(defun insert-before (a b list)
(cond ((null list) nil)
((listp (car list))
(cons (insert-before a b (car list))
(insert-before a b (cdr list))))
((eq b (car list))
(append (list a b)
(insert-before a b (cdr list))))
(t
(cons (car list)
(insert-before a b (cdr list))))))
(insert-before 'a 'b '(b c)) ; (a b c)
(insert-before 'a 'b '(b c (b (b)))) ; (a b c (a b (a b)))
(insert-before 'a 'b '(b (b b) b)) ; (a b (a b a b) a b)
(insert-before 'a 'b '(c (d e) ((f)))) ; (c (d e) ((f)))
;;; My implementation of a function that counts the number of atoms inside
;;; sublists in a list.
(defun atom-count (list)
(cond ((null list) 0)
((atom (car list))
(+ 1 (atom-count (cdr list))))
(t
(+ (atom-count (car list))
(atom-count (cdr list))))))
(defun sublist-count (list)
(cond ((null list) nil)
(t
(cons (atom-count (car list)) ; can the length func. be used instead?
(sublist-count (cdr list))))))
(sublist-count '(((a) b) (c d) (e))) ; (2 2 1)
(sublist-count '((((a))) (b c (d)))) ; (1 3)
(sublist-count '((a) (b))) ; (1 1)
;;; My implementation of the existing max function which returns the greatest
;;; number in a list of numbers.
;;; TODO: Accept numbers as arguments.
(defun my-max (list)
(cond ((null list) 0)
((> (car list) (my-max (cdr list)))
(car list))
(t
(my-max (cdr list)))))
(my-max '(3 2 1)) ; 3
(my-max '(8 7 9 6)) ; 9
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment