It's hard to pin it down to just a couple of things, because I came across SICP early in my programming life and it changed so much of my approach to the art. But here are a couple:<p>1. It taught me to think of programming languages as constructed things, rather than just being "there" and immutable. In particular, to think about the purpose of each language feature, and separating features into core primitives vs. syntactic sugar that could be reduced to those core primitives. It becomes harder to do this for "complicated" languages like C++ and Python, because many of their language features are not for one purpose but bundle together lots of disparate ideas. But it's still worth making the effort to see what choices the designers of those languages made, and how different choices would give you different points in the space of programming languages.<p>2. Once you have a small enough "core language", you can start thinking about algorithms that operate on programs. I had always thought of programs as expressing algorithms that operate on data, but didn't think of programs as data themselves. Of course every program is text, but in complicated languages with many constructs it seems horrendously hard to write programs that operate on other programs and change their meaning. But if your language desugars to a simple core language, the ability to transform programs opens the door to techniques like automatic differentiation of programs, probabilistic programming (like Church), and many others. These would now be called domain-specific languages, but those are often thought of as limited toys for very specific tasks. Instead, I like to think how every task has the "right" language to express it, and when you do API design you're really embedding a DSL in some "host language".<p>Since you asked, the other big development in my approach to programming came from learning Haskell and embracing types as an elegant way of expressing universal truths about programs. Sometimes the type of a function fully determines what the function can be, like how the only function of the type (forall a) a -> a is the identity function; this idea becomes more revelatory with more complicated types.<p>I don't use functional programming very much in my day-to-day life, but I think learning these ideas has shaped my approach to every language. It's not really about the superficial "functional patterns" that people often think of, like using map and filter and such, which is often idiomatically wrong in many other languages.