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
[Ruby] Blocks explained
3 posts
• Page 1 of 1
[Ruby] Blocks explained
I was hesitating to do a mini-tutorial on this subject, because blocks are advanced Ruby programming tools, and I am not sure if I can explain them as simple, as I could in the other mini-tutorials.
We can't talk about blocks, without talking about a certain concept, that lead to the existence of blocks. The concept came up with object-oriented programming and simply says: Don't repeat yourself!
Let's look at an example. We might want to find the distance of coordinates from zero, but once in cm and once in inches. Straight forward, the code might look like so:
But here we repeat the same line of code, and that is redundant and ugly to look at. So the next step might be this:
Ok, but now we have 3 methods, and two of them are only slightly different. They only differ on the unit. And here come blocks into play. A block will help us cleaning up the code further:
Let's analyze this. We can see that there is a block passed to the method. We also see a new command, "yield". Now, I don't know why they decided to use that word. I had a hard time to understand it. Stripped down it calls and runs the block that is passed to the method, it is placed in. Copy the following example and paste it into an empty RubyEdit:
yield runs whatever the block contains. Which makes obvious that a block is nothing more than a chunk of code, that is executed from within the method with the command yield. Add this line in your RubyEdit that contains the example above:
This shows another aspect. Just as a method would, yield not only executes the code, but also returns the last evaluation to the method (in this case the result from 3*2, which is 6).
So how is a block constructed? It is always passed to a method, and it is enclosed by the keywords do and end. If your block is a simple one-liner, you can pass it inline, which means you replace do and end by { and }. If your block contains more than one line, you will use do and end, though:
Let's go one step further. A block can have parameters (which are very similar to arguments of a method). Those paramters will have to be passed by yield, and you can access them using local variables enclosed with the pipe sign.
Clear your RubyEdit and paste the following code:
The first value yield passes is assigned to a, the second to b. You can pass as many parameters as you like, and the block is free to use as many as it likes (including none of them). The Ruby style guide says that if you use only some of the parameters you should show the unused ones as an underscore ( for example, { |_, b| 4 * b } ). And of course you can name the parameters in the block however you like. Just use snake_case (for example { |my_awesome, two_values| my_awesome + two_values }
If you passed attention you have probably noticed, that the last code example looks a lot like the blocks, you use for iterations. And that is no coincidence. As a matter of fact, you can use yield in your method as often as you like, and the enumerable module uses it to pass yield in a loop for every object in an iteration, so that you can access the object AND return the changes you made in the block.
However, here's a serious warning. Yield does not check the code in the block. Therefore a block is very powerful and could be used to inject malicious code. By all means, never expose your blocks to the outside world! It could be replaced by harmful code. And because this is really important NOT to do, I won't talk about how you would make blocks exposed!
We can't talk about blocks, without talking about a certain concept, that lead to the existence of blocks. The concept came up with object-oriented programming and simply says: Don't repeat yourself!
Let's look at an example. We might want to find the distance of coordinates from zero, but once in cm and once in inches. Straight forward, the code might look like so:
- Code: Select all
def in_cm(a, b)
dist = (a**2 + b**2)**0.5
return "The length is #{ dist } cm"
end
def in_inches(a, b)
dist = (a**2 + b**2)**0.5
return "The length is #{ dist } inches"
end
But here we repeat the same line of code, and that is redundant and ugly to look at. So the next step might be this:
- Code: Select all
def distance(a, b)
dist = (a**2 + b**2)**0.5
return "The length is #{ dist } "
#we could very well make a one-liner from it, but this is easier to understand
end
def in_cm(a, b)
return distance(a, b) << "cm" #this extends the returned string by "cm".
end
def in_inches(a, b)
return distance(a, b) << "inches"
end
Ok, but now we have 3 methods, and two of them are only slightly different. They only differ on the unit. And here come blocks into play. A block will help us cleaning up the code further:
- Code: Select all
def distance(a, b)
dist = (a**2 + b**2)**0.5
return "The length is #{ dist } " << yield
end
first = distance(2, 3) { "cm" }
second = distance(5, 1) { "inches" }
Let's analyze this. We can see that there is a block passed to the method. We also see a new command, "yield". Now, I don't know why they decided to use that word. I had a hard time to understand it. Stripped down it calls and runs the block that is passed to the method, it is placed in. Copy the following example and paste it into an empty RubyEdit:
- Code: Select all
def mymethod
yield
end
mymethod { watch "Hello, I was executed from mymethod" }
yield runs whatever the block contains. Which makes obvious that a block is nothing more than a chunk of code, that is executed from within the method with the command yield. Add this line in your RubyEdit that contains the example above:
- Code: Select all
mymethod { 3 * 2 } #info pane will report 6
This shows another aspect. Just as a method would, yield not only executes the code, but also returns the last evaluation to the method (in this case the result from 3*2, which is 6).
So how is a block constructed? It is always passed to a method, and it is enclosed by the keywords do and end. If your block is a simple one-liner, you can pass it inline, which means you replace do and end by { and }. If your block contains more than one line, you will use do and end, though:
- Code: Select all
mymethod do
x = 3 * 2
y = 4 * 5
x + y
end
Let's go one step further. A block can have parameters (which are very similar to arguments of a method). Those paramters will have to be passed by yield, and you can access them using local variables enclosed with the pipe sign.
- Code: Select all
{ |a, b| a * b } #we get the objects for a and b passed by yield and the block uses them to multiply them
Clear your RubyEdit and paste the following code:
- Code: Select all
def mymethod
yield(3, 4)
end
mymethod { |a, b| a * b }
The first value yield passes is assigned to a, the second to b. You can pass as many parameters as you like, and the block is free to use as many as it likes (including none of them). The Ruby style guide says that if you use only some of the parameters you should show the unused ones as an underscore ( for example, { |_, b| 4 * b } ). And of course you can name the parameters in the block however you like. Just use snake_case (for example { |my_awesome, two_values| my_awesome + two_values }
If you passed attention you have probably noticed, that the last code example looks a lot like the blocks, you use for iterations. And that is no coincidence. As a matter of fact, you can use yield in your method as often as you like, and the enumerable module uses it to pass yield in a loop for every object in an iteration, so that you can access the object AND return the changes you made in the block.
However, here's a serious warning. Yield does not check the code in the block. Therefore a block is very powerful and could be used to inject malicious code. By all means, never expose your blocks to the outside world! It could be replaced by harmful code. And because this is really important NOT to do, I won't talk about how you would make blocks exposed!
"There lies the dog buried" (German saying translated literally)
- tulamide
- Posts: 2714
- Joined: Sat Jun 21, 2014 2:48 pm
- Location: Germany
Re: [Ruby] Blocks explained
Bravo!
Yet again you’ve explained what I think is a tricky concept better than any other I’ve read.
And I must offer the biggest thanks I can for taking time to do this for me/us.
It’s one thing to know something really well and be an expert, but it’s a rare talent that can also explain what they know so lucidly. In one tutorial I have, the writer introduced blocks and went on to use pipes without ever explaining WTF they were for exactly. I had to shout at my monitor in sheer frustration.
Again, many thanks tulamide.
Spogg
Yet again you’ve explained what I think is a tricky concept better than any other I’ve read.
And I must offer the biggest thanks I can for taking time to do this for me/us.
It’s one thing to know something really well and be an expert, but it’s a rare talent that can also explain what they know so lucidly. In one tutorial I have, the writer introduced blocks and went on to use pipes without ever explaining WTF they were for exactly. I had to shout at my monitor in sheer frustration.
Again, many thanks tulamide.
Spogg
-
Spogg - Posts: 3358
- Joined: Thu Nov 20, 2014 4:24 pm
- Location: Birmingham, England
Re: [Ruby] Blocks explained
Prior to this .... I had never heard of Ruby Blocks.
Once again ... Thanks T !!
Once again ... Thanks T !!
- RJHollins
- Posts: 1571
- Joined: Thu Mar 08, 2012 7:58 pm
3 posts
• Page 1 of 1
Who is online
Users browsing this forum: No registered users and 10 guests