When is a symbol a Symbol? Is there an easy Mathematica way to test if an object is a symbol sort of like a SymbolQ?
I'd probably use x_Symbol
in a function argument to control evaluation. Otherwise, one might do the following (thanks to @Leonid for pointing out an oversight).
If the argument is to be evaluated before testing:
SymbolQ = MatchQ[#, t_Symbol /; AtomQ[t]] &
If the argument is not to be evaluated:
SymbolQ = Function[s,
MatchQ[Unevaluated@s, t_Symbol /; AtomQ[Unevaluated@t]],
HoldAllComplete];
Examples with the second definition:
SymbolQ@Plot
(* True *)
x = 1;
SymbolQ[x]
(* True *)
Clear[y];
SymbolQ@y[1]
(* False *)
Addendum
Here's what I had in mind for makeRuleRow
:
ClearAll[makeRuleRow];
SetAttributes[makeRuleRow, HoldFirst];
makeRuleRow[symbol_Symbol, altname_ : "", desc_ : ""] :=
"execute body of function";
makeRuleRow[symbol_, altname_ : "", desc_ : ""] :=
Null /; (Message[makeRuleRow::sym, symbol, 1]; False);
makeRuleRow[123]
makeRuleRow::sym: Argument 123 at position 1 is expected to be a symbol.
(* makeRuleRow[123] *)
makeRuleRow[y]
(* "execute body of function" *)
Addendum 2
1.
You could use Replace
or Switch
to define name
in either way below:
ClearAll[makeRuleRow];
SetAttributes[{makeRuleRow}, HoldFirst];
makeRuleRow[symbol_, altname_ : Null, desc_ : Null] :=
Module[{name = "", prepend = ""},
name = Replace[Unevaluated@symbol, {
s_Symbol :> objectName[symbol]
, s_ /; StringQ@altname :> altname
, _ -> $Failed}
];
prepend = If[StringQ[desc], desc <> " ", ""];
{Row[{Style[prepend, desccolor], name, rule}],
TraditionalForm[symbol]} /; FreeQ[name, $Failed]];
makeRuleRow[symbol_, altname_ : Null, desc_ : Null] := Null /; (
Message[makeRuleRow::args, makeRuleRow]; False);
2. Or:
ClearAll[makeRuleRow];
SetAttributes[{makeRuleRow}, HoldFirst];
makeRuleRow[symbol_, altname_ : Null, desc_ : Null] :=
Module[{name = "", prepend = ""},
Switch[Unevaluated@symbol
, s_Symbol, name = objectName[symbol]
, s_ /; StringQ@altname, name = altname
, _, name = $Failed
];
prepend = If[StringQ[desc], desc <> " ", ""];
{Row[{Style[prepend, desccolor], name, rule}],
TraditionalForm[symbol]} /; FreeQ[name, $Failed]];
makeRuleRow[symbol_, altname_ : Null, desc_ : Null] := Null /; (
Message[makeRuleRow::args, makeRuleRow]; False);
Some may prefer Switch
because they know it from another language or just find it easier to read. Too many commas for me, and I find the Replace
method easier.
3.
There are a few ways to handle complicated argument checking. Another is to call an "internal" version which throws $Failed
when there's is an error:
func[symbol_, altname_ : Null, desc_ : Null] := Module[{res},
res = Catch[iFunc[symbol, altname, desc], func];
res /; FreeQ[res, $Failed]
];
iFunc[symbol_, altname_, desc_] := Module[{ ...},
If[error1,
Message[func::err1, ...];
Throw[$Failed, func]
];
If[error2,
Message[func::err2, ...];
Throw[$Failed, func]
];
...
res (* return result *)
];
4.
Yet another way is to have the outer function process the arguments and call the internal function with canonicalized arguments (for example, iMakeRuleRow[name_, desc_]
) or indicate an error. The internal function then can assume the arguments are valid.
I found my answer thanks to Sjoerd Smit who referenced me to the Mathematica Function Repository. And yes it is appropriately called SymbolQ
which is used like the following...
xxx = 123
ResourceFunction["SymbolQ"][xxx] (* returns True *)
A little bit ugly and long but it works. But why not fix if it isn't broken? And that is what I tried to do...
SetAttributes[symbolQ, HoldAllComplete];
symbolQ = ResourceFunction["SymbolQ"][#] &;
symbolQ[xxx] (* returns False *)
However Sjord came up with a solution that looks eerily similar to mine which leaves me scratching my head, why doesn't my alias work?...
SetAttributes[symbolQ, HoldAllComplete];
symbolQ[x_] := ResourceFunction["SymbolQ"][x];
symbolQ[xxx] (* returns True *)
How about:
SymbolQ[_Symbol] = True
SymbolQ[_] = False
?