I have the following code, and was wondering if someone can tell me why, after running it, the value of #left_child and #right_child are still nil.
I think I know why, but I am asking for confirmation to the community. Also, is there a way I can make this work in a way like this?
module BinaryTree
class Node
attr_accessor :left_child, :right_child
def initialize(value)
#value = value
#left_child = nil
#right_child = nil
end
def add_child(value)
if value > #value
create_child(value, #right_child)
else
create_child(value, #left_child)
end
end
private
def create_child(value, which_child)
if which_child.nil?
which_child = Node.new(value)
else
which_child.add_child(value)
end
end
end
end
node = BinaryTree::Node.new(50)
node.add_child(20)
node.left_child # => nil
node.add_child(70)
node.right_child # => nil
They are still nil because you've never assign values to them. Instead, you should change to this:
module BinaryTree
class Node
attr_accessor :left_child, :right_child
def initialize(value)
#value = value
#left_child = nil
#right_child = nil
end
def add_child(value)
if value > #value
#right_child = create_child(value, #right_child)
else
#left_child = create_child(value, #left_child)
end
end
private
def create_child(value, which_child)
if which_child.nil?
which_child = Node.new(value)
else
which_child.add_child(value)
end
which_child
end
end
end
which_child is a variable local to create_child. The value of #right_child is being copied to it when you call the method. Your code is basically the same as
right_child = nil
which_child = right_child
which_child = true
# right_child is still nil!
Variables in Ruby store pointers to objects, and Ruby passes around those pointers by value. See also:
Ruby - Parameters by reference or by value?
Is Ruby pass by reference or by value?
Related
I'm having issues understanding this encapsulation. I have instance variables defined with attr_accessor. I'm trying to access them outside class. But they are always nil and returns undefined method.
NoMethodError: undefined method `has_key?' for nil:NilClass
Please help me understand.
class TrieNode
attr_reader :value, :next, :children
def initalize
#value = nil
#children = Hash.new
#next = nil
end
end
class Trie
attr_accessor :root
def initialize
#root = TrieNode.new
end
def build_trie(strs)
cur = #root
strs.each do |str|
str.chars.each do |char|
if cur.children.has_key? char
cur = cur.children[char]
next
else
new_node = TrieNode.new
cur.children[char] = new_node
cur = new_node
end
end
cur = #root
end
end
end
Yes, it is not encapsulation, it is because your object is not instantiated properly, which is caused by a typo
def initalize
#value = nil
#children = Hash.new
#next = nil
end
should be initialize not initalize
I have some issues with this code, so, I'm trying to make a linked list but with the first variable I get the next issue:
nodo.rb:34 in 'initialize': wrong number of arguments(1 for 0)
So, the Node class have the actual node and the link, and LinkedList the size and the header.
The problem comes when I try to add a new value but I receive the issue. So I dont know how to fix this problem. I will receive any help you could give me.
class Node
def intialize(data,ref = nil)
#data = data
#refe = refe
end
def get_data
return #data
end
def set_data(newdata)
#dato = newdata
end
def get_ref
return #ref
end
def set_ref(newref)
#ref = newref
end
end
class Linkedlist
def initialize
#size = 0
#header = nil
end
def add_var(value)
#aize = #size + 1
if #header == nil
#header = Node.new(value) #the issue comes here, in the moment when I try to make a new class of Node
else
nodeActual = #header
while nodeActual.get_ref != nil
nodeActual = nodeActual.get_ref
end
nodeActual.set_ref(Node.new(value))
end
end
#def print_list
#end
def get_size
return #size
end
end
list = Linkedlist.new
stop = nil
while stop != -1
a = gets.chomp
if a.to_i == -1
stop = -1
else
list.add_var(a)
end
end
#list.print_list
you have a typo in Node class, rename intialize to initialize (missing i)
I am trying to have sushiable? return an instance variable set in initialise but I can't seem to get it to work. What am I doing wrong?
attr_accessor :weight, :value, :sushiable?
def initialize (weight,value, sushiable?)
#weight = weight
#value = value
#sushiable = sushiable?
end
# def sushiable?
# false
# end
Using ? is only valid for methods names, not for variables. So, the correct way would be:
attr_accessor :weight, :value, :sushiable
def initialize (weight, value, sushiable)
#weight = weight
#value = value
#sushiable = sushiable
end
def sushiable?
sushiable
end
I got a question for implementation methods like get_item(index), or find(value) with used classes.
class SinglyLinkedListItem
attr_accessor :object, :next
attr_reader :list
def initialize(object, list)
#object = object
#list = list
end
end
class SinglyLinkedList
attr_reader :length
def initialize
#length = 0
#head = nil
#tail = nil
end
got some methods like
def each
if #length > 0
item = #head
begin
yield item.object
item = item.next
end until item.nil?
end
end
I tried with many ways, but im still getting this error:
NoMethodError: undefined method `object' for nil:NilClass
You have to define method #object on nil:
def nil.object; self end
The error will not appear that way.
I had this problem before with attr_accessor.
Try replacing the
##
with
self.#
And you might want to check the item class as a precaution.
yield item.object unless item.nil?
For Ex:
def each
if self.length > 0
item = self.head
begin
yield item.object unless item.nil? #Check if item turned nil or not
item = item.next
end until item.nil?
end
end
And there might be some more handling that you need to do, but your given data doesn't provide me enough information.
I'm trying to understand this function.
What I can see is an attribute and type are passed to the opal() method.
Then type_name takes its value from type as long as type is a Symbol or String. Otherwise, the name method is called on type. I imagine the name method is similar to the class method to get the class of the type argument.
After self.class_eval I'm kind of lost but my guess is this is defining maybe a block of code to be added to the class referenced by self.
How this works I'm not sure though.
Would appreciate if someone could explain what's going on after self.class_eval << DEF.
def opal(attr, type)
self.ds "#{attr}_id"
type_name = (type.is_a?(Symbol) || type.is_a?(String)) ? type : type.name
self.class_eval <<DEF
def #{attr}
if defined?(##{attr})
##{attr}
else
##{attr} = if self.#{attr}_id
#{type_name}.get(self.#{attr}_id)
else
nil
end
end
end
def #{attr}=(value)
self.#{attr}_id = value.key
##{attr} = value
end
DEF
end
Everything between <<DEF and DEF is just a string and the #{ ... }s work on that string like any other.
class_eval will cause the interpreter to run on the string in the context of the module.
So, if you know what attr and type are then you can work out what code is being run to add methods to the class.
Lets say attr is "foo" and type is "Bazzle". The code being run would be:
def foo
if defined?(#foo)
#foo
else
#foo = if self.foo_id
Bazzle.get(self.foo_id)
else
nil
end
end
end
def foo=(value)
self.foo_id = value.key
#foo = value
end
To make it easy to understand, let's suppose the value of 'attr' is 'foo', here's what it looks like now:
self.class_eval <<DEF
def foo
if defined?(#foo) # Return the value of attr if it's defined
#foo
else
#foo = if self.foo_id
#{type_name}.get(self.foo_id)
else
nil
end
end
end
def foo=(value) # Define setter
self.foo_id = value.key
#foo = value
end
DEF
So it's just defining some getter and setter methods for #foo, and evaluating it at the class level.