Convert defined variables to rule list

I'd like to make a function that takes a list of variables and returns a corresponding rule list with the current values of the variables. E.g.

x = 1;
y = 2;
VariablesToRules[{x, y, z}]
(* {x -> 1, y -> 2, z -> z} *)


Is this even possible?

• This is a super interesting question. This post is related, because you will need to get the symbol names in order to Clear them, but it's not clear how to short-circuit the evaluation when you will be feeding a list of variable names to the function rather than just the variable name. – march Feb 6 at 20:34
• Is OwnValues /@ Unevaluated@{x, y, z} OK? – xzczd Feb 7 at 3:28

Update 2

Based on a suggestion by Somos, the following version is nicer. According to what the OP wants:

SetAttributes[variableToRule, {HoldAll, Listable}]
variableToRule[var_] := SymbolName@Unevaluated@var -> var


and according to my original interpretation of the problem:

SetAttributes[variableToRule, {HoldAll, Listable}]
variableToRule[var_] := Module[{val = var}, Clear@var; var -> val]


Update 1

After some comments from the OP, it seems they want instead something like

variableToRule[var_] := SymbolName@Unevaluated@var -> var


Original Post

Here's a first iteration. First define the helper function,

ClearAll@variableToRule
SetAttributes[variableToRule, HoldAll]
variableToRule[var_] := Module[{val = var}
, Clear@var
; var -> val
]


Then, the function is

ClearAll@variablesToRules
SetAttributes[variablesToRules, HoldAll]
variablesToRules[vars_List] := variableToRule /@ Unevaluated@vars


This uses the trick from this answer.

Then,

x = 1; y = 2; z = 3;
variablesToRules[{x, y, z}]
(* {x -> 1, y -> 2, z -> 3} *)

• Thanks - any way to keep the variables' values afterwards? – Chris K Feb 6 at 20:57
• @ChrisK. Your question confuses me. If you're making replacement rules, isn't the whole point that you will use them to replace the values of x and y, etc. in expressions that contain those variables? In that place, you don't want x and y set before-hand. What is it that you are trying to do here? Is this just for display purposes or something? If you keep the variables set, then you will get {1 -> 1, 2 -> 2}. – march Feb 6 at 21:02
• I think the trick from your link works: variableToRule[var_] := SymbolName[Unevaluated@var] -> var seems OK – Chris K Feb 6 at 21:02
• But then, what is the point of the replacement rule? Because that won't actually work as a replacement rule, because you have the symbol name (which is a string), instead of the symbol itself. – march Feb 6 at 21:04
• It's a bit hard to explain, but I've got an inner function that takes a list of rules as an argument, which needs to be defined in an outer function where the variables are already defined. Anyhow I think I'm sorted now. Thanks! – Chris K Feb 6 at 21:07

Pass in the names of the symbols as strings, and the rest is quite easy:

ClearAll[varsToRules];
varsToRules[s_] := With[{t = Map[Symbol, s]},
s // Apply[ClearAll];