I have run into a problematic behavior, and then came to find that it is a "possible issue" called out in the documentation, but I guess I am just baffled that this IS an issue, and am wondering why. The example from the documentation is:
In the presence of global variables, pattern variables may show unexpected behavior:
x=5; f[x_]=x^2; f
The result of this is 25. I am utterly shocked that Mathematica doesn't recognize that within the definition of f, it should treat x as local. Every other programming language I have used recognizes this. And I swear that earlier versions of Mathematica recognized this, though I suppose I could have never tested it.
Why is this the behavior? Is there any way to fix the problem without resorting to a delayed assignment?
Edited to add: Many people are suggesting memoization and/or simply understanding the execution model of Mathematica. Unfortunately, the situations where I am decrying this behavior is not helped by memoization. Imagine a function f[x_,y_,z_,n_,l_,m_,p1_,p2_,p3_] that is defined over all real values of x, y, and z, and for some subset of integers n, l, and m, and applies to different systems based on real-valued parameters p1, p2, and p3. The function itself is complicated, and computationally intensive. Often this function is then combined into a composite function that still depends on the same variables and parameters, but which has multiple offsets (so g is f[x-x1,y-y1,z-z1,...] added together for multiple offsets). And then I need to integrate g over x, y, z to normalize it and then I need to ContourPlot3D the resulting function. In order to make the integration and plotting not take forever, I need Mathematica to do as much preprocessing simplification as possible, which means using Set instead of SetDelayed. The calculations are over all 3D space, so memoization doesn't help.
Further, the applications are part of a college class I teach that uses Mathematica as a tool, but isn't itself about Mathematica, so the goal is to give the students a just-in-time introduction to the Mathematica skills they need to solve the content-specific problems they are being tasked with. So, I give them code that they can copy-and-paste to do complicated stuff, and then expect them to modify calls to that code to apply the concepts to new problems. And here's the issue... if I have a parameter that all of the textbooks call De, then it makes sense to define the function with De as the name of the parameter in order to make calling that function more transparent. And it also makes sense for the students to plug in their values for De into a variable they name De. Many of these students have a tiny bit of programming experience before my class, and so expect the behavior to be similar to the languages they have used before. And in many, many cases that expectation is reasonable. But not in this case, which is why I asked my question. I cannot afford to devote significant time in class to the execution model of Mathematica when for nearly every other purpose a student approaching Mathematica as a procedural language is sufficient for my course.
So thank you all for your responses. And I apologize for venting.