#!/usr/local/bin/sbcl --script (in-package #:cl-user) (defpackage #:beer (:use #:common-lisp) (:export #:verse #:sing)) (in-package #:beer) ;; [*endpoint-min*, *endpoint-max*] in notations for intervals. (defparameter *endpoint-max* 99) (defparameter *endpoint-min* 0) (defun generate-1st-line (n) (format nil "~a bottle~p of beer on the wall, ~a bottle~p of beer." (if (= 0 n) "No more" n) n (if (= 0 n) "no more" n) n)) (defun generate-2nd-line (n) (if (= *endpoint-min* n) (format nil "Go to the store and buy some more, ~a bottle~p of beer on the wall." *endpoint-max* *endpoint-max*) (let ((n-1 (1- n))) (format nil "Take ~a down and pass it around, ~a bottle~p of beer on the wall." (if (= *endpoint-min* n-1) "it" "one") (if (= *endpoint-min* n-1) "no more" n-1) n-1)))) (defun verse (n) (format nil "~a~&~a~&" (generate-1st-line n) (generate-2nd-line n))) (defun sing (&optional (start *endpoint-max*) (end *endpoint-min*)) (format nil "~{~a~%~}" (loop for i from start downto end collect (verse i)))) (format t (sing))