Support

If you have a problem or need to report a bug please email : support@dsprobotics.com

There are 3 sections to this support area:

DOWNLOADS: access to product manuals, support files and drivers

HELP & INFORMATION: tutorials and example files for learning or finding pre-made modules for your projects

USER FORUMS: meet with other users and exchange ideas, you can also get help and assistance here

NEW REGISTRATIONS - please contact us if you wish to register on the forum

Users are reminded of the forum rules they sign up to which prohibits any activity that violates any laws including posting material covered by copyright

need ruby help

For general discussion related FlowStone

Re: need ruby help

Postby trogluddite » Fri Apr 26, 2013 3:18 pm

Ah, that's an interesting case.

A hash can contain absolutely any object you like - including other nested hashes, arrays etc.
The problem here is actually with the GraphicsPath.addEllipse method.

Let's say we have a simple addition method called add...
Code: Select all
x = a.add(b)

...OK, simple enough - the method has the receiver 'a', and a parameter 'b', and it returns the result of the maths and puts it into x.
The important thing here is that it's entirely up the the 'add' method what it sends back as a result - you could just as easily define the method ignore 'a' and 'b' and just return a string, "Go away, I don't like doing maths!"

Now, when you call GraphicsPath.addEllipse, something different happens - what is known as "modifying the receiver".
When you do...
Code: Select all
@my_path = GraphicsPath,new
@my_path.addEllipse([x,y,w,h])

...the 'addEllipse' method doesn't actually return any value at all - just 'nil'. Instead, the original "receiver" object held inside @my_path gets updated "in-place" by adding the ellipse to it.
That's why, in the User Guide examples for the paths, you hardly ever see any assignment ('=') operations - there is no need to assign the modified path to a new (or the same) variable, because the modified path is already there in its original place.

The same with your hash; when you do...
Code: Select all
data[:shape] = data[:path].addEllipse...

...the ellipse is added directly to the GraphicsPath inside data[:path], and data[:shape] ends up with the return value of 'nil'. To display your ellipse, you would simply draw data[:path] to the screen.

This is something to be careful to watch out for if you are looking up methods in the Ruby documentation - it's very important to know if a method returns a new value, or whether the original 'receiver' object is being modified "in-place". In some cases, there are two versions of the same method, so that you have the choice of doing it either way.
For example, when converting a string to uppercase...
Code: Select all
a = "hello"
b = a.upcase   =>  a: "hello",  b:"HELLO"

...'a' was not changed, and 'b' got assigned to the new value.
...OR....
Code: Select all
a = "hello"
a.upcase!  => a:"HELLO"

...we just changed the value of 'a' directly, replacing "hello" with "HELLO".
You notice that the "in-place" version ends with an exclamation mark (often called a "bang"). Where there is a choice like this, that is the Ruby convention - the "bang" is a warning that you are modifying your receiver object. But there is no requirement for the "bang", it's just a choice of the developer how they name their methods and it can't be trusted to 100% tell you.

Actually, in Ruby, a method always has to send back a return value, even if it is just 'nil', so you could still write...
Code: Select all
b = a.upcase!

But this is still just modifying 'a', and you have to be careful to check what the return value actually is - sometimes it something useful, sometimes not. it could be just a copy of the new value, sometimes a 'flag' giving you some info about what the method just did, "yes, I found some lower case letters that needed converting".
A good example of that is the 'pop' method that extracts the last value in an array....
Code: Select all
a = [10,20,30,40,50]
b = a.pop    => a:[10,20,30,40],  b:50

...in this case, the return value in 'b' is the 'popped' number from the end of the array - but the array also gets modified by having the 'popped' value removed.

So, why do it two different way - is it just to confuse us? ;)

Well, Ruby is all about objects, and creating new objects can be pretty CPU intensive - they have to be stored, indexed, have their "constructor" called to build their inner workings etc. That's especially true of something like a GraphicsPath that could hold hundreds or thousands of data points - having a dozen copies of the same, huge, GraphicsPath is just littering!
And when an object is no longer being used, the "Garbage Collector" has to go around cleaning them all up, so that you don't run out of memory - for example, all those local variables that have to get 'killed' when their method comes to an end - they have to be swept up every once in a while, and that takes some CPU too.
By using a "bang" method, you can just modify an object that already exists, saving a lot of CPU and memory if the object is a particularly bulky one.

So for GraphicsPath, using "self-modifying" methods is a wise choice. You might want to add dozens of shapes/lines/curves to the same path to build a complex shape - and there is no point creating a brand new "incomplete" path at every step, none of which you would ever want to draw.

I think this is something that really should be made clearer in the documentation. If you look at the official guides for the Ruby language, every standard method has a full description of the return value, and what, if anything, happens to the receiver - it's crucial information for being able to diagnose bugs like your hash problem - and if I hadn't spent so much time working on my own graphical doo-dads, I probably wouldn't have had a clue how to answer your question!
All schematics/modules I post are free for all to use - but a credit is always polite!
Don't stagnate, mutate to create!
User avatar
trogluddite
 
Posts: 1730
Joined: Fri Oct 22, 2010 12:46 am
Location: Yorkshire, UK

Re: need ruby help

Postby Tronic » Sat Apr 27, 2013 2:30 pm

Many thanks Trog,
I have understood now, that we must think with the concept of getter and setter for the variable and related functions.
Thanks again for your time, in helping others.
Tronic
 
Posts: 539
Joined: Wed Dec 21, 2011 12:59 pm

Re: need ruby help

Postby RJHollins » Sat Apr 27, 2013 8:41 pm

Thanks TROG ...

I feel I have a slightly better understanding. The test will be when I'm flying solo :o
:lol:
RJHollins
 
Posts: 1571
Joined: Thu Mar 08, 2012 7:58 pm

Previous

Return to General

Who is online

Users browsing this forum: No registered users and 84 guests