# ReplaceAll with pattern matching not working with list of lists

Abstract This is just a learning exercise for me. I am trying to create a function that will take a list of vectors, multiply them by a constant if constant is given, and then add all vectors. If we have no constants then the list looks like this: {list1, list2,...}. However if we want to scale one or more vectors the list would look like this: {{c1,list}, {c2,list}}. I can get it to work with one list whether it has a constant or not but not for a list of lists.

u = {1, -2}; v = {2, -5}; c1 = 4; c2 = -3;
vec1 = {u, c1}; vec2 = {c2, v};
ReplaceAll[{vec1, vec2}, {x_List, c_} -> c  x] (* gives wrong values *)
vec1 /. {x_List, c_} -> c*x (* this works but not if x_List and c_ reordered *)
{c1*u, c2*v} (* this is the value I am seeking *)

• You can use the pattern  {x_List, c_?NumericQ} :> c x to prevent ReplaceAll from matching c to vec2. Or even {x_List, c : Except[_List]} :> c x Also, it's better to use RuleDelayed (:>) for these kinds of replacements. The normal rule -> will not work correctly if x has a value already. – Sjoerd Smit Jun 4 '20 at 8:21

When you did

ReplaceAll[{vec1,vec2}, {x_List, c_} :> c x ]
(* {{-3, 6}, {8, -20}} *)


Then it took x=vec1 and c=vec2 which is not what you want. So it did vec1 vec2 which is

vec1*vec2
(* {{-3,6},{8,-20}} *)


(ReplaceAll[#, {x_List, c_} :> c x] &) /@ {vec1, vec2}
(*  {{4, -8}, {-3, {2, -5}}}  *)


One way to find this out, is to actually insert Print statements, on the right side, like this

ReplaceAll[{vec1, vec2}, {x_List, c_} :> (Print["x=", x, " c=", c]; c x)]


The print does not affect the replacement, but useful to see what is being replaced. Then you would see the following In addition, if you do Attributes[ReplaceAll] you would see that Listable is not given as attribute of ReplaceAll

• thank you so much it worked. but as I add a Apply[Plus[... to complete my function it works when not named but does not work when called by name (vectorScalerPlus[vecs]). c1 = 1; c2 = 2; c3 = 3; u = {1, 1, 1}; v = {1, 1, 1}; w = {1, 1, 1}; vecs = {{c1, u}, v, {c3, w}} Plus[c1 u, v, c3 w] (* seeking this value *) Apply[Plus, (Replace[#, {c_, x_List} :> c x] &) /@ vecs, {0}](* this works *) vectorScalerPlus := Apply[Plus, (Replace[#, {c_, x_List} :> c x] &) /@ vecs, {0}]; vectorScalerPlus[vecs](* does not work in classical function call *) – Jules Manson Jun 4 '20 at 21:03
• I believe I may have inadvertantly typed a few hidden characters spoiling my function because when I tried to line up Plus[c1 u, v, c3 w] (* seeking this value *)  the comment insisted on dropping down to the next line even though it was a short line of characters. I also noticed large parenthesis forming at the Apply[... line of code and noticed a box entity I didn't mean to type. To fix these I reordered and retyped fresh line with comment and retyped offending areas of code but it is still buggy. Im not sure how to fix this. – Jules Manson Jun 4 '20 at 21:15