In the context of programming languages, “magic” is often a pejorative term for code that does something other than what it appears to do.
Programmers seem to have a love/hate relationship with magic. Even people who say that don’t like magic (e.g. because it’s hard to debug) end up using it. The Haskell community prides itself on having a transparent language with no magic, and yet monads are slightly magical. The whole purpose of a monad is to hide explicit data flow, though in a principled way. Haskell’s do
notation is more magical, and templates are even more magical still. (However, I do hear some Haskellers express disdain for templates.)
People who like magic tend to use the word “automagic” instead. It means about the same thing as “magic” but with a positive connotation.
To conclude with a couple sweeping generalizations, magic fans tend to be tool-oriented (such as Microsoft developers) while magic detractors tend to be language-oriented (such as Haskell developers ).
Update: Someone asked me on Twitter about the difference between abstraction and magic. I’d say abstraction hides details, but magic is actively misleading or ironic.
Magic is relative. Functions and “while” loops were magical before the “structured programming” “fad” of the 1960s. My father was in “information sciences” at the time and he still has textbooks on his bookshelf such as “Structured Programming with Fortran IV” that remind me that nothing changes. He’s long since retired from computing, but still thinks in assembly and goto.
I disagree with the characterization of monads as *hiding* data flow. (>>=) is just an abstract description of how data flows are combined. In other words, it doesn’t hide the flow any more than (+) *hides* the process of addition.
I’m surprised that you bring up monads but not lazy evaluation. In my mind, lazy evaluation is much more magical.
I guess to me, magic isn’t about doing something “other than what it appears to do” (that’s a bit subjective–the monadic syntax seems pretty transparent to me). It’s more about how easy or hard the semantics are to infer/model.
Once you know a bit about monads, figuring out what a monad does is usually pretty straightforward. By contrast, lazy evaluation problems like memory issues from unforced thunks crop up everywhere, and it’s much harder to figure them out because they can require holding the whole program in your head and doing a lot of complicated inference.
Abstraction is where you hide unimportant details. Magic is where you hide important details.
To me, “automagic” implies that the speaker understands it – it is not magical to them – but the explanation would be too long or complicated for the present time. It’s a way of saying “trust me on this for the time being”.
That’s really only one way of using the term. The Jargon File gives a good overview of the other uses. Usually it just suggests deep knowledge that appears magical to those who don’t understand it (yet). That’s the sense in which it’s used in SICP, for example.