Do we have a canonical answer for “Why doesn't b=a; f[a_]:=b; f return 1”?

There exist many related posts, but has it ever been explained in a clear and detailed enough way?

Notice a variant of the question in title is

Why doesn't

lst = {a, b, c};

return

{f[a], f[b], f[c]}

?

• Comments are not for extended discussion; this conversation has been moved to chat. – Kuba Jan 29 at 17:23
• To the downvoter, I am interested in what's wrong with my question, would you please elaborate. I'm not trying to complain here, I just want improve my question if possible. – xzczd Jan 31 at 13:28

ANSWERING THE QUESTION IN THE TITLE:

I'm not sure exactly what you don't understand about this, but I can take you through this step by step.

b = a is a symbol assignment. It tells Mathematica "from now on, replace b with a."

Next, f[a_] := b defines a replacement rule. The a_ is a named pattern, and it is unrelated to the symbol a mentioned in the first line. This rule is exactly the same as the rule f[x_] := b -- the rule doesn't care what you name the pattern. It tells Mathematica to "replace every expression with f as the head and one argument with b".

Finally, f is evaluated. The second rule tells Mathematica to replace this with b. Then the first rule tells Mathematica to replace this with a.

I'm not sure what exactly is confusing about this. It's important to understand that Mathematica is a pattern-replacement machine.

ANSWERING THE SECOND QUESTION:

Unevaluated@f[lst] tells Mathematica not to evaluate "lst", so, as far as Thread is concerned, lst is just an undefined symbol.

So, Thread[Unevaluated@f[lst]] is evaluated the same way as Thread[f[X]] where X is just an undefined symbol, which would give f[X].