1

Update: I'm realizing now my question should be: how do I pass an argument by REFERENCE? I have a clue here: 'pass parameter by reference' in Ruby? but I don't nkow if it's even possible. Might be worth closing this question in fact.

In reference to this previous question: How to reverse a linked list in Ruby

I'm a bit confused why the list isn't reversed in place.

So my expectation would be that: print_values(node3)

Would initially give: 12 -> 99 -> 37 -> nil

And then when I call: reverse_list(node3)

I would expect a call to print_values(node3) to give 37 -> 99 -> 12 -> nil

However, I'm instead getting 12 -> nil

To a degree this makes sense because the object referenced by node3 still has a value of 12 and has a next_node of nil, but is there a way to reverse the list completely in place in Ruby?

There seems to be something here about mutability w/r/t ruby that I'm not quite grasping. It's as though with every new addition to the memory stack/function call we get new objects? Some clarification here would be much appreciated.

I've also creatd my own method to try to get the functionality working in place:

def reverse_list(list, previous=nil)

    rest_of_list = list.next_node
    print "rest of list: "
    print_values(rest_of_list)
    list.next_node = previous
    previous = list
    print "new previous: "
    print_values(previous)  
    list = rest_of_list
    print "new list: "
    print_values(list)
    if list.nil?
        print "list now nil\n"
        list = previous
        print "updated list: "
        print_values(list)
        return list
    else
        reverse_list(list, previous)
    end
end
Community
  • 1
  • 1
Ramy
  • 20,541
  • 41
  • 103
  • 153
  • I could be misinterpreting the question, but it seems like you're a bit confused about the meaning of *in place*. Reversing a linked list in place means reversing the list purely by manipulating the `next_nodes` and without creating any new `LinkedListNode` objects. This is the approach used by the answer in the question you linked. [This](http://www.teamten.com/lawrence/writings/reverse_a_linked_list.html) is also a good non-Ruby specific overview. – mikej Jan 03 '16 at 21:06
  • I can clarify: Is it possible to change the head pointer to point to the head first node of the reversed list? – Ramy Jan 03 '16 at 21:16
  • Perhaps you would be good enough to accept the answer I provided, and then ask your question re pass by reference, rather than keep changing the question. – Mitch VanDuyn Jan 04 '16 at 00:32

2 Answers2

1

In answer to your updated question:

Yes you will have to reverse the values of the list, instead of the pointers.

To do this AFAIK you have to first build a new reversed list, and then copy the reversed values back into the original list.

I have updated the original code to be more ruby-ish (i.e. the methods are part of the list class, and the "!" suffix is used to indicate the method will modify the object (rather than just return a new value.)

<script type="text/ruby">
def print(s)
  s = s.gsub("\n", "<br/>").gsub(" ", "&nbsp;")
  Element['#output'].html = Element['#output'].html + s
end

class LinkedListNode
  attr_accessor :value, :next_node

  def initialize(value, next_node=nil)
    @value = value
    @next_node = next_node
  end
 
  def reverse_list(reversed=nil)
    if next_node
      next_node.reverse_list(LinkedListNode.new(value, reversed))
    else
      LinkedListNode.new(value, reversed)
    end
  end
  
  def reverse_list!(list=self, reversed_list = reverse_list)
    self.value = reversed_list.value
    if next_node
      next_node.reverse_list!(list, reversed_list.next_node)
    else
      list
    end
  end
  
  def print_values
    print "[#{object_id}]#{value} --> "
    if next_node.nil?
      print "nil\n"
    else
      next_node.print_values
    end
  end
 
end

node1 = LinkedListNode.new(37)
node2 = LinkedListNode.new(99, node1)
node3 = LinkedListNode.new(12, node2)
print "original list:     "
node3.print_values
print "reversed list:     "
node3.reverse_list.print_values
print "reversed in place: "
node3.reverse_list!
node3.print_values

</script>


<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://rawgit.com/reactrb/reactrb-express/master/reactrb-express.js"></script>
<div id="output" style="font-family: courier"></div>
Mitch VanDuyn
  • 2,838
  • 1
  • 22
  • 29
  • I updated my question for clarity. It's not that I think the code doesn't work. I'd like to know if there's a way to update the original head pointer to point to the first node of the newly reversed list. – Ramy Jan 03 '16 at 21:30
  • 1
    ah! this is great! And you're right I changed the goalposts with the last update and this does answer the original question. accepted. – Ramy Jan 04 '16 at 00:53
  • 1
    Thanks! Hope you like that inline-reactive-ruby library, runs react.rb as well! – Mitch VanDuyn Jan 04 '16 at 01:32
1

There is no pass by reference in Ruby

For all but the most basic classes such as numbers, there are methods that will modify an object in place, thus accomplishing much of the functionality of call by reference.

Mitch VanDuyn
  • 2,838
  • 1
  • 22
  • 29