# Using pure functions to assign a value to variable depending on whether it has been defined already

Let's say I want to assign to a variable the value $$2020$$ if it has not already been defined and do nothing if it has. In short, for a variable $$a$$, I want to achieve the functionality of If[Not[ValueQ[a]], a=2020]. Now, if the variable itself is very long, I want to avoid having to type it 2 or more times, so I tried to use pure functions. If $$a$$ has not been defined,

Clear[a]
If[Not[ValueQ[#]], #=2020] &[a];
a

(* 2020 *)


This works as expected. However, in the opposite case, it won't work since we're trying to assign e.g. $$10=2020$$,

a = 10;
If[Not[ValueQ[#]], #=2020] &[a];
a

(* Set::setraw: Cannot assign to raw object 10. *)
(* 10 *)


In theory, this does leave $a$ with the behaviour I want, so I could just suppress the error and move on, but of course I'm looking for an error-free solution. I also tried:

a = 10;
a := 2020 /; Not[ValueQ[a]];
a

(* During evaluation of In[1]:= \$RecursionLimit::reclim2: Recursion depth of 1024 exceeded during
evaluation of HoldPattern[a]:>2020/;!ValueQ[a]. *)
(* 2020 *)


I don't understand why this sets $$a=2020$$ even though the condition is not met. Also, I don't think it would work with #.

• Pure functions don't hold their arguments by default, so a evaluates before it's ever inserted into the body. You can use something like Function[var, body, HoldFirst] to prevent a from evaluating prematurely. Commented May 15, 2020 at 12:03

You say that you want to reproduce the behavior of If[Not[ValueQ[a]], a = 2020]. This will assign a value and return it if a is not assigned, or return Null if a already has a value.

I wonder if the following function would work for you then:

ClearAll[condassign]
condassign[variable_Symbol, value_: 2020] := (variable = value)
condassign[variable_?NumericQ, value_: 2020] := Null


The value itself can be given as a second argument, but if omitted it is assumed to be 2020.

Here are two examples:

a =.                            (* Clear any value in a              *)
condassign[a]                   (* Out: 2020 because a had not value *)
Print@condassign[a]             (* Out: Null now that a has a value  *)


The Print expression above is only to show the Null return value, which otherwise would not appear explicitly.

• Thanks, that works well enough. I wonder how to generalise it though. For example, if I have a list b={1,2,3} defined somewhere else in my code, then condassign[b] is not going to work. I would have to add condassign[variable_?ListQ, value_: 2020] := Null and similarly for other types of data. Is there a way to do it in one line, e.g. something to the effect of AnyQ? I was thinking about using Names["Global*"] to get a full list of defined symbols, but I don't know what the correct syntax would be after variable_?... . Commented May 17, 2020 at 20:51
• @dzejkob Truthfully, I worry that you may be making your life harder than you need. I have never encountered the need to do what you ask, so I wonder: perhaps one could that a completely different approach? Why do you need this functionality? What problem are you trying to solve with it? Maybe there's another way around it. Commented May 17, 2020 at 21:05
• You are right, this is definitely not a critical issue. I have a module which checks if there exists a global list of replacements, then creates it/updates the existing one with new rules (different input to module may lead to new rules). These replacements are then used on a different quantity which is the final output. This runs in a Do loop, so list is employed and updated every time. If[Not[ValueQ[a]], a = {}] works fine, I guess my attempt to rewrite it as a pure function was just an exercise for the sake of it - I feel that I'm not comfortable with pure functions as a beginner... Commented May 17, 2020 at 21:34
• @dzejkob If I understand your comment here, you don't need to write a version of the function for every type of head. Just condassign[v_Symbol,val_:2020]:=(v=val);condassign[v_,val_]:=Null will evaluate to Null anytime v isn't a symbol. Commented May 18, 2020 at 19:06
Clear[a]
If[Head[a] === Symbol, a = 2020]
a                                       (* 2020 *)

a=10;
If[Head[a] === Symbol, a = 2020]
a                                        (* 10 *)
`