# How to delay this evaluation

I am trying to create two sets, then merge them (they have one common element) and then take the total of the new set.

Let's call them set1 and set2 while their union is called set

set1[t_,gh_,ga_]:=If[gh==0,Reap[For[i=0,i<=10,i++,Sow[fn[0,i,t,gh,ga]]]][[2,1]],{}];
set2[t_,gh_,ga_]:=If[ga==0,Reap[For[i=0,i<=10,i++,Sow[fn[i,0,t,gh,ga]]]][[2,1]],{}];


and

set[t_, gh_, ga_] :=
Union[set1[t, gh, ga], set2[t, gh, ga]];


I call them by setting t=gh=ga=0 and I get this:

set1[0,0,0]


{fn[0,0,0,0,0],fn[0,1,0,0,0],fn[0,2,0,0,0],fn[0,3,0,0,0],fn[0,4,0,0,0],fn[0,5,0,0,0],fn[0,6,0,0,0],fn[0,7,0,0,0],fn[0,8,0,0,0],fn[0,9,0,0,0],fn[0,10,0,0,0]}

set2[0,0,0]


{fn[0,0,0,0,0],fn[1,0,0,0,0],fn[2,0,0,0,0],fn[3,0,0,0,0],fn[4,0,0,0,0],fn[5,0,0,0,0],fn[6,0,0,0,0],fn[7,0,0,0,0],fn[8,0,0,0,0],fn[9,0,0,0,0],fn[10,0,0,0,0]}

and finally

set[0,0,0]


{fn[0,0,0,0,0],fn[0,1,0,0,0],fn[0,2,0,0,0],fn[0,3,0,0,0],fn[0,4,0,0,0],fn[0,5,0,0,0],fn[0,6,0,0,0],fn[0,7,0,0,0],fn[0,8,0,0,0],fn[0,9,0,0,0],fn[0,10,0,0,0],fn[1,0,0,0,0],fn[2,0,0,0,0],fn[3,0,0,0,0],fn[4,0,0,0,0],fn[5,0,0,0,0],fn[6,0,0,0,0],fn[7,0,0,0,0],fn[8,0,0,0,0],fn[9,0,0,0,0],fn[10,0,0,0,0]}

and then i simply ask for set[0,0,0]//Total.

Here is the thing. When I feed my program with some initial values everything works fine, unless the initial values are such that fn[1,0,0,0,0] is equal to fn[0,1,0,0,0] and so on, for example suppose that they are both equao to 0.2

since two sets (set1,set2) are equal after evaluation for example:

set1 = {0.20, 0.30, 0.40}
set2 = {0.20, 0.30, 0.40}


when I ask for their union I get set = {0.20, 0.30, 0.40} and later on I get half the total I was supposed to get: set[0,0,0]//Total = 0.90 while I was expecting 1.80

So basically I need to form set before fn is evaluated. It is crucial to define fn though before those sets. I tried hold, Unevaluated, Cell [Evaluatable->False] and other functions/properties but none workded. Any idea?

• What about starting the iterator i of set2 at 1 rather than 0, and then using Join instead of Union?
– user31159
Nov 8 '16 at 15:26
• You may be interested in defining set1 as follows: set1[t_, 0, ga_] := fn[0, #, t, 0, ga] & /@ Range[0, 10]; set1[t_, gh_, ga_] := {}; (and similarly for set2).
– user31159
Nov 8 '16 at 15:30
• @xavier thanks for replying. Your first suggestion is my initial approach for a workaround, if nothing more elegant could come in mind. Your second is really clever, though I need to define set1,set2 in a way where gh,ga get actual values in a future stage. What I implemented is set1[t_,gh_,ga_]:=If[gh==0,Reap[For[i=0,i<=10,i++,Sow[fn[0,i,t,gh,ga]]]][[2,1]],{}]; set2[t_,gh_,ga_]:=If[ga==0,Reap[For[i=0,i<=10,i++,Sow[fn[i,0,t,gh,ga]]]][[2,1]],{}]; NoGoalSet[t_,gh_,ga_]:=Delete[Join[NoGoalHomeSet[t,gh,ga],NoGoalAwaySet[t,gh,ga]],1];  Nov 9 '16 at 8:50
• @xavier (cont) in order to delete the only duplicate value (fn[0, 0, , , ,]) before evaluating and Deleteduplicates worked the very same way as Union, so I just \ used Delete by deleting the 1 st element of my list (0, 0) which is basically what you suggested. Nov 9 '16 at 8:53

If the problem is that you already defined the function called fn while you are executing your code a simple solution is to execute it inside a Block redefining fn locally:

fn[a_, b_, c_, d_, e_] := a + b + c + d + e;

Block[{fn},
Union[set1[1, 0, 0], set2[1, 0, 0]] // Total
]
(* Out[1] = 131 *)

Union[set1[1, 0, 0], set2[1, 0, 0]] // Total
(* Out[2] = 66 *)


where I arbitrarily defined a fn function to show that this works

• it just works, thanks. I was not aware of Block function usage. Good to be taught something new. It is my understanding that it actually gives prioritization in creating the set (defined by Union) and then evaluates it using fn to get Total, correct? Nov 9 '16 at 11:06
• @TomZinger it simply redefined locally fn. In this case undefining it locally. This means that set1 and set2 evaluate as you shown in your original post, without fn evaluating to actual numbers, and you can count the number of different fn[...] objects. I do agree with xavier that using Join would make more sense for this kind of counting anyway, and directly avoids the problem that I solved with Block
– glS
Nov 9 '16 at 12:11