evaluation - How can I test properties of a symbol from the string name without the symbol completely evaluating
Suppose I have a few symbols, one of which has a value:
{abc1, abc2 = 5, abc3};
I can use Names
to get the list of names, as strings:
InputForm[names = Names["Global`abc*"]]
(* {"abc1", "abc2", "abc3"} *)
Now I want to find which symbols have values. This fails, because ValueQ
expects the first argument to be a Symbol
, not a String
:
Select[names, ValueQ]
(* {} *)
This fails (with lots of messages), because ValueQ
doesn't evaluate the argument enough:
Cases[names, st_ /; ValueQ[Symbol[st]]]
(* {"abc1", "abc2", "abc3"} *)
If we force evaluation, we go too far, and this fails because we get ValueQ[5]
instead of ValueQ[abc2]
:
Cases[names, st_ /; ValueQ[Evaluate[Symbol[st]]]]
(* {} *)
This approach works, but is far from elegant:
Cases[names, st_ /; ToExpression["ValueQ[" <> st <> "]"]]
(* "abc2" *)
Answer
I usually use
ToExpression["symbol", InputForm, ValueQ]
ToExpression will wrap the result in its 3rd argument before evaluating it.
Generally, all functions that extract parts (Extract
, Level
, etc.) have such an argument. This is useful when extracting parts of held expressions. ToExpression
acts on strings or boxes, but both the problem with evaluation control and the solution is the same. I thought this was worth mentioning here.
Comments
Post a Comment