Programming Language Pragmatics, Fourth Edition, is the most comprehensive programming language textbook available today. It is distinguished and acclaimed for its integrated treatment of language design and implementation, with an emphasis on the fundamental tradeoffs that continue to drive software development.
The book provides readers with a solid foundation in the syntax, semantics, and pragmatics of the full range of programming languages, from traditional languages like C to the latest in functional, scripting, and object-oriented programming. This fourth edition has been heavily revised throughout, with expanded coverage of type systems and functional programming, a unified treatment of polymorphism, highlights of the newest language standards, and examples featuring the ARM and x86 64-bit architectures.
The scope of "Proglangprag" (how I've taken to saying it) is enormous. It is not only a (fairly) comprehensive survey of languages, but also a pretty decent guide to understanding how languages are parsed, scanned, and turned into machine language.
Make no mistake: you won't be able to write a compiler for your own language using just this book as your guide. Nor will you be able to write any functioning programs of your own in any of the languages featured in this book.
So what's the point? Well, sometimes you have to take a step (or two) away from the keyboard and get a birds-eye view of a subject. Proglangprag is a meticulous guide to the landscape of programming languages.
It's a topic so enormous that it takes a book this big to even explore the territory. In no way can it take the time to explore a language or concept in enough detail for you to do anything practical on a keyboard.
As it is, many whole chapters were removed from the book and put on a companion CD (included with the book). I wish these chapters had been included so that I could have read them from the comfort of my couch like the rest of the book (I sure has heck wasn't going to print them all out). As the author himself states, they're not superfluous chapters and they're worth reading.
Reading Proglangprag straight through is not a fun task by any means. It took me two long months to complete. And now that it's four months later, I couldn't regurgitate any of the material without having to consult the book. But that's not why I read books like this. I read them to fill in gaps in my knowledge and to give these topics familiarity when I come across them again. In this respect, Proglangprag served my needs perfectly.
I wrote a parser for a text-based adventure game system I created called Hoot before, during, and after I read this book. I can say from real, practical experience that familiarity with the material in Proglangprag can make an excellent guide to further research into these topics. Even just knowing the right terminology cannot be overvalued.
Michael Scott's writing is quite dry. You won't be chuckling while you read this, or even getting any of those faint grins you might crack when reading Donald Knuth's footnotes. At times, it's just plain boring, even if you're quite interested in the topic. Nonetheless, I know of no other book with the same range or scope, which puts this in a class of its own and worth reading for that reason alone.
In the end, these are topics with which every programmer should be acquainted. If you've any doubts, bust this beast open and read until you get to the last page. You can thank (or choke) me later.
Programming is an activity and there is no doubt that (here as always) it's practice that makes perfect. Yet, as Michael Scott explains, there are reason you might want to have a closer look at your main tool, the languages in which you write your programs.
If you know the essential differences between different programming languages, you are in a better position to decide what best to use for a task at hand. Equipped with more technical concepts, you might find it easier to understand obscure features (like closures or the dereference operator) and learn new languages. With an idea about implementation details you might be able to assess performance trade-offs and make informed decisions about the design of extensive software projects.
For me personally it was an interest in the intricacies of language design that made me pick up this book. You might say I'm interested in programming languages as languages. I approached the book from the angle of computation linguistics, a field motivated by the belief that natural languages (like English or Turkish) are formal languages akin to programming languages, or can at least be described as if they were.
In more formal disciplines (like syntax or semantics), linguists make use of tools that originated or were first practically applied in computer science to define high-level programming languages. Because these languages resulted from conscious design and implementation decisions, they are freed from many of the complications that plague the study of real languages (like vagueness or ambiguity); as a result, it's probably easier to learn the relevant methodology in respect to the artificial languages and only later return to the real deal. Or at least so it appears from my laymen perspective.
Obviously, natural languages are implemented very differently in the human brain than programming languages are in the computer. Maybe this explains why I was less bothered about the implementation details that underlie design decisions and that are a main concern of the textbook. Of course, computer linguists use tools like scanners or parsers to generate language applications, but when it came symbol tables, registers, microprocessors, or the algorithmic definition of when an object is no longer useful (to be garbage-collected) I found myself skipping ahead. So, even to say that I've read only the core chapters – the chapters 1 to 10 – it would be an overstatement.
But even if you are only interested in the conceptual dimension of Programming Language Pragmatics, it's still a highly rewarding read. For instance, you might be surprised how much there is to learn about names and scopes. I'm sure I wasn't quite aware of the subtle differences between overloading (names can stand for different things in different contexts), coercision (the automatic converting of values from one type into another), and polymorphism (one and the same function allows for arguments of different times).
Variables too are deceptively simple. Yet, what they really are might be different from one language to the next, or even within a given language. Variables could be like boxes that contain values (the value model); or they might be references to values that (in a sense) live somewhere else in memory (the reference model). This distinction is related to other distinctions. For objects to exist, the computer needs to allocate memory. This is not a trivial matter, especially for data structures that can grow or shrink dynamically during runtime. The latter objects are created on the so-called heap, while objects of more primitive types live on the stack. A language like Java uses both; in some languages you can explicitly define variables to be of the one or of the other kind.
Similarly, there are different modes to pass objects as arguments into subroutines, namely call by reference, call by value, and even call by sharing. Speaking of subroutines, the author gives names for the two obvious kinds, i.e. the ones that return a value (functions) and the ones that do not (procedures). Throughout the book there are some occasions to introduce helpful terminology for familiar concepts. Additionally, footnotes point to inconsistent terminology between different languages. For instance, words like "functor" or "object" or "barrier" might mean different things for different people.
To better understand what's unique to given approaches, it's often helpful to contrast them with other options. The author gives illuminating examples from a vast variety of languages, very old (like Fortran) and newer (like Python) alike. There is also some attempt to explain why certain paths had been abandoned in favor of others, and why some approaches mark a clear progress over attempts of the past. For instance, it explains why `goto` statements are basically extinct today in favor of more structural concepts or why asynchronous events are now thread-based rather than based on coroutines and interrupts.
If you are motivated to really understand how compilers work and what makes different programming languages tick "under the hood", I'm sure you can spend months with this book. There are many exercises and suggestions for further research. If you want to pursue issues in even more detail, there are bibliographical notes that mostly point to the historical origins of now popular ideas. But even if you won't pursue all matters, Programming Language Pragmatics would be a great reference book even if you come across some interesting ideas in the future and you want to get some background. Not the least because of its very extensive Index.
Excellent coverage of both fundamental and advanced topics; while some of the sections more related to compilation are excised from the main text, they are freely available on the publisher's site (and recommended). While I read this through in the order the text was presented, it would also be useful as a reference guide / amenable to reading subsections in alternate orders.
Overall, "Programming Language Pragmatics" (PLP) is a very good book. According to the Preface:
"It aims, quite simply, to be the most comprehensive and accurate languages text available, in a style that is engaging and accessible to the typical undergraduate....
At its core, PLP is a book about how programming languages work. Rather than enumerate the details of many different languages, it focuses on concepts that underlie all the languages the student is likely to encounter, illustrating those concepts with a variety of concrete examples, and exploring the tradeoffs that explain why different languages were designed in different ways."
I'm not knowledgeable enough to pass judgment on "the most comprehensive and accurate" part. But, I'm pretty happy about the book meeting the rest of those goals. I read through the book on my own and have only a few significant gripes:
- Chapters 2 (Programming Language Syntax) and 4 (Semantic Analysis) are tough to get through. They're basically trying to teach enough about Alphabets, Languages, Regular Expressions, Context-Free Grammars, Finite Automata and Push-Down Automata for the reader to understand what the rest of the book is based on. I've read Cohen's Introduction to Computer Theory , which is dedicated solely to this material and I still had some trouble. With an instructor in a class to walk through the things, it should be doable. But, for a person reading the book on his own, ugh.
- All of Section III: Alternative Programming Models, seems to depart from the format of the rest of the book (as noted in the Preface) where the author talks about the concepts and then how the different languages implement them. Instead, he focuses on the languages themselves and almost seems to be trying to cram a primer into his text. Since the section seems to be a special case, it wouldn't be so bad except that the languages covered are a bit out of the mainstream and so that degree of depth gets pretty unreadable at times. Again, with a professor around, things would be better.
- At a more pedagogical level, the author has a tendency to merely explain what his example Figures are doing in general terms. The problem is that a lot of the code/pseudocode involves fairly advanced structures in several languages (many of which most people won't have run across). It would have made things a lot easier if he had walked his way through each of those Figures line-by-line and explained what each line did. Once again, this wouldn't be that much of a problem in a normal teaching environment since a professor could do it.
Other than those three things, this is a very good and readable book. I rate it at four stars out of five.
Bought this book in about 2000 for a college course, and held onto it all this time. The class was only a quarter, so I'm sure we didn't go through the whole book in that time. I just reread it from cover to cover, and it has held up pretty well. The newest language covered in my copy was java, but the fundamentals of languages don't change that much in ten years, and I felt like it was a good refresher and overview of some technical things that you just don't interact with much in a non-academic setting.
This book goes into detail how and why different parts of programming languages are implemented, it uses different languages to help covey the implementation details and how it differs between them.
Whereas a specific programming language book will cover how to use that language, this book helps to understand what goes into the languages and their development, why different languages are suited to certain tasks.
This is a perfect overview of programming languages, their taxonomy, and how they work. Essential reading (and re-reading) for the self-taught or working programmer! The balance between breadth and depth is exactly right and this edition has been updated to include newer languages like Scala, Go and Swift. Belongs on every programmers' bookshelf.