Yes, Ruby is a very different way of looking at things compared to DSP and ASM (or "Green" primitives)! While there are methods which have "aliases" (different names for the same thing), there are usually enough subtle differences to justify having several ways of doing the same thing.
However, I get the feeling from your examples that maybe what's baffling you most is the difference of "type systems". "Green" primitives, DSP, and assembly are all "strictly typed" - the "type" of data that a component can use is determined entirely by the component (or instruction) itself. An "add" primitive with "F" inputs (or assembly "addps") only ever adds values of the "floating-point number" type and returns a floating-point number, and an Array Builder primitive with "[F]" output only ever builds a "container of floating point numbers" type. If you feed one of these components with the wrong kind of data it either won't work or, in the case of most "green" primitives/connectors, FS will attempt to convert the data to the correct type before using it.
OTOH, Ruby code works the other way around - when you call a method, Ruby looks at what type of object you have, and does whatever best seems to fit that type of object. Each different type (or, in Ruby lingo "class") of object can have it's own version of a method (or none at all). If the method call doesn't make sense for the objects in hand, it will usually just fail (automatic conversions are rare, aside from between Float/Integer numbers). For example...
- Code: Select all
a = 1
b = 2
c = a + b
# "c" now equals 3 - Integer summing.
a = "Hugh"
b = "Banton"
c = a + b
# "c" now equals "HughBanton" - String concatenation.
a = [1, 2]
b = [3, 4]
c = a + b
# "c" now equals [1, 2, 3, 4] - Array concatenation.
a = [1, 2]
b = "Banton"
c = a + b
# TypeError: can't convert String into Array.
# (An Array can only have another Array joined to it.)
a = Color.new(255)
b = 2
c = a + b
# NoMethodError: No method "+" for Color.
# (There isn't any "+" behaviour defined for Colors!)
When you call a method using "dot notation" (
@my_object.method_name()), the class of the object before the dot determines which behaviour you get, and for operators such as "+", it's the object on the left hand side (in fact, there's no difference - operators are just regular methods with "syntax sugar" to allow the familiar mathematical infix notation).
This type-system is known as "duck typing" (from the old saying; "if it waddles like a duck and quacks like a duck, then treat it as a duck"), and the methods/operators are said to be "polymorphic" ("many shaped"). As we've seen in the previous posts, Ruby Arrays are similarly versatile - there is only one, generic class of Array, but the elements can be of any type at all, and you can mix elements of different classes in the same Array. In contrast, "Green" has three "types" of Array; but they're "strict", only allowing homogenous lists of floats, integers, or strings respectively.
HughBanton wrote:So, what happens with this one, concatenating strings?
Whether for a RubyEdit or any other kind of primitive, if the type of "green" data does not match the type of an input connector, the data is converted to the connector type BEFORE anything else is done with it. So, in this case, conversion happens outside of the Ruby code, and the Ruby variables will contain Arrays of Floats. The Ruby code will therefore use the Array form of the "+" operator - so you'll get Array concatenation, not String concatenation.
Similarly, for RubyEdit outputs, FS will convert invalid Ruby data into the correct output connector type before it can be passed along to subsequent components. For example, a "green" float array output will convert non-Float Array elements to zero (or will output an empty float array if the Ruby code failed to produce an Array at all).
HughBanton wrote:...didn't know you could do this!
As with so much of it, the User Guide documentation of "green" type conversions (end of Chapter 5) is incomplete! For example, if you connect any kind of array link to an integer connector, you'll get the size of the Array. I don't know of any comprehensive list, so I can't even tell you for sure what's missing - even after all my time using FS/SM, I still get the odd surprise!
These different type-systems have another consequence: With "green" primitives, you pretty much can't connect things together in a way that will break anything - when a Float is expected, FS will make damned sure that it gets one! OTOH, Ruby doesn't hold our hands anything like as much - it's easy to get the dreaded "red boxes" and Ruby shut-downs if you lose track of what kind of objects you're passing around!
(PS: If mY Capitalisation seems a BiT strAnge: In Ruby, the names of classes of object are always in UpperCamelCase. I habitually do the same in prose when writing about code- but please don't rely on me being at all consistent about it when there's a class-name/generic-word ambiguity!!).