2018 Reading List

1On Wings of SongThomas M. Disch
2The Left Hand of DarknessUrsula K. Le Guin
3Humanity PrimeBruce McAllister
4Fahrenheit 451Ray Bradbury
5Till We Have FacesC. S. Lewis
6Seeking Allah, Finding JesusNabeel Qureshi
7Nicaea and it’s LegacyLewis Ayres
8After Things Fell ApartRon Goulart
9The Truth About Uri GellerJames Randi
10Flim-FlamJames Randi
11Ship of FoolsC. R. Hallpike
12The Future of the People of GodAndrew Perriman
13The Last Days According to JesusR. C. SproulPerriman


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.~%"))))



Comments