19
$\begingroup$

I'm trying to get the name of a symbol passed to a function with this:

f[x_] := {SymbolName[x], x}
SetAttributes[f, HoldFirst]
x = 5;
f[x]

But x is being evaluated anyway:

SymbolName::sym: Argument 5 at position 1 is expected to be a symbol. >>
{SymbolName[5], 5}

What am I missing here?

$\endgroup$
4
  • $\begingroup$ I'm fairly certain this is a duplicate. Please help me locate it, or correct my assertion. $\endgroup$
    – Mr.Wizard
    Dec 4, 2012 at 13:13
  • $\begingroup$ @Mr.Wizard If it's a dupe (quite possible), then I haven't seen the original, since I don't recall it. $\endgroup$ Dec 4, 2012 at 13:16
  • $\begingroup$ @Leonid perhaps I was thinking of this question but that is the converse of the present one, or perhaps it was on Stack Overflow. $\endgroup$
    – Mr.Wizard
    Dec 4, 2012 at 13:24
  • $\begingroup$ @Mr.Wizard That one is related, but not a dupe. But the issue is very common, I would not be surprised if it was asked in some slightly different context before. $\endgroup$ Dec 4, 2012 at 13:30

1 Answer 1

23
$\begingroup$

You are missing Unevaluated:

SetAttributes[f, HoldFirst]
f[x_] := {SymbolName[Unevaluated@x], x}

because SymbolName does not hold its arguments, so you have to prevent evaluation also there.

Generally, if you are passing some argument via a chain of function calls, and want to keep it unevaluated, you have to prevent it's evaluation at each stage (function call). If the chain is long, it may be easier (and more robust) to wrap the argument in Hold, for the passing purposes, and unwrap in the function that actually needs it.

Note by the way that it is better to set attributes before you give definitions to a function, to avoid some surprises, unless you know precisely what you do and why.

$\endgroup$
8
  • 1
    $\begingroup$ "... it is better to set attributes before you give definitions to a function, to avoid some surprises." I argue that it's better to set the Attribute at the appropriate time, being mindful of the ramifications of the order. This has powerful uses as you know. I know what you are trying to warn new users against but for a long time that "rule" kept me from understanding and using Attributes to their full potential. Maybe this is one of those "you must know the rules before you decide to break them" cases. $\endgroup$
    – Mr.Wizard
    Dec 4, 2012 at 13:22
  • $\begingroup$ @Mr.Wizard I stand by what I advised. Those who know these advanced uses know what they do. Most people would find it highly confusing when their functions would not work according to their definitions, only to discover (with pain, hours later), that there was some evaluation happening at definition-time which ruined their definitions. I am speaking from personal experience here, but I know that lots of other people got into this trap at some point, and more than once. $\endgroup$ Dec 4, 2012 at 13:27
  • $\begingroup$ You already had my vote but I appreciate the addition. Quite reasonably your answers are generally viewed as authoritative (even if you disagree) and it's good, IMHO, to at least allow for situations where an Attribute is not set first. $\endgroup$
    – Mr.Wizard
    Dec 4, 2012 at 13:35
  • $\begingroup$ @Mr.Wizard Thanks, I appreciate that. I used to give more detailed answers which would also explain the reasons behind some of the rules. A little more busy now :) $\endgroup$ Dec 4, 2012 at 13:37
  • 3
    $\begingroup$ @LeonidShifrin I was alluring to R - quite lamely as it seems. Thx for the offer though! $\endgroup$
    – Yves Klett
    Dec 4, 2012 at 13:51

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.