-1

I have this method

def forest(sword, armour, ring)

with its arguments having true or false values, which I declare in the main program as

forest false, false, false

If during the program sword=true && armour=true, is there any way for Ruby to automatically assess whether the arguments are true or false? Could I write something like

forest sword-truth-value, armour-truth-value, ring-truth-value?

The program I'm writing is very long and it would take too many code lines to take every single case into consideration.

Thanks for the help!

davidhu
  • 9,523
  • 6
  • 32
  • 53
Sophie Proud
  • 223
  • 1
  • 6
  • I'm not sure I understand the question, can you clarify with a few more examples? – davidhu Oct 12 '16 at 19:05
  • During the program, sword changes its truth value. Instead of sword=false, now sword=true and when I write the forest method again, I should write forest true, false, false. But what if I wanted Ruby to tell me whether or not sword is true or false? Is there any command that can do that? – Sophie Proud Oct 12 '16 at 19:11
  • I think i have an idea now, I'll work on an answer below – davidhu Oct 12 '16 at 19:22
  • Remember that `sword=true && armor=true` does an **assignment** to both variables and not a test. If you want to compare, use `==`. When doing multiple assignments don't chain together with `&&`, just put them on multiple lines, or do `sword = armor = true` if you want it compact. – tadman Oct 12 '16 at 19:41

2 Answers2

2

To achieve what you are looking for, you should wrap the forest method in a class and define each argument as an instance variable.

class Forest

  attr_accessor :sword, :armour, :ring

  def initialize(sword = false, armour = false, ring = false)
    @sword = sword
    @armour = armour
    @ring = ring
  end

end

So now, you can declare an instance of Forest,

forest = Forest.new

All the variables default to false, unless you explicitly write true.

With the attr_accessor, you can access and set all the variables.

forest.sword #=> false
forest.sword = true
forest.sword #=> true
davidhu
  • 9,523
  • 6
  • 32
  • 53
1

The values true and false are atomic. If you don't want pass them as literal values you have to set a variable, i.e.

is_sword = false
is_armor = false
is_ring = false
forest is_sword, is_armor, is_ring

It seems like that should address your question, but it might be worth introducing the concepts of "mutable" objects as well. For example hashes and arrays are mutable:

   hash = { armor: false, sword: false, ring: false }
   def delete_nil_values(options)
     # delete all key-vals from the hash where the val is falsey
     options.each_key { |key| options.delete(key) if !options[key]}
     options
   end
   delete_nil_values(hash)
   puts hash
   # => {} 
   # it is empty

This may or may not be what you intend; if you want to write 'side effect free' code you should be aware of this.

If you "clone" the input at the top of the delete_nil_values method using options = Marshal.load(Marshal.dump(options)) then it will be immutable.

To summarize: A function evaluates its arguments at runtime. So its variables will be the same that you passed in but if you have side-effects in your code the variables may have mutated.

max pleaner
  • 26,189
  • 9
  • 66
  • 118