Last active
October 2, 2020 16:33
-
-
Save catsocks/66aa0f7edb55b121179273226ed256ac to your computer and use it in GitHub Desktop.
inzanozulu's Common Lisp tutorial
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;;;; 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