18

This is probably a very simple question, but I couldn't find a duplicate.

As everybody knows, {x, y} + v gives {x + v, y + v}. But if I intend v to represent a vector, for example if I am going to substitute v -> {vx, vy} in the future, then the result {x + v, y + v} is meaningless.

How I can indicate to Mathematica that v is not a scalar and functions like Plus should not treat it as one? I tried setting $Assumptions = v ∈ Vectors[2] but that didn't help.

  • 1
    I suppose you don't want to Inactivate Plus because there are other computations you want to do? – march Dec 24 '15 at 03:51
  • Thanks for all the answers, everyone! I guess I should have been more forthcoming about my ultimate goal, namely getting a correct PiecewiseExpand[f[t, 0, 2]] for my Koch snowflake parametrization, because I couldn't figure out make the answers here work for it. But seeing all the different approaches inspired a solution of my own that did work out (though still not as elegant as I would like). –  Dec 25 '15 at 02:51

6 Answers6

7

You can use Inactivate

pl = Inactivate[{x, y} + v, Plus]

enter image description here

As an indication to not being "active" the plus sign is dimmed

You can still use a (partially) inactivated expression

ti = pl * 8

enter image description here

and Activate it whenever you want

Activate[ti]

enter image description here

eldo
  • 67,911
  • 5
  • 60
  • 168
5

One workaround would be ClearAttributes[Plus,Listable] (The Plus is threading because of the Listable attribute). If you need the Listable attribute in another part of your code, you would need to run SetAttributes[Plus,Listable] to put the attribute back in.

ClearAttributes[Plus,Listable];
{x, y} + v

(* v + {x, y} *)

Or, you could simply use Defer (a bit tricky to use):

Defer[{x, y} + v]

(* {x, y} + v *)

Alternatively, you could use Hold (or HoldForm) and ReleaseHold:

ReleaseHold[Hold[{x, y} + v] /. v -> {vx, vy}]

(* {vx + x, vy + y} *)
JungHwan Min
  • 4,664
  • 1
  • 22
  • 36
5

I like to wrap lists in some suitable function to block this evaluation. MatrixForm is good because it looks pretty, but an undefined function would also work.

a = MatrixForm[{x, y}] + MatrixForm[v]

Then, once you have concrete definitions for your arrays, take away the MatrixForm:

b = a /. v -> {1, 2}
b /. MatrixForm -> Identity
(* {1 + x, 2 + y} *)
John Doty
  • 13,712
  • 1
  • 22
  • 42
4

You may use Indexed to represent v as its components in the calculation.

{x, y} + (Indexed[v, #] & /@ Range[2])
(* {x + Indexed[v, {1}], y + Indexed[v, {2}]} *)

Later when v is assigned the Indexed components will become Part values of v.

v = {1, 2};
{x, y} + (Indexed[v, #] & /@ Range[2])
(* {1 + x, 2 + y} *)

As a function

f[t_] := {x, y} + (Indexed[t, #] & /@ Range[2])

Hope this helps.

Edmund
  • 42,267
  • 3
  • 51
  • 143
3

If there's a specific addition operation one wants to block, one can just apply a custom function instead, for example

{x, y} ~plus~ v
(* plus[{x, y}, v] *)

and replace it with Plus when one is ready:

{x, y} ~plus~ v /. v -> {vx, vy} /. plus -> Plus
(* {vx + x, vy + y} *)
2

Another option, which doesn't require activation/replacement-by-identity/manual-indexing/etc. is to create a custom Plus function, which only evaluates for lists:

vectorPlus[a_?ListQ,b_?ListQ]=a+b;

With it you have:

vectorPlus[x, {q,r,s}]
vectorPlus[{q,r,s}, y]
vectorPlus[{q,r,s}, y] /. y->{a,b,c}
vectorPlus[{q,r,s}, {x,y,z}]

vectorPlus[x, {q, r, s}]

vectorPlus[{q, r, s}, y]

{a + q, b + r, c + s}

{q + x, r + y, s + z}

Ruslan
  • 7,152
  • 1
  • 23
  • 52