Let me repeat again:
If a function doesn't have a HoldAll
/HoldFirst
/HoldRest
/HoldAllComplete
attribute, its argument(s) will always be evaluated before going into the function.
ReplaceAll
(/.)
doesn't have such attribute, so the whole {x, x^2, Length@x, Subsets[x]}
evaluates before the replacement happens. (The order is from left to right, BTW. ) This can be checked with Trace
:
Trace[{x, x^2, Length[x], Subsets[x]} /. x -> {1, 2, 3}]

If you want to check the evaluation of x
and x^2
, set TraceOriginal -> True
, the output will be a bit more involved, though.
As we can see, Length@x
evaluates to 0
. This is expected. As mentioned in Details section of document of Length
:
Length[expr]
returns 0
whenever AtomQ[expr]
is True
.
Subsets[x]
evaluates to itself with a warning Subsets::normal
. Since the Subsets[x]
is still there, once the replacement happens, it'll become Subsets[{1, 2, 3}]
and further evaluates to the desired output.
Finally, in addition to the Hold
& ReleaseHold
technique shown in rhermans' answer, another (more advanced) way to adjust the evaluation order is to use Unevaluated
:
Unevaluated@{x, x^2, Length[x], Subsets[x]} /. x -> {1, 2, 3}
(* {{1, 2, 3}, {1, 4, 9}, 3, {{}, {1}, {2}, {3}, {1, 2}, {1, 3}, {2, 3}, {1, 2, 3}}} *)
Length
evaluates to be0
; checkLength@x
. Not sure what you mean when you say it does not evaluate. Also, the argument ofSubset
has to be a list, and currently it is not, hence the error. $\endgroup$Length
andSubsets
evaluate after replacement? Then x will be List! And why we see right result ofSubsets
? $\endgroup$Length@x
gives0
. Is it possible that you want to writefoo[n_] := {x, x^2, Length@Range@n, Subsets[Range@n]} /. x -> Range@n
and thenfoo[3]
? $\endgroup$