# Converting expression into string without evaluating it

How can one convert a Mathematica expression into a string without the expression being evaluated first? I tried using Hold, but it returns Hold[expr], instead of expr. Is there any way to get just the expression?

For example, I have a variable var = 5, and I need to assign the name of var to another variable, so that var2 = "var". How can I do this?

My actual use case is this:

I am trying to synchronize my mathematica variables with certain fields in an external database. Every time the external database is updated, I call on a function that is supposed to update my corresponding Mathematica variables. It takes in a list of mappings like {var1 -> "field1", var2 -> "field2"}, and its role is to access the external database, look up the value in "field1", and assign it to var1, then look up the value in "field2" and assign it to var2. The number of variables in the mapping (and their names) can be arbitrary.

The problem is that I need those var1 and var2 variables to be passed as variable names, not values, so that I can assign them inside the function. I do the assignment using

 Do[ i[[1]]->i[[2]]/.remoteData, {i,mappings} ] 

where remoteData = {"field1"->"value of field 1", "field2" -> "value of field 2"}. I need i[[1]] to stand for var1, not for its value. I tried setting the attribute SetAttributes[fn,HoldAll] but that didn't help.

The result that I am looking for is var1 = "value of field 1", var 2 = "value of field 2".

-
This is a duplicate I believe so I shall not post an answer. I think the simplest is MakeBoxes[var], but how you get var into that expression will be the issue. What is your actual use for this? –  Mr.Wizard Feb 9 at 16:42
What I mean is, you could of course just type in "var" so presumably you are working with some list of Symbol names or the like that you need to manipulate. Please describe the situation and your goals. –  Mr.Wizard Feb 9 at 16:45
Other alternatives include SymbolName @ Unevaluated[var] and ToString @ HoldForm[var] and each of these may be useful, again depending on your actual needs. I await your clarification. –  Mr.Wizard Feb 9 at 16:49
The key is Unevaluated. As MrW said, you can use something similar to ToString@Unevaluated[1+1]. It gives "1 + 1". Juggling unevaluated expressions is likely to get complicated though ... –  Szabolcs Feb 9 at 16:56
This is not an answer, but it's related and might be interesting. @Mr.Wizard I believe I could answer this is it's reopened ... –  Szabolcs Feb 9 at 17:16

If I understand the question correctly, this is what you are asking:

You have a table with headings in a text file. You want to read this table in and assign the columns to certain variables. You want to do this based on some mapping of the form "heading-name" -> variable that your code takes as input.

First of all, personally I feel uneasy about programmatically manipulating variable names, but I know that many people disagree with this ... If I were doing this myself, I'd choose to retrieve the columns based on some name stored as a string (e.g. using replacement rules), but not actually assign to variables corresponding to this name. There are fewer things that can go wrong, e.g. variables won't accidentally get overwritten.

That said, here's how to do what you asked for. Here's a example table stored in a string. You'll have a file instead.

table =
"one  two  three
1    2    3
4    5    6
7    8    9"


These are the mappings. Variable names are stored as strings to prevent evaluation:

mapping = {"var1" -> "one", "var2" -> "two", "var3" -> "three"}


We'll use this function to assign to variables:

set[s_String, v_] := ToExpression[s, InputForm, Function[x, x = v, {HoldFirst}]]


The code:

data = ImportString[table, "Table"]
values = mapping[[All, 2]] /. (First[#] -> Rest[#] &) /@ Transpose[data]


Now the variables are set to the values read from the table, based on the mappings we defined:

var1

(* ==> {1,4,7} *)


The key was using the third argument to ToExpression, which allows manipulating an expression converted from a string before it gets evaluated.

However, as I said at the beginning, I would stop at creating the mapping (First[#] -> Rest[#] &) /@ Transpose[data] and using it to reference columns by their names.

EDIT: Per the OP's request, here's how to do it without storing the variable names as strings. In this case we need to store the mapping inside Hold to prevent evaluating the variables.

mapping = Hold[var1 -> "one", var2 -> "two", var3 -> "three"]

ReleaseHold[Set @@@ (mapping /. (First[#] -> Rest[#] &) /@ Transpose[data])];


Slightly simpler with a different syntax for the mapping:

mapping = Hold[var1 = "one", var2 = "two", var3 = "three"];
ReleaseHold[ mapping /. (First[#] -> Rest[#] &) /@ Transpose[data] ];

-
thanks for the suggestion. I did consider passing variable names as strings to my function, but that didn't look like native Mathematica code. There must be a way to actually pass the variables themselves, but not evaluate them right away, since many built-in functions are able to do this. –  verse Feb 9 at 17:37
@user6236 The whole idea of assigning to variables progammatically based on their name makes me feel uneasy, so at this point I stopped being bothered by what looks "native" or "beautiful" ... but yes, it's possible, if you keep the mapping inside a Hold. Otherwise not. –  Szabolcs Feb 9 at 17:40
could you please clarify how one can use Hold to achieve the desired outcome? The problem I encountered was that if I put Hold around i[[1]] inside my function, it is not replaced with var1. –  verse Feb 9 at 17:44
@user6236 OK, I updated the post. Can you please choose a display name other than the auto-generated user98765-style name? I don't understand your last comment completely, so let me know if this is not what you're looking for. –  Szabolcs Feb 9 at 17:46

It looks like I should have used HoldForm instead of Hold.

Here is my current solution that does the job:

 SetAttributes[fn,HoldAll];

 

fn[mappings_]:= ReleaseHold[Apply[Set, HoldForm[mappings]/.remoteData, {2}]] 

-