How to write a global variable?

Couldn’t find anything about it in the documentation. The code is:

# input
a440hz = 440
octave_division = 12
semitone_offset = [0,0,0,0,0,0,0,0,0,0,0,0]
tuning_stretch = 0
random_offset = 0

def tuning_generator
	i = 0; while i < 128
		puts frequency(i+1)
		i += 1
	end
end

tuning_generator

def frequency(note)
	a440hz * (2 + tuning_stretch ** ((note - 57) / octave_division))
end

The frequency method is using the variables on top of the file. How to make them global variables so I can access them everywhere?
ps. don’t know for sure if this is the right formula for frequency :slight_smile:

There are no global variables in Crystal. You can use constants for this.

An alternative would be class variables.

2 Likes

In addition to what @straight-shoota said, global vars can be considered a bad practice depending on the context. Not really applicable to this small example, but as a/your application grows bigger and bigger they probably aren’t the best solution anymore.

Ref: https://wiki.c2.com/?GlobalVariablesAreBad.

2 Likes

I would like to ask an additional question on this topic.

When I was trying to convert a ruby code with global variables to a crystal code, it took some time how to convert.

Please check the following codes and let me know if there is a better way.

Using constants:

A440HZ = 440
OCTAVE_DIVISION = 12
TUNING_STRETCH = 0

def frequency(note)
  A440HZ * (2 + TUNING_STRETCH ** ((note - 57) / OCTAVE_DIVISION))
end

Using class variables:

module Global
  class_property a440hz, octave_division, tuning_stretch
  @@a440hz = 440
  @@octave_division = 12
  @@tuning_stretch = 0
end

def frequency(note)
  Global.a440hz * (2 + Global.tuning_stretch ** ((note - 57) / Global.octave_division))
end

Thank you, in advance.

In Ruby those aren’t called global variables. They are called constants. It’s the same thing in Crystal. I don’t have a computer near y, but that Ruby code should work out of the box in Crystal.

I think both code examples are Crystal translations of a non-disclosed original Ruby code. One translation changed global variables to constants, the other to class variables.

@j.m Without knowing the overall intention of the code, it appears that these values are actually constant values. They’re not going to change during the runtime of the program. So using constants seems like a natural choice (even in Ruby).

Thank you for your reply. I know that those in my codes are not called global variables in crystal/ruby. I want to realize replacement of global variables that have the prefix $ in ruby. I understand that using constants or class variables depends on the context. I think it is better not to introduce an unnecessary class/module.

If you have this code in Ruby:

$global = 1
puts $global

You can do this in Crystal:

module Globals
  class_property global : Int32?
end

Globals.global = 1
puts Globals.global

Thank you for your reply again. I have progressed.

A minor comment on your original code. I would rather write the while like:

(1..128).each do |i|
  puts frequency(i)
end
2 Likes