November 2018
2018 Reading List
11/30/18 11:41 AM Filed in: Books
1 On Wings of Song Thomas M. Disch 2 The Left Hand of Darkness Ursula K. Le Guin 3 Humanity Prime Bruce McAllister 4 Fahrenheit 451 Ray Bradbury 5 Till We Have Faces C. S. Lewis 6 Seeking Allah, Finding Jesus Nabeel Qureshi 7 Nicaea and it’s Legacy Lewis Ayres 8 After Things Fell Apart Ron Goulart 9 The Truth About Uri Geller James Randi 10 Flim-Flam James Randi 11 Ship of Fools C. R. Hallpike 12 The Future of the People of God Andrew Perriman 13 The Last Days According to Jesus R. C. Sproul
Still reading: Ceremony, by Leslie Marmon Silko; Lost in the Cosmos, by Walker Percy; The Female Man, by Joanna Russ; Common Lisp Recipes, by Edi Weitz; The Letter to the Colossians and to Philemon, by Douglas Moo; Infinity and the Mind, by Rudy Rucker.
Comments
Goto considered harmful
Y-Combinator recently had an item about The History, Controversy, and Evolution of the Goto Statement [pdf]. The .pdf considers the "right" way to implement code that computes the average of integers read from the standard input, where the value 99999 is used to denote end-of-input. Code written in C is presented on page 10 and is offered as a good solution. It avoids an explicit goto by using a break statement but, in so doing, misses the forest for the trees. It entangles obtaining data with processing the data and this is almost always a bad idea. But C makes it hard to write better code because C doesn't have built-in support for lists. The following Lisp code separates concerns, promotes code reuse, and the only explicit loop construct is the recursive call by read-input to collect data up to the end-of-data sentinel. C needs constructs like for, break, and continue because it's weak on data structures and memory management. It's also a strongly typed language: variables have types and types have values. In Lisp, however, variables have values and values have types which makes it easier to write generic code.
(defun read-input (&optional (result nil))
(let ((value (read)))
(if (equalp value 99999)
(reverse result)
(read-input (cons value result)))))
(defun average (numbers)
(let ((n (length numbers)))
(if (zerop n)
nil
(/ (reduce #'+ numbers) n))))
(defun main ()
(let ((avg (average (read-input))))
(if avg
(format t "~f~%" (float avg))
(format t "no numbers input. average undefined.~%"))))