# Exception handling in Lisp, as seen from C++, Part 2

We’ve talked a bit about conditions in Lisp, and how they differ from those in C++.  It’s helpful, though, to provide an example or two.

So, to demonstrate conditions, we’ll start with a simple program.  It opens a file on disc and reads pairs of numbers from it.  For each pair it displays the ratio of the first number to the second number.  Let’s call this the “My First Lisp Homework Problem” version of the code, because, while it does kind of work, it needs some improvements for real applications.

```;; Some examples of using conditions in Lisp code.
;;
(declaim (optimize (debug 3) (safety 3)))

(defun condition-demo (pathname)
(format t "Starting to analyse file ~A~%" pathname)
(with-open-file (s pathname :direction :input)
(analyse-stream s)))

;; Goes through the stream, dividing entries one by the next
(defun analyse-stream (stream)
(do ()
(nil)
(let ((num1 (get-next-number stream))
(num2 (get-next-number stream)))
(format t "The ratio of ~A to ~A is ~A~%" num1 num2 (/ num1 num2)))))

;; Returns the next object in the stream
(defun get-next-number (stream)

If you run condition-demo on a disc file that contains numbers, it will produce ratios and display them on the screen.  However, this code can’t handle anything unexpected.  If the pathname doesn’t exist, or if it doesn’t contain only numbers, or if the file isn’t infinitely long, it will, sooner or later, generate an unhandled error.

So, let’s start with the most obvious case.  The pathname is unreadable.  Either it doesn’t exist, or the process doesn’t have permission to open the file for reading.  In that case, a condition of the type ‘file-error is signaled.  Condition objects typically have a printable form, so we can print them in a format statement to help the user understand the problem.

```;; Some examples of using conditions in Lisp code.
;;
(declaim (optimize (debug 3) (safety 3)))

(defun condition-demo (pathname)
(format t "Starting to analyse file ~A~%" pathname)
(handler-case
(with-open-file (s pathname :direction :input)
(analyse-stream s))
(file-error (c)
(format t "A file error was encountered while trying to analyse ~A.~%The error returned was:~%~A~%" pathname c))))

;; Goes through the stream, dividing entries one by the next
(defun analyse-stream (stream)
(do ()
(nil)
(let ((num1 (get-next-number stream))
(num2 (get-next-number stream)))
(format t "The ratio of ~A to ~A is ~A~%" num1 num2 (/ num1 num2)))))

;; Returns the next object in the stream
(defun get-next-number (stream)
{"ft_lang_label":"__label__en","ft_lang_prob":0.87265694,"math_prob":0.77204937,"size":2894,"snap":"2020-24-2020-29","text_gpt3_token_len":707,"char_repetition_ratio":0.12595156,"word_repetition_ratio":0.31465518,"special_character_ratio":0.25812024,"punctuation_ratio":0.12345679,"nsfw_num_words":0,"has_unicode_error":false,"math_prob_llama3":0.96979845,"pos_list":[0],"im_url_duplicate_count":[null],"WARC_HEADER":"{\"WARC-Type\":\"response\",\"WARC-Date\":\"2020-05-26T08:20:37Z\",\"WARC-Record-ID\":\"<urn:uuid:05f6abf5-96d2-4636-8419-091b75593de5>\",\"Content-Length\":\"31941\",\"Content-Type\":\"application/http; msgtype=response\",\"WARC-Warcinfo-ID\":\"<urn:uuid:d233414f-b7cc-453e-8a29-548cd3093c65>\",\"WARC-Concurrent-To\":\"<urn:uuid:234e575e-e171-4551-9983-5c1031f6b73e>\",\"WARC-IP-Address\":\"69.165.173.139\",\"WARC-Target-URI\":\"https://blog.cneufeld.ca/2013/10/exception-handling-in-lisp-as-seen-from-c-part-2/\",\"WARC-Payload-Digest\":\"sha1:NLAC5RK2KZPYDZGI5IQDZ6YHTM4ZZSJE\",\"WARC-Block-Digest\":\"sha1:3FQDEKJDIGBM3EMGIU7H4Q63SIHAZJAC\",\"WARC-Identified-Payload-Type\":\"text/html\",\"warc_filename\":\"/cc_download/warc_2020/CC-MAIN-2020-24/CC-MAIN-2020-24_segments_1590347390755.1_warc_CC-MAIN-20200526081547-20200526111547-00588.warc.gz\"}"}