# How do I avoid vector variables being treated as scalars in the course of replacements?

I often work with a mixture of symbolic and concrete values as I develop teaching materials. I introduce variables symbolically and then need to instantiate them to specific values while continuing to use the original variables. My i represents a vector {1, 0, 0} but I don't want to replace i with {1, 0, 0} everywhere, just when convenient. Thus I lit upon the idea of using replacement rules rather than definitions. But things didn't work out too well:

{a, a + b} //. {a -> 4 i, b -> {0, -2, 2}, i -> {1, 0, 0}}
(* output: {{4, 0, 0}, {{4, 0, 0}, {2, -2, -2}, {6, 2, 2}}} *)


while I wanted this result instead:

{a /. {a -> 4 i}, (a /. {a -> 4 i}) + b} //. {b -> {0, -2, 2}, i -> {1, 0, 0}}
(* output: {{4, 0, 0}, {4, -2, 2}} *)


I now understand that 4 i is treated as a constant in rewriting a + b:

{a, a + b} /. {a -> 4 i, b -> {0, -2, 2}}
(* output: {4 i, {4 i, -2 + 4 i, 2 + 4 i}} *)


I could attempt to control the substitution order by doing something like

{a, a + b} //. ({a -> 4 i, b -> {0, -2, 2}} /. i -> {1, 0, 0}) //. {i -> {1, 0, 0}}
(* output: {{4, 0, 0}, {4, -2, 2}} *)


But this is not very robust and won't work if substitutions are nested more deeply.

I can prevent premature application of the problematic rule using conditions e.g.

{a, a + b} //. {a :> 4 i /; i ∈ Vectors[v], b -> {0, -2, 2}, i -> {1, 0, 0}}


But then the rule never gets used as the RHS of the rule is never rewritten.

I don't really want to recast all the vector operators I might need following the example of this answer; this seems like overkill.
But I do already use a wrapper bv[i] which prints as UnderBar[i]. Can anyone suggest a lightweight solution? Could I make Plus, Times etc. (temporarily) un-listable?

BTW This issue is flagged in the documentation for Assuming, which does not help in this situation as Plus just goes ahead and uses its Listable attribute:

Assuming[v ∈ Vectors[2], v + {1, 2}]
(* output: {1 + v, 2 + v} *)


You can make the i replacement first for other rules:

{a, a + b} /. ({a -> 4 i, b -> {0, -2, 2}} /. i -> {1, 0, 0})

{{4, 0, 0}, {4, -2, 2}}


Or even your first way will do if you Hold on for a while :)

Hold[{a, a + b}] //. {a -> 4 i, b -> {0, -2, 2}, i -> {1, 0, 0}} // ReleaseHold

{{4, 0, 0}, {4, -2, 2}}


but here I'd choose to make second replacement instead of ReplaceRepeted:

Hold[{a, a + b}] /. {a -> 4 i, b -> {0, -2, 2}} /. i -> {1, 0, 0} // ReleaseHold

{{4, 0, 0}, {4, -2, 2}}

• yes; I think I covered that; the problem with that approach is that it is hard to predict in advance how much of such manipulations will be needed: they will need to match the depth of nesting of substitutions. Commented Nov 20, 2013 at 0:44
• @fairflow have you tried Hold approach with your more complicated examples? I must say I don't know what do you need to predict here, could you explain further?
– Kuba
Commented Nov 20, 2013 at 0:48
• Sorry, I posted my comment before you'd added to your answer and then my edit window timed out. Hold is good, don't know why I didn't think of that, probably forgot replacements work inside Holds. And I take your point about ReplaceAll instead of ReplaceRepeated but my example was artificially simplified and in general I need the repeats. Commented Nov 20, 2013 at 0:54
• @fairflow Ok :) I'm glad it works :)
– Kuba
Commented Nov 20, 2013 at 1:15

You can temporarily change the attributes of a function within Block:

Block[{
Plus = Plus,
Times = Times},
Attributes[Plus] = {};
Attributes[Times] = {};
{a, a + b} //. {a -> 4 i, b -> {0, -2, 2}, i -> {1, 0, 0}}
]


Careful what you put inside though, as that temporary override will trickle into all functions inside too.

• Nice trick, redefining Plus and Times as...themselves! So the attribute changes are shadowed and don't persist outside the Block. This might do it for me, though the Hold solution seems simpler. Commented Nov 20, 2013 at 2:08