3

I am new to Julia and I am trying to migrate from existing code in Mathematica. I am trying to do: with an array of vectors, subtract a constant vector from it. Here is what I want:

a=[[1, 2], [1, 3]]

println(a)

b=a.-[1,1]

println(b)

I want b=[[0,1],[0,2]] but it gives me error about dimension mismatch. I am a bit at a loss regarding the difference between "a list of vectors" and "a matrix" in Julia. I am not sure what is the right way to do these two different things.

I then tried broadcasting but it did not work either

a=([1, 2], [1, 3])

println(a)

b=broadcast(-,[1,1],a)

println(b)

Finally, I tried

a=([1, 2], [1, 3])

println(a)

b=a.-([1,1],)

println(b)

and it worked.

My questions: Why don't the first two work? Is this a hack walkaround or should I be using this in the future?

wooohooo
  • 576
  • 1
  • 4
  • 15

2 Answers2

2

You need to use Ref to avoid vectorization on the second argument of your difference:

julia> a .- Ref([1,1])
2-element Vector{Vector{Int64}}:
 [0, 1]
 [0, 2]

Without that you were iterating over elements of a as well as elements of [1, 1] which ended in calculating an unvectorized difference between a vector and a scalar so it did not work.

Przemyslaw Szufel
  • 40,002
  • 3
  • 32
  • 62
  • Or wrap it in a tuple. Or array. Though that last one is slower. – DNF Jun 18 '22 at 19:56
  • With wrapping on tuple or array it would work as long as he uses `+` and `-` which are defined for vectors. However, when he decides to multiply or divide - it would not work as those are not defined for vectors. (@DNF you of course know it but this is a comment for other people reading this and this is an important difference compared to how numpy works) – Przemyslaw Szufel Jun 18 '22 at 20:13
0

An alternative way:

julia> broadcast(.-, a, [1, 1])
2-element Vector{Vector{Int64}}:
 [0, 1]
 [0, 2]

In more recent Julia versions, "dotted operators" can be used as stand-alone values of a wrapper type:

julia> .-
Base.Broadcast.BroadcastFunction(-)

which you can then broadcast.

phipsgabler
  • 20,535
  • 4
  • 40
  • 60