I have very mixed emotions about this book. On the one hand, it is perhaps the best introductory work on the philosophical and theorectical issues of computation, dealing with many concepts that normally are either taken for granted by most programmers, or else are completely unknown to them. If you get past the dry, analytical tone (and the rather flat punnery), it actually becomes quite engaging. It is a book that demands careful thought on the part of the reader, and can reward dilligent and thoughtful study. It scrutinizes even such seeming obvious concepts as recursion and assignment, and often reveals a great deal of hidden complexity to them.
However, by itself it is not a very good primer to progamming, either in theory or in practice. The examples given are often unnecessarily tortuous, especially given the imperative to teach strict functional design in the first several chapters. Too much effort has been given to keeping it at 'pure' and 'general', and there is little attempt to connect the important ideas with how they appear in actual use.
Among the flaws is too great a concern with language independence, and specifically, an obsession with presenting the fewest possible language constructs needed to achieve a given purpose. It makes no attempt to present the Scheme language itself except where it is absolutely necessary in order to give an example; while this is done to keep the discussion as general as possible, it often has the effect of confusing the student. Many example programs which would be crystal clear with the use of certain language facilities are made hopelessly incoherent because the authors wanted to enforce 'language independence'.
Also, because many aspects of the language are ignored as irrelevant, the students learn only a small part of the language itself, and are left with the impression that Scheme is a hamstrung, pedantic language lacking in many obvious features. From reading SICP, few would ever imagine that it supported strings, characters and vectors, or had an iterative construct (do), an escape mechanism (call/cc), a macro facility (let-syntax and syntax-rules), or even basic stream I/O (read and write). Scheme is a simple enough language as it is; it need not be pared down any further no matter how noble the purpose.
More importantly, much of the presentation so abstracted as to be completely divorced from real practice, especially in the sections on imperative and OO programming. While this is a good thing in many ways, as it shows the conceptual underpinnings which are so often lost in day-to-day programming, no attempt is made to draw a connection between the theoretical abstractions and the concrete practices. The ideas are left floating aimlessly, and the student is left with no clue as to their relevance or value - which is a pity, because they truly are important, and understanding them can make the difference between a true programmer and a mere coder.
The section on logic databases is an excellent example of this. While it presents all the elements of keys, querying, unification, etc. in a lucid, detailed fashion, the databases are represented solely as list structures. No mention of files is made at all, in this section or anywhere else in the book - the word 'file' does not even appear in the index. Nor does it reveal that most database work today is based on the relational calculus, not predicate logic.
Similarly, the discussion of streams concentrates solely on their use as a way of representing change in state over time; not only are ports (Scheme's stream I/O mechanism) ignored, at no point is the student given any hint at all that the primary use of streams is for input and output. This is like discussing driving without ever admitting the existence of roads; it is abstraction run rampant. While the discussions are wondefully insightful, the student isn't given any way to apply them, even within the context of study.
In the end, I would strongly recommend this book as a supplement to an introductory course based around another Scheme text, such as Simply Scheme. While I think that every serious student of computer science (as independent from software engineering) should study it, really requires the work of a gifted teacher to make it clear, and it should never be used as the sole text. It is a brillant piece of work, and a wonderful source of key insights into programming, but it does not stand alone.