0
$\begingroup$

ValueQ returns True when for example on the following test (from a clean kernel with no assignments to f):

test := Module[{a = 1}, ValueQ[f[a]]]

I guess this is because a gets replaced in f[a]. This is not the behavior I want. Is there an easy way to get more intuitive version of ValueQ that checks whether there is a value for f["evaluated form of arguments"]. (Possibly unless f has a holdall attribute but it is not important.)

I tried alternative versions of valueQ that try to avoid the evaluation of the the argument of ValueQ as described in https://mathematica.stackexchange.com/a/1484/45020 and https://mathematica.stackexchange.com/a/1485/45020, but they don't produce the behavior I want either.

I don't care much about leaking of the argument of ValueQ but would prefer the whole expression f[args] to not be evaluated since it is slightly cleaner (it might be expensive to evaluate).

$\endgroup$
1
  • $\begingroup$ Does f Have an assigned value in your code? If so, what is it? $\endgroup$
    – MarcoB
    Jun 2, 2020 at 13:50

1 Answer 1

0
$\begingroup$

It seems that the simplest solution is to insert all (fully evaluated) arguments of f using With. That insertion happens before ValueQ and are thus not counted as f[arg] having a value because of any transformation of arg.

For example,

test := Module[{a = 1}, With[{i = a}, ValueQ[f[i]]]]

For a single argument function f the following works:

SetAttributes[valueQ,HoldAll]
valueQ[f_[args__]]:=With[{argEvaluated=args},ValueQ[f[argEvaluated]]]

See

test1[a] = 1;
Module[{i1 = a}, valueQ[test1[i1]]]
Module[{i1 = b}, valueQ[test1[i1]]]

but it does not work in the multi-argument case. (I don't know how to do the proper insertion to the final evaluated sequence there.)

test2[a, b] = 1;
Module[{i1 = a}, valueQ[test2[i1, b]]]
Module[{i1 = b}, valueQ[test2[i1, b]]]

A stupid but effective fix seems to be to add n separate definitions where n is the maximal expected arguments of functions inside valueQ,

SetAttributes[valueQ,HoldAll]
valueQ[f_[a1_,a2_]]:=With[{aE1=a1,aE2=a2},valueQNoEval[f[aE1,aE2]]]

SetAttributes[valueQ,HoldAll]
valueQ[f_[a1_,a2_,a3_]]:=With[{aE1=a1,aE2=a2,aE3=a3},valueQNoEval[f[aE1,aE2,a3]]]
...

(Finally we can combine this with the linked versions of valueQ in order to get something that does not evaluate the full expression (avoiding side effects and wasted computational resources), but does evaluate the arguments as requested here.)

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.