Właściwie funkcja ValueQ nie jest niewinny, ponieważ przecieki ocenę dla kodu z efektów ubocznych. Przykłady:
ClearAll[f, g];
f[x_] := Print[x];
g[x_][0] := Print[x];
{ValueQ[f[1]],ValueQ[g[2][0]]}
Jeśli usuniesz ReadProtected atrybutem ValueQ i spojrzeć na kod, widać dlaczego - kod jest bardzo proste i robi dobrej pracy dla zaledwie OwnValues. Tutaj jest bardziej skomplikowana wersja którą opracowano w celu uniknięcia tego problemu (można sprawdzić, że, przynajmniej na powyższych przykładach, to nie przecieka ocenę):
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]];
To nie jest pełna albo, ponieważ nie robi Uwzględnij UpValue, NValue i FormatValues, ale wydaje się to wystarczające dla twoich określonych potrzeb, a także reguły dla tych trzech dodatkowych przypadków mogą być również dodane w taki sam sposób jak powyżej.
Świetnie, wydaje się działać zgodnie z oczekiwaniami dla wszystkich 3 formularzy –