На самом деле, функция ValueQ не невинна, так как она просачивается оценками для кода с побочными эффектами. Примеры:
ClearAll[f, g];
f[x_] := Print[x];
g[x_][0] := Print[x];
{ValueQ[f[1]],ValueQ[g[2][0]]}
Если удалить ReadProtected атрибут ValueQ и посмотреть на код, вы увидите, почему - код очень упрощенно и делает достойную работу для всего OwnValues. Вот более сложный вариант, который я разработал, чтобы избежать этой проблемы (вы можете проверить, что, по крайней мере, на приведенных выше примерах, не вытекла оценки):
ClearAll[symbolicHead];
SetAttributes[symbolicHead, HoldAllComplete];
symbolicHead[f_Symbol[___]] := f;
symbolicHead[f_[___]] := symbolicHead[f];
symbolicHead[f_] := Head[Unevaluated[f]];
ClearAll[partialEval];
SetAttributes[partialEval, HoldAllComplete];
partialEval[a_Symbol] /; OwnValues[a] =!= {} :=
Unevaluated[partialEval[a]] /. OwnValues[a];
partialEval[a : f_Symbol[___]] /; DownValues[f] =!= {} :=
With[{dv = DownValues[f]},
With[{eval = Hold[partialEval[a]] /. dv},
ReleaseHold[eval] /;
(First[Extract[eval, {{1, 1}}, HoldComplete]] =!=
HoldComplete[a])]];
partialEval[a_] :=
With[{sub = SubValues[Evaluate[symbolicHead[a]]]},
With[{eval = Hold[partialEval[a]] /. sub},
ReleaseHold[eval] /;
(First[Extract[eval, {{1, 1}}, HoldComplete]] =!=
HoldComplete[a])]];
ClearAll[valueQ];
SetAttributes[valueQ, HoldAllComplete];
valueQ[expr_] := partialEval[expr] =!= Unevaluated[partialEval[expr]];
Это не полный либо, так как он не учет UpValues, NValues и FormatValues, но этого, кажется, достаточно для ваших заявленных потребностей, а также правила для этих трех дополнительных случаев, возможно, также могут быть добавлены по тем же линиям, что и выше.
Отлично, кажется, работает как ожидалось для всех 3 форм –