#!/usr/local/bin/sbcl --script (defun foo (&key a b c) (list a b c)) (format t "~a~%" (foo :a 1 :b 2 :c 3)) (format t "~a~%" (foo :c 3 :b 2 :a 1)) (format t "~a~%" (foo :a 1 :c 3) ) (format t "~a~%" (foo)) (defun foo (&key a (b 20) (c 30 c-p)) (list a b c c-p)) (format t "~a~%" (foo :a 1 :b 2 :c 3)) (format t "~a~%" (foo :c 3 :b 2 :a 1)) (format t "~a~%" (foo :a 1 :c 3) ) (format t "~a~%" (foo)) (defun make-cd (title artist rating ripped) (list :title title :artist artist :rating rating :ripped ripped)) (defvar *db* nil) (defun add-record (cd) (push cd *db*)) (add-record (make-cd "Roses" "Kathy Mattea" 7 t)) (add-record (make-cd "Fly" "Dixie Chicks" 8 t)) (add-record (make-cd "Home" "Dixie Chicks" 9 t)) (defun dump-db () (dolist (cd *db*) (format t "~{~a:~10t~a~%~}~%" cd))) ;(dump-db) ;select (format t "~a~%" "select") (defun select-by-artist (artist) (remove-if-not #'(lambda (cd) (equal (getf cd :artist) artist)) *db*)) (defun select (selector-fn) (remove-if-not selector-fn *db*)) (defun artist-selector (artist) #'(lambda (cd) (equal (getf cd :artist) artist))) (format t "~a~%" (select (artist-selector "Dixie Chicks"))) ;where (format t "~a~%" "where") (defun where (&key title artist rating (ripped nil ripped-p)) #'(lambda (cd) (and (if title (equal (getf cd :title) title) t) (if artist (equal (getf cd :artist) artist) t) (if rating (equal (getf cd :rating) rating) t) (if ripped-p (equal (getf cd :ripped) ripped) t)))) (format t "~a~%" (select (where :artist "Dixie Chicks"))) (format t "~a~%" (select (where :rating 10 :ripped nil))) ;update (format t "~a~%" "update") (defun update (selector-fn &key title artist rating (ripped nil ripped-p)) (setf *db* (mapcar #'(lambda (row) (when (funcall selector-fn row) (if title (setf (getf row :title) title)) (if artist (setf (getf row :artist) artist)) (if rating (setf (getf row :rating) rating)) (if ripped-p (setf (getf row :ripped) ripped))) row) *db*))) (format t "~a~%" (select (where :artist "Dixie Chicks"))) (update (where :artist "Dixie Chicks") :rating 11) (format t "~a~%" (select (where :artist "Dixie Chicks"))) ;delete (format t "~a~%" "delete") (dump-db) (defun delete-rows (selector-fn) (setf *db* (remove-if selector-fn *db*))) ;(delete-rows (where :artist "Dixie Chicks")) ;(format t "~a~%" "deleted Dixie Chicks") (delete-rows (where :rating 7 :ripped T)) (format t "~a~%" "deleted rating 7 ripped T") (dump-db) ;defmacro (format t "~a~%" '(1 2 3)) (format t "~a~%" (reverse '(1 2 3))) (format t "~a~%" "hello, world") (defmacro backwards (expr) (reverse expr)) (backwards ("hello, world" "~a~%" t format)) (defun make-comparison-expr (field value) (list 'equal (list 'getf 'cd field) value)) (make-comparison-expr :rating 10) (make-comparison-expr :title "Give Us a Break") (format t "~a~%" `(1 2 3)) (format t "~a~%" '(1 2 3)) (format t "~a~%" `(1 2 (+ 1 2))) (format t "~a~%" `(1 2 ,(+ 1 2))) (defun make-comparison-expr (field value) `(equal (getf cd ,field) ,value)) (defun make-comparisons-list (fields) (loop while fields collecting (make-comparison-expr (pop fields) (pop fields)))) (defmacro where (&rest clauses) `#'(lambda (cd) (and ,@(make-comparisons-list clauses)))) `(and ,(list 1 2 3)) `(and ,@(list 1 2 3)) `(and ,@(list 1 2 3) 4) (format t "~a~%" (macroexpand-1 '(where :title "Give Us a Break" :ripped t))) ;(format t "~a~%" (select (where :title "Give Us a Break" :ripped t))) (format t "~a~%" (select (where :title "Give Us a Break" :ripped t)))