Message Boards Message Boards

5 Replies
7 Total Likes
View groups...
Share this post:

Getting the usage string for a symbol given by name

Posted 11 years ago
Given the string "Plot", you could do


to get the usage string for Plot. But then there are symbols with pre-defined values such as LightRed which evaluates to RGBColor[1, 0.85, 0.85] immediately. You can get around that by Clear'ing LightRed temporarily (already a bit hackish). But you still run into problems with symbols that get a value regardless (after being Clear'ed), e.g. $Line.
So to get from "$Line" to its usage string, I basically do this now:

In[1]:= getSymbol[name_, k_] := If[k <= 1, Symbol[name], getSymbol[name, k - 1]]
In[2]:= getSymbolUsage[symbol_] := symbol::usage
In[3]:= SetAttributes[getSymbolUsage, HoldFirst]
In[4]:= getUsage[name_] := Block[{$IterationLimit = 21}, Quiet[ReleaseHold[getSymbolUsage /@ getSymbol[name, 10]], {$IterationLimit::itlim}]]
In[5]:= getUsage["$Line"]
Out[5]= "$Line is a global variable that specifies the number of the current input line. "

So there is a function getSymbol that does some artificial iteration (because $IterationLimit must be at least 20) in order to stop at the exact point where Symbol has been applied on the string but the own value of the symbol has not been applied yet, so it will return the symbol in a Hold. I can then map a Hold-ing function getSymbolUsage on the Hold expression (containing the symbol) to get the actual usage string (after releasing Hold again).

Is there an easier way to do this? I would assume there is at least some internal functionality to deal with cases like this, but something official would be nicer, of course. I need this to compile a list of all Names["*"] and their usage strings.

In a broader sense, I sometimes find myself wanting to "do one application of a function without further evaluating its result" (like Symbol in the specific case). Is this $IterationLimit trick the canonical workaround for that, or am I missing something fundamental?
POSTED BY: Jan Poeschko
5 Replies
but why not just do:
In[66]:= getUsage[symbol_String] := ToExpression[symbol <> "::usage"]
In[67]:= getUsage["$Line"]
Out[67]= "$Line is a global variable that specifies the number of the current input line. "
POSTED BY: Arnoud Buzing
and this is certainly the most beautiful solution to the specific question. Although, I still need to solve the general problem ("do one iteration of function application").
POSTED BY: Jan Poeschko
Posted 11 years ago
Here are a couple of options:
In[255]:= ToExpression["$Line", InputForm, Function[x, MessageName[x, "usage"], {HoldFirst}]]
Out[255]= "$Line is a global variable that specifies the number of the current input line. "
In[260]:= MessageName[#, "usage"] &[ToExpression["$Line", InputForm, Unevaluated]]
Out[260]= "$Line is a global variable that specifies the number of the current input line. "

POSTED BY: Oyvind Tafjord
Thanks, Oyvind! I did not think of ToExpression["$Line", InputForm, Unevaluated] -- love it.

Any suggestions for the general problem of doing one iteration (applying a function) and then stopping (putting the result in a Hold)? 
POSTED BY: Jan Poeschko
Well, an absolutely terrible way of solving the specific question is to use Trace:
In[72]:= getUsage2[s_String]:=Extract[Trace[Symbol[s]],2,Apply[Function[symb,MessageName[symb,"usage"],{HoldFirst}],#]&]
In[73]:= getUsage2["Plot"]
Out[73]= Plot[f,{x,Subscript[x, min],Subscript[x, max]}] generates a plot of f as a function of x from Subscript[x, min] to Subscript[x, max].
Plot[{Subscript[f, 1],Subscript[f, 2],\[Ellipsis]},{x,Subscript[x, min],Subscript[x, max]}] plots several functions Subscript[f, i].
In[74]:= getUsage2["$Line"]
Out[74]= $Line is a global variable that specifies the number of the current input line.

That's surely rife with corner cases, but the idea is that the first thing that's going to be evaluated during Symbol[ s ] is, well, Symbol[ s ], and Trace is going to return that result wrapped with Hold to avoid further evaluation. Of course, in the case of $Line, it continues to evaluate further, and if that further evaluation had side effects, you'd see the side effects. E.g.
In[81]:= a::usage="a is a symbol with a usage message";
a:=Print["Hello World!"];
In[83]:= getUsage2["a"]
During evaluation of In[83]:= Hello World!
Out[83]= a is a symbol with a usage message

In particular, this doesn't stop evaluating; it just lets you see what the expression was at the intermediate step. So I wouldn't recommend this approach in general, but it probably does generalize to the problem of seeing the result after one iteration, at least for off-line investigation.
POSTED BY: Jeremy Michelson
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
or Discard

Group Abstract Group Abstract