18
$\begingroup$

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" *)
$\endgroup$
24
$\begingroup$

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.

$\endgroup$
  • 2
    $\begingroup$ Note that ValueQ is not innocent - it leaks evaluation. Here is some discussion, where I also contributed an answer with what is supposed to be a safer version of valueQ based on one-step evaluation: stackoverflow.com/questions/4599241/…. It is overly complex, I know it can be written better, but the point is to be wary of the system ValueQ, to avoid nasty surprises. $\endgroup$ – Leonid Shifrin Jan 18 '12 at 20:55
  • $\begingroup$ @Leonid I think ValueQ is safe for as long as it's acting on a symbol only (i.e. is looking at OwnValues), but it evaluates the argument for anything else. Is this correct? I remember I looked at the implementation of ValueQ once (it's accessible) and concluded this, but that was a long time ago. $\endgroup$ – Szabolcs Jan 18 '12 at 21:14
  • 1
    $\begingroup$ Yes, I think I came to the same conclusions. Actually, in the linked SO discussion, I give some explicit example where it leaks evaluation. Can not dig in deeper now, need to get some sleep :). But for OwnValues only, there is a bullet-proof solution: (HoldComplete[sym]/.OwnValues[sym])=!=HoldComplete[sym] - very simple and robust. $\endgroup$ – Leonid Shifrin Jan 18 '12 at 21:25
9
$\begingroup$

You can also use MakeExpression

ValueQ @@ MakeExpression["abc2"]
$\endgroup$
2
$\begingroup$

This one is a different method to access symbol names and values (I think it originates from MathGroup):

(edited to fit the original question)

Attributes[symbolToRule] = {HoldAll, Listable};
symbolToRule[sym_String] := HoldForm[sym] -> Head[Symbol[sym]] =!= Symbol;
symbolToRule[sym_Symbol] := HoldForm[sym] -> ValueQ[sym];

with symbols:

{a, b = 5, c};
rules = symbolToRule[{a, b, c}]
Pick[First /@ rules, Last /@ rules]

output:

Mathematica graphics

with strings:

rules = symbolToRule[{"a", "b", "c"}]
Pick[First /@ rules, Last /@ rules]

output:

Mathematica graphics

$\endgroup$
  • $\begingroup$ Ah, but you're using {a,b,c} instead of {"a","b","c"}. That's the tricky part... :-) $\endgroup$ – Brett Champion Jan 18 '12 at 21:08
  • $\begingroup$ Ah, I see. Trying to cover this up cleverly... $\endgroup$ – István Zachar Jan 18 '12 at 21:14
  • $\begingroup$ @IstvánZachar pretty neat approach. +1 ! $\endgroup$ – Ali Hashmi Feb 5 '17 at 12:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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