I'm reading Structure and Interpretation of Computer Programs, which MIT Press has kindly made available on line. Here is a tasty nibblet from the preface to the first edition:
Our design of this introductory computer-science subject reflects two major concerns. First, we want to establish the idea that a computer language is not just a way of getting a computer to perform operations but rather that it is a novel formal medium for expressing ideas about methodology. Thus, programs must be written for people to read, and only incidentally for machines to execute. Second, we believe that the essential material to be addressed by a subject at this level is not the syntax of particular programming-language constructs, nor clever algorithms for computing particular functions efficiently, nor even the mathematical analysis of algorithms and the foundations of computing, but rather the techniques used to control the intellectual complexity of large software systems.As a hobby I've been learning Common Lisp. Several folks in the comp.lang.lisp newsgroup have recommended SICP to folks who desire to improve their knowledge of the theoretical underpinnings of Lisp, so here I am.
It all started when someone in c.l.l asked "why does lisp need the 'apply' function?". As an exploration of this question I attempted the impossible task of implementing Lisp's 'apply' using Common Lisp macros and the 'funcall' function. If you resort to also using the 'eval' function then it is possible to define 'apply'. Of course having to resort to calling 'eval' is a terrible price to pay. This is why Lisp defines 'apply' as a primative. (it is trivial to define 'funcall' in terms of 'apply' -- you don't even need to use macros much less 'eval'. To wit: "(defun funcall (fn &rest arg) (apply fn rest))").
BTW, for you folks who don't know Lisp, Lisp macros are very powerful. The macro system provided by the C language preprocessor is nothing compared to lisp macros. Lisp macros are more powerful than C++ templates. If you haven't studied Lisp it is hard to conceive what Lisp macros are capable of.