Anatomy of Programming Languages by William R. Cook.
From the Introduction:
In order to understand programming languages, it is useful to spend some time thinking about languages in general. Usually we treat language like the air we breathe: it is everywhere but it is invisible. I say that language is invisible because we are usually more focused on the message, or the content, that is being conveyed than on the structure and mechanisms of the language itself. Even when we focus on our use of language, for example in writing a paper or a poem, we are still mostly focused on the message we want to convey, while working with (or struggling with) the rules and vocabulary of the language as a given set of constraints. The goal is to work around and avoid problems. A good language is invisible, allowing us to speak and write our intent clearly and creatively.
The same is true for programming. Usually we have some important goal in mind when writing a program, and the programming language is a vehicle to achieve the goal. In some cases the language may fail us, by acting as an impediment or obstacle rather than an enabler. The normal reaction in such situations is to work around the problem and move on.
The study of language, including the study of programming languages, requires a different focus. We must examine the language itself, as an artifact. What are its rules? What is the vocabulary? How do different parts of the language work together to convey meaning? A user of a language has an implicit understanding of answers to these questions. But to really study language we must create an explicit description of the answers to these questions.
The concepts of structure and meaning have technical names. The structure of a language is called its syntax. The rules that defined the meaning of a language are called semantics. Syntax is a particular way to structure information, while semantics can be viewed as a mapping from syntax to its meaning, or interpretation. The meaning of a program is usually some form of behavior, because programs do things. Fortunately, as programmers we are adept at describing the structure of information, and at creating mappings between different kinds of information and behaviors. This is what data structures and functions/procedures are for.
Thus the primary technique in these notes is to use programming to study programming languages. In other words, we will write programs to represent and manipulate programs. One general term for this activity is metaprogramming. A metaprogram is any program whose input or output is a program. Familiar examples of metaprograms include compilers, interpreters, virtual machines. In this course we will read, write and discuss many metaprograms.
I have only started to read this book but to say:
A good language is invisible, allowing us to speak and write our intent clearly and creatively.
May describe a good quality for a language but it is also the source of much difficulty.
Our use of a word may be perfectly clear to us but that does not mean it is clear to others.
Wood you believe that I didn’t no
About homophones until too daze ago?
That day in hour class in groups of for,
We had to come up with won or more.
Mary new six; enough to pass,
But my ate homophones lead the class.
Then a thought ran threw my head,
”Urn a living from homophones,” it said.
I guess I just sat and staired into space.
My hole life seamed to fall into place.
Our school’s principle happened to come buy,
And asked about the look in my I.
“Sir,” said I as bowled as could bee,
My future roll I clearly see.”
“Sun,” said he, “move write ahead,
Set sail on your coarse, Don’t be mislead.”
I herd that gnus with grate delight.
I will study homophones both day and knight,
For weaks and months, through thick oar thin,
I’ll pursue my goal. Eye no aisle win.
—George E. Coon
The Reading Teacher, April, 1976
I first saw this at Verbal Confusion.