3

I started learning how to program in Julia, and I'm making a pretty simple code, but it's not working as I wish, and I'm lost because I can't find where's the error.

Basically, I have a vector like this one: (1,0,0,1,1) and I made two functions that will change the entries of the vector.

The first function needs to change every entry of the vector for 1.

The second function needs to change every entry as follows: if the entry is 1, then change it for 0, and vice versa.

I have the next code:

function vectorMethodOne(vector1)
    for i = 1:length(vector1)
        if vector1[i] == 0
           vector1[i] = 1
        end
    end
    return vector1
end

function vectorMethodTwo(vector1)
    for i = 1:length(vector1)
        if vector1[i] == 0
           vector1[i] = 1
        elseif vector1[i] == 1
           vector1[i] = 0
        end
    end
    return vector1
end

The problem happens when I run the code like this:

vectorEx = rand(0:1, 5)
println("Original Vector:")
println(string(vectorEx))
println("Vector using method 1:")
vectorM1 = vectorMethodOne(vectorEx)
println(string(vectorM1))
println("Vector using method 2:")
vectorM2 = vectorMethodTwo(vectorEx)
println(string(vectorM2))

The output looks like this:

> Original Vector:
> [1,0,0,1,1]
> Vector using method 1:
> [1,1,1,1,1]
> Vector using method 2:
> [0,0,0,0,0]

But I want that the output looks like this:

> Original Vector:
> [1,0,0,1,1]
> Vector using method 1:
> [1,1,1,1,1]
> Vector using method 2:
> [0,1,1,0,0]

If I only run the vectorMethodTwo, it works like I want, like this:

vectorEx = rand(0:1, 5)
println("Original Vector:")
println(string(vectorEx))
println("Vector using method 2:")
vectorM2 = vectorMethodTwo(vectorEx)
println(string(vectorM2))

And the output looks like this:

> Original Vector:
> [1,0,0,1,1]
> Vector using method 2:
> [0,1,1,0,0]

But I want that every function run over the original vector (1,0,0,1,1) but the vectorMethodTwo is running over the modified vector (1,1,1,1,1) and I can't understand where's the error in my code.

NHDaly
  • 7,390
  • 4
  • 40
  • 45
DkRckr12
  • 183
  • 1
  • 1
  • 3

1 Answers1

4

Let's look at your output:

> Original Vector:
> [1,0,0,1,1]
> Vector using method 1:
> [1,1,1,1,1]
> Vector using method 2:
> [0,0,0,0,0]

Odd. Method 2 looks like method 1 flipped. Let's check:

println(vectorMethodTwo([1,1,1,1,1]))

> [0,0,0,0,0]

Very suspicious! Why could this be happening? Please think about this before moving to the next section.


Your "functions" are mutating the vector. When you do this in vectorMethodOne,

vector1[i] = 1

, you are changing the contents of vector1 that was passed in. That vector1 refers to the same memory as vectorEx.

Do not write code that mutates your inputs (unless you name the function accordingly). Either create a copy of your vector before mutating it, or try a list comprehension:

function vectorMethodOne(vector1)
    return [x == 0 ? 1 : x for x in vector1]
end

function vectorMethodTwo(vector1)
    return [x == 0 ? 1 : x == 1 ? 0 : x for x in vector1]
end

These do not modify the contents of the input vector1 in any way.

Mateen Ulhaq
  • 24,552
  • 19
  • 101
  • 135
  • Thanks a lot for your answer. Actually, I realized what you say, I try to make a copy of the vector, but I think I wasn't doing it correctly because the functions were still mutating the vector. May I show you my attempt to solution this, so you can tell me what I was doing wrong? – DkRckr12 Jan 08 '18 at 07:29
  • Instead of doing the somewhat complicated list comprehensions (for beginners), you could also do a `copy()` of the vector of the beginning of the function to make sure you're not mutating it. `fun_vector=copy(vector1)` and then modify `fun_vector` to your liking. – niczky12 Jan 08 '18 at 15:44
  • You can also use a construct such as `ifelse`, which can speed up your code by avoiding the `if` branch. For example: `ifelse.(iszero.(v), 1, v)` is equivalent to `vectorMethodOne`. Edit: Or, to avoid type-instabilities: `ifelse.(iszero.(v), one(eltype(v)), v)`. – DNF Jan 09 '18 at 09:35
  • Just dropping this by, but if you intend to use a mutating function in the future @frl93 , it's better to follow [the naming conventions](https://stackoverflow.com/a/45397024/2874779), _eg_ `vectorMethodOne!` instead of `vectorMethodOne`, indicating it mutates its input. – catastrophic-failure Jan 16 '18 at 00:32