3

I have a little problem with this exercise, can you help me? I tried to edit a script, but for each time that I create new instance the last element overwrites the Others (i.e. )

The class must provide a functionality for the combination of consequent blocks: i.e. it must be able to inherit from the previous block the instructions that have not been explicitly defined for the current block.

blocks = [] 

blocks << Block.new({ X:0, Y:100, Z:20}) # p blocks:({ X:0, Y:100, Z:20}) 

blocks << Block.new({X:100}, blocks[-1]) #p blocks:({ X:100, Y:100, Z:20},{ X:100, Y:100, Z:20})

blocks << Block.new({Y:0}, blocks[-1]) #p blocks:({ X:100, Y:0, Z:20},{ X:100, Y:0, Z:20},{ X:100, Y:0, Z:20})

My code with problems is:

#!/usr/bin/env ruby

    class Block


      $instance_2 = true
      $instance_3 = true


      attr_reader :out


      def initialize(out, previous = nil )

        @out = update(out, previous)
      end # end initialize


      def update(actual, previous)
        puts "IN UPDATE: box is: #{previous}"
        box = previous
        if box != nil      
          puts "IF: changing is: #{actual}"
          actual.each do |key, value|
            box[key] = value               
          end  
           box  
        else
          puts "ELSE"
             actual   
        end # end if 
      end # end update

      def inspect
        @out
      end



    end # end Block

    blocks = []
    puts "\n#----------------------1 INSTANCE----------------------#" 
    blocks << Block.new({G: "00", X: 100, Y:100, Z: 100})
    puts "\n#----------------------blocks element----------------------#" 
    p blocks
    puts "last block is: #{blocks[-1].out}"

    puts "\n#----------------------2 INSTANCE----------------------#"  if $instance_2
    blocks << Block.new({G: "01"}, blocks[-1].out) if $instance_2 
    puts "\n#----------------------blocks element----------------------#"if $instance_2 
    p blocks if $instance_2
    puts "last block is: #{blocks[-1].out}"


    puts "\n#----------------------3 INSTANCE----------------------#" if $instance_3
    blocks << Block.new({G: "02"}, blocks[-1].out) if $instance_3 
    puts "\n#----------------------blocks element----------------------#" if $instance_3
    p blocks if $instance_3
    puts "last block is: #{blocks[-1].out}"

    puts "\n#----------------------4 INSTANCE----------------------#" if $instance_3
    blocks << Block.new({G: "03"}, blocks[-1].out) if $instance_3 
    puts "\n#----------------------blocks element----------------------#" if $instance_3
    p blocks if $instance_3
    puts "last block is: #{blocks[-1].out}"
5
  • Mh... It seems that someone is making some exercise for Manufacturing Automation, am I right? For who is reading, the Block class is a G-code statement. Commented Feb 10, 2018 at 16:05
  • Hi Matteo, is a exercise for a course of 3d printer, where we have to implement the gcode. Have you any idea to solve my problem? Commented Feb 10, 2018 at 16:13
  • Can you please explain better which is the problem with your code and what have you tried? it is not clear in your question. Commented Feb 10, 2018 at 16:17
  • i edited the question, this is my trial, but for each instance that i create the last value of hash ovewrite all the previous element, try it if you have a time. Thank you very much friend Commented Feb 10, 2018 at 16:28
  • Ciao Luca, I have added to my answer a sectionthat explains which is the issue with your code... Commented Feb 10, 2018 at 16:42

1 Answer 1

2

The question is not exactly clear, but if I understand it correctly it is possible to provide a class that may or not accept a previous Block. What do you think of something like that?

#!/usr/bin/env ruby

class Block < Hash

  def initialize(h, b=nil)
    [:x, :y, :z].each do |s|
      # We start by trying to assign the coordinate that is in the 
      # input hash
      if h[s]
        self[s] = h[s]
      else
      # If the coordinate is not in h, we check for it in b, but we have to
      # remember that if the block that we are providing in b does not have
      # the method :[] or the coordinate is nil we may raise an exception
        begin
          self[s] = b[s]
          raise if not self[s]
        rescue
          raise(Exception, "Cannot initialize block.")   
        end  
      end
    end 
  end

  def inspect
    "block:(x: #{self[:x]}, y: #{self[:y]}, z: #{self[:z]}"
  end
end

# Let's try it!
blocks = [] 
blocks << Block.new({ x:0, y:100, z:20}) 
puts blocks
puts
blocks << Block.new({x:100}, blocks[-1]) 
puts blocks
puts
blocks << Block.new({y:0}, blocks[-1])
puts blocks
puts

With respect to your code

Let's consider only the update method:

def update(actual, previous)
    puts "IN UPDATE: box is: #{previous}"
    box = previous                 # ! ! ! ! ! ! ! ! WHOOPS!
    if box != nil      
      puts "IF: changing is: #{actual}"
      actual.each do |key, value|
        box[key] = value               
      end  
       box  
    else
      puts "ELSE"
         actual   
    end # end if 
  end # end update

the "whoops" line is what is creating you the issue. With that line you are giving the reference to previous (your object variable actually contains a reference) to the box variable. What you are actually doing, when you perform some action on box, is modifying what is pointed by both variable.

You can test what I'm saying immediately. Try to modify that line in this way:

box = previous.clone if previous

(nil does not have a method #clone that the rationale behind the if). If you run it again you will get a list of blocks that have not being modified. This is not an efficient code tough, and you should really rethink the update method code.

Sign up to request clarification or add additional context in comments.

2 Comments

wow, it works exactly as i want. i made a lot of error in my code :( Thank you very much for you time friend
It is a good thing that you are trying and you are understanding which are the mistakes you made. In this context it is a good way to learn. Keep trying.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.