1
$\begingroup$

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 *)
$\endgroup$
1
  • 1
    $\begingroup$ 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. $\endgroup$ Jun 4 '20 at 8:21
2
$\begingroup$

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}} *)

You can instead thread over the input

(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

enter image description here

In addition, if you do Attributes[ReplaceAll] you would see that Listable is not given as attribute of ReplaceAll

$\endgroup$
2
  • $\begingroup$ 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 *) $\endgroup$ Jun 4 '20 at 21:03
  • $\begingroup$ 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. $\endgroup$ Jun 4 '20 at 21:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.