Styx_
Styx_

Reputation: 135

Unexpected return value in ruby

def gen_path_locations(start, destination)
    initial_dest = destination
    last_dest = destination
    path_locations = []
    loop do
        last_dest[0] -= 1 if initial_dest[0] > start[0]
        last_dest[0] += 1 if initial_dest[0] < start[0]
        last_dest[1] -= 1 if initial_dest[1] > start[0]
        last_dest[1] += 1 if initial_dest[1] < start[0]
        break if last_dest == start
        path_locations << last_dest
        puts last_dest.inspect
    end
    path_locations
end

gen_path_locations([5, 5], [9, 9]) returns [[5, 5], [5, 5], [5, 5]]

It adds the starting location to my path_locations instead of the current iteration of last_dest. Of course, if I change the push over to this:

path_locations << [last_dest[0], last_dest[1]]

It returns the expected values. What am I missing?

Upvotes: 0

Views: 74

Answers (1)

Amadan
Amadan

Reputation: 198324

What am I missing?

A .clone:

path_locations << last_dest.clone

Otherwise, you keep adding the same object whose contents you keep changing; in the end, you will still have the same object three times, whose contents are whatever you changed it to last.

Here's an example to illustrate:

a = ["foo", "bar"]
b = [a, a, a]
# => [["foo", "bar"], ["foo", "bar"], ["foo", "bar"]]
a[1] = "quux"
b
# => [["foo", "quux"], ["foo", "quux"], ["foo", "quux"]]

You can see what is happening here. The tool is not for Ruby, but happily the example works in Python as well.

EDIT: Actually, here is the link to visualisation of your code, rewritten into Python - you can step through and see exactly what is happening. Then replace the append line with path_locations.append([last_dest[0], last_dest[1]]), which is exactly what you did (and exactly what Ruby's clone does more succintly), and see how it changes the program.

Upvotes: 1

Related Questions