Spogg wrote:@m = (4) is correct. The (4) in brackets declares the size of the array, not an element
Nope! -
@newdsp is closer to what you were aiming for. Your parentheses are just evaluated as enclosing a mathematical expression - so it just assigns integer four. To create an Array, you either need to do what
@newdsp did, and use square brackets (albeit his array has only one element - you might prefer e.g.
@m = [0, 0, 0, 0]), or use the Array.new method...
Code: Select all
@m = Array.new # Creates an empty Array.
@m = Array.new(4) # Creates an array with four empty (nil) elements.
@m = Array.new(4, 0) # Four elements all zero (needs care if the element is not numeric)
The reason that your code and
@newdsp's code both work is because the
event method is assigning a new value for @m at every Midi event anyway, and prior to this happening @m isn't processed in any way. In fact, you could have assigned anything, or nothing at all, to @m in the
init method without it making any difference, because Ruby variables differ from DSP/ASM variables in a couple of important ways:
1) You don't have to declare Ruby variables at initialisation to reserve space; they're just created ad-hoc when the first assignment happens. Of, course, you still should initialise them if you need them to have specific values at startup! Reading an unassigned
@instance_variable (the persistent kind) will return
nil. Trying to read an unassigned
local_variable is an error.
2) Assigning to a variable doesn't fix its value type. The same variable could hold an Integer one moment, and an Array of Strings the next; Ruby just doesn't care. Naturally, as a coder,
you should care! - being consistent is jolly helpful, though switching types does have its uses (e.g. Pens and Brushes are interchangeable for GUI drawing methods).
BTW, creating the Array and a new Midi object is redundant and quite wasteful in this case. Sending out the same Midi object (when you need to) is fine, and you can test the key data values directly. Here's a neater example (though the sent Midi objects aren't so Christmassy!

)...
Code: Select all
def init
# Checking multiple static values is quicker, more legible, and shareable using an Array.
@ghs_keys = [67, 69, 71, 72, 74, 76, 77, 79, 81]
end
def event i, v
# If the incoming value is a Midi object, we don't care where it came from!
if v.is_a?(Midi)
# '.include?' returns true if the argument value is anywhere in the Array.
if @ghs_keys.include?(v.data1) || @keysw == v.data1
output v
end
end
end
NB: Syntax: Don't space out or omit the question marks of
.is_a?() or
.include?() - they are part of the method names, not separate symbols; Ruby uses this a lot for predicate [true/false question] methods. Also, prefer boolean
&& and
|| over
and and
or - the latter have unusual precedence rules in Ruby; it's rarely a problem in practice, but that just makes it all the more perplexing when it does bite!