Obtaining assigned symbols and values

*To*: mathgroup at yoda.physics.unc.edu*Subject*: Obtaining assigned symbols and values*From*: villegas*Date*: Thu, 1 Oct 92 04:47:34 CDT

Hi John, Though there is not a built-in function which automatically figures out what variables you've defined and gives a report of what they are and how they're defined, you can write a few functions that will accomplish about what you want, with fair generality. Generally, a user works in a context called "Global`", so all the user's symbols are in that context. The current context can be abbreviated by a lone grave accent ` , so unless you have changed your context purposely, it will represent the global context. Here's how to get a listing of all symbols in the global context, then: In[1]:= globals = Names["`*"] Out[1]= {args, ClearKernelHistory, context, ctx, Erase, expr, file, > fileOrpipe, Form, globals, info, Info, InfoWild, instream, > instream$, k, m, Modulo, name, PackageInfo, patt, PrintTime, > readlist, readlist$, ReadOnce, result, result$, ShowDef, str, > stream, stream$, StringReadList, SupportAges, sym, username} (You'll probably have a different list than I do; this is a result of how I've changed my start-up). If you wanted to remind yourself of what the "`*" means, you could make the "Global" explicit; the result would be the same, and we can have Mathematica verify that fact: In[2]:= Names["Global`*"] === globals Out[2]= True Mathematica creates a symbol in the symbol table of the current context anytime you use a new symbol, and this goes for symbols you just use in expressions, even when you aren't assigning values to them. For instance: In[3]:= Expand[(2 x - 5 y)^4] 4 3 2 2 3 4 Out[3]= 16 x - 160 x y + 600 x y - 1000 x y + 625 y In[4]:= ? x Global`x In[4]:= ? y Global`y I didn't assign anything to 'x' and 'y', but now they "exist", and we can see that Mathematica has put them in the context "Global`". So some of the symbols we got in the list we stored in 'globals' above might be no-value symbols. Presumably we don't care about those, so we want to extract the ones which have values as constants or as functions, for example (note that Mathematica has several different types of assignments): a = 5 f[x_] := Sin[Tan[x]] + Tan[Sin[x]] These assignments are stored in different ways, because the one for 'a' means 'a' has a value by its own self, and 'f' produces a value only when acting on something. In Mathematica, the former are called 'OwnValues', and the latter 'DownValues'. We can take a look at how the kernel has stored them: In[6]:= OwnValues[a] Out[6]= {Literal[a] :> 5} In[7]:= DownValues[f] Out[7]= {Literal[f[x_]] :> Sin[Tan[x]] + Tan[Sin[x]]} The symbol 'Literal' is there merely to prevent the left sides from evaluating as they would ordinarily; it "freezes" the left sides so we can see to what the definitions are made. If we ask for some kind of *Values for a symbol which doesn't have the type we request, then we'll get an empty list instead of one of the form { Literal[leftside] :> rightside } as we did above. In[8]:= OwnValues[x] Out[8]= {} Now we can use this fact to check to see if a symbol has been assigned some type of value. The different types of values all end in "Values", so we can generate all system names ending in that, and leave out the one that is a linear algebra function (SingularValues) rather than a function for looking up values. Then we can define a function to take a symbol and a type of value (like 'OwnValues') and give us 'True' if the symbol has at least one assignment of that type, 'False' if it doesn't. We allow the function to take the variable name as a symbol or as a string, since the 'Names' function we used above generates a list of strings like "x" instead of symbols like x (without quotes). In[1]:= $ValueTypes = ToExpression /@ Complement[Names["*Values"], {"SingularValues"}] Out[1]= {DefaultValues, DownValues, FormatValues, NValues, OwnValues, > SubValues, UpValues} In[2]:= ValueTypes = Apply[Alternatives, $ValueTypes] Out[2]= DefaultValues | DownValues | FormatValues | NValues | > OwnValues | SubValues | UpValues In[3]:= Attributes[HasValueQ] = HoldFirst Out[3]= HoldFirst In[4]:= HasValueQ[sym_Symbol, valtype:ValueTypes] := Length[ valtype[sym] ] != 0 In[7]:= HasValueQ[name_String, valtype:ValueTypes] := Length[valtype @@ ToHeldExpression[name]] != 0 The function 'HasValueQ' tests any symbol for any type of value. If we're just interested in assigments like the ones we made to 'a' and 'f' above, we can use 'HasValueQ' to get OwnValues and DownValues. Now let's get a list of all global variables and see which ones have assignments we're interested in (again, this is a different Mathematica session, so the names will be different from the example given earlier): In[24]:= globals = Names["`*"] Out[24]= {args, ClearKernelHistory, context, ctx, downvalues, Erase, > expr, file, fileOrpipe, Form, globals, HasValueQ, hh, info, Info, > InfoWild, instream, instream$, k, left, lit, m, Modulo, name, > ownvalues, PackageInfo, patt, PrintTime, PrintValue, readlist, > readlist$, ReadOnce, result, result$, right, ShowDef, str, stream, > stream$, StringReadList, SupportAges, sym, u, username, valtype, > $ValueTypes, Valuetypes, ValueTypes, WantedValuesQ} In[29]:= ownvalues = Select[globals, HasValueQ[#, OwnValues]& ] Out[29]= {downvalues, globals, ownvalues, SupportAges, $ValueTypes, > ValueTypes} In[30]:= downvalues = Select[globals, HasValueQ[#, DownValues]& ] Out[30]= {Erase, HasValueQ, info, Info, InfoWild, Modulo, PackageInfo, > PrintTime, PrintValue, ReadOnce, ShowDef, StringReadList, > WantedValuesQ} Earlier in this session I defined a function that will take the kinds of rules we saw stored: Literal[left] :> right, and display it in something like the form "left = right", without evaluating 'left' or 'right'. The 'HoldForm' prevents the evaluation, but doesn't display itself. In[20]:= PrintValue[(lit:Literal)[left_] :> right_] := StringForm["`1` -is- `2`", HoldForm[left], HoldForm[right] ] I chose " -is ", but could have chosen "=". Values can be assigned with "=" or ":=", and I don't know (tell me, someone) how to get this information out of 'DownValues' and such, though it does get displayed when you use "?? f" to print out info. You could use "--->", or whatever you like, to "equate" the left and right sides. Now you can generate the DownValues and OwnValues of symbols and use this function on them. Instead of applying this to 'ownvalues' and 'downvalues' above, which generates a lot of output (I haven't figured out how to make output look nice in complicated cases yet), I'll try it on some simpler definitions: In[33]:= {a, b, c} = {7, 2 - x, 3 + y} Out[33]= {7, 2 - x, 3 + y} In[34]:= f[x_] := Sin[Tan[x]] + Tan[Sin[x]] In[37]:= g[x_] := Integrate[1/t, {t, 1, x}] In[44]:= Apply[PrintValue, simpledown, {1}] //TableForm Out[44]//TableForm= f[x_] -is- Sin[Tan[x]] + Tan[Sin[x]] 1 g[x_] -is- Integrate[-, {t, 1, x}] t In[45]:= Apply[PrintValue, simpleown, {1}] //TableForm Out[45]//TableForm= a -is- 7 b -is- 2 - x b -is- 2 - x The general idea would be to use this on the lists we made earlier, 'ownvalues' and 'downvalues', but the output can be somewhat hard to read. I used: In[32]:= Map[PrintValue, Apply[DownValues, ToHeldExpression /@ downvalues, {1}], {2}] to get a listing of the things that have DownValues. The general ideas are there, and this technique could probably be modified to return better-looking output. Since a similar question came to me from someone else one time, I'll append most of the answer (along with a summary of the questions) to this email. Some of it is about the same as above, but I think there are some extra things in it. Robby Villegas Wolfram Research ************************************************************************ The user asked two questions: (1) How do I get some kind of listing of all the commands entered in the current session? (2) How do I get a listing of all the variables I've assigned values to (functions, constants, etc.) in the current session? ======================================================================== (1) Commands entered in the current session. Mathematica has several variables that comprise a kernel history for the current session. The familiar "%" usage to refer to previous _output_ is a shorthand for Out[n], where n is the line number. "%" is short for Out[-1], which means the immediately previous output; "%%" refers to Out[-2], etc. And "%n" is an absolute reference to Out[n], which means the result of evaluation of the nth input line. Just as output is stored, so is input, in the variable 'In'. In[-1] refers to the immediately previous input expression, and using it will cause it to be evaluated again. In[n] means evaluate the nth input statement again. If you just want to see the input statements as they were, without evaluating them over again, another variable is 'InString': InString[n] is the string which was the literal input of the user for the nth line. So to get a complete list of commands entered in the current session, in a nice format, you could use: Table[InString[n], {n, $Line - 1}] //TableForm This will display a list of all the commands entered so far, except for the Table command itself (that is why '$Line - 1' is used instead of just '$Line'). Another kernel record is MessageList, which maintains a list of the names of error messages generated by input statements. MessageList[n] is a list of the message names generate by In[n]. The names are wrapped in the symbol 'HoldForm' which "freezes" them, so they don't produce message output on the screen anymore. If you do just want a tabular display of In, for instance, and don't care about putting the input strings into a list that you can later use (i.e. you just want to look at them yourself, not have a program analyze them) you could type '?? In', and along with a short description of what 'In' is about, there would follow a list of n's for which In[n] has been assigned. (2) Variables used or assigned in the current session. For a table of variables that have been used in the current session, you could type: ? `* Notice the _context mark_ ` which is a grave accent, not an apostrophe like '. This will give you only a list of symbols in the currently active _context_, which will always be Global` unless you modify it yourself. So if you don't alter your context, this will list all variables _you_ have used. As with In and its relatives, you can get your result in a list that you can actually use as a Mathematica expression: globalnames = Names["Global`*"]; The list will be the same as with "? `* ", but 'globalnames' will contain a list like {"x", "y", "f", ...} which you could use further Mathematica commands on if you needed to. Any time you use a symbol like 'x' in Mathematica, it gets created in a symbol table, whether you assign any values to it or not. So the above won't tell you what symbols have been _assigned_, say as functions or as constants. If you want to know which ones have values associated with them, here's a little program, called 'AssignedNames', to generate the subset of global names which have had assignments made to them. It defines auxiliary functions NonEmptyQ, which simply decides if a list is empty, and TagQ, the important one which decides if an individual symbol or name has had any assignments tagged to it. $ValueTypes = ToExpression /@ Complement[Names["*Values"], {"SingularValues"}] NonEmptyQ[list_List] := Length[list] != 0 Attributes[TagQ] = HoldFirst TagQ[name_Symbol] := NonEmptyQ @ Apply[Union, Map[#[name]&, $ValueTypes]] TagQ[name_String] := Apply[TagQ, ToHeldExpression[name]] AssignedNames[] := Select[Names["`*"], TagQ] The variable $ValueTypes is a list of all the symbols like 'OwnValues', 'DownValues', and 'NValues' that store the various kinds of assignments you can make to a symbol. For instance, x = 3 - - - - - - - - - - - - -> stores an entry in OwnValues[x] f[x_] := Tanh[1/x] - - - - - - -> stores an entry in DownValues[f] N[c, n_] := - - -> stores an entry in NValues[c] NSum[1/k^2, {k, Infinity}, WorkingPrecision->n + 15, PrecisionGoal->n ] Currently its value is In[17]:= $ValueTypes = ToExpression /@ Complement[Names["*Values"], {"SingularValues"}] Out[17]= {DefaultValues, DownValues, FormatValues, NValues, OwnValues, > SubValues, UpValues} but it might well need to be updated for future versions if more or fewer types of assignments exist, or if other symbols whose names end in "Values" are added that, like 'SingularValues', do not represent value types for assignments.