Dynamic constant assignment main.rb:6: Ruby

Viewed 648

I get that error while naming variables in my loop. The point of the method is to print the index position of the only element with unique parity in the array. For example the method should print "3" for the following input array because it is the only odd number and everything else is even: [2, 4, 6, 3, 8, 10]. More specifically, it points out the error to "Odd" and "Even" variables below ("main.rb:7: dynamic constant assignment Odd = numbers[i] % 2 == 1").

  def test(numbers)
  i=1
  countOdd = 0
  countEven = 0
  Odd = numbers[i] % 2 == 1
  Even = numbers[i] % 2 == 0

  while i < numbers.length
    if Odd
      countOdd += 1
      else countEven +=1
      end
    i+=1
  end

  if countEven == 1
  print Odd.index
  else print Even.index
  end
end
2 Answers

When you define a Capitalized variable in Ruby, that is a constant - it is a special kind of variable that is not allowed to change value (well, technically you can change it with const_set, but that's not really relevant here).

Because of this limitation, Ruby won't allow you to change constants from within functions. It assumes the function will be called many times, which would cause the constant to change value, which as I just mentioned is illegal.

So, quick fix, just replace your Odd and Even with the lowercase versions odd and even. That way they're regular variables and not constants.

the above code could be return easily using the built in array methods:

even_numbers = numbers.select(&:even?)
odd_numbers = numbers.select(&:odd?)

then the even counts will be even_numbers.count, and similarly odd_numbers.count

the first odd number index will be numbers.find_index(odd_numbers.first)

for the constants you can assign a proc to the constant : Odd = Proc.new{ |n| n%2 == 1 } then call the constant like this: Odd.call(10) #=> false, similarly you can define a proc for even numbers.

what happening here is every time the method get called the constant will be redefined thus having a new value, but constants are meant to hold a value that would not change, and that is the cause of the error.

also note that the following condition in your method:

if Odd
  then do something
....

is not actually correct. once the constant holds a value then it will have that value during execution. so after doing Odd = some_integer % 2 == 1 the Odd constant will be either true or false always. and will not re-execute some_integer % 2 == 1 in your if condition. but if you make it a proc or lamda it well re-do the calculation because it wil be as if you are calling a method.

[NOTE] however doing Odd = Proc.new{ |n| n%2 == 1 } inside your method will still give you the same error dynamic constant assignment Odd = Proc.new { |n| numbers[n] % ... since still the code is re-executed every time the method runs giving the constant different values each time. so by putting Odd = Proc.new{ |n| n%2 == 1 } definitions outside of the method then doing if Odd.call(i) it will work just fine.

Related