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

[Ruby] Blocks explained

Post any examples or modules that you want to share here

[Ruby] Blocks explained

Postby tulamide » Thu Apr 26, 2018 12:39 am

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:
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

Postby Spogg » Thu Apr 26, 2018 7:35 am

Bravo! :ugeek:

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
User avatar
Spogg
 
Posts: 3358
Joined: Thu Nov 20, 2014 4:24 pm
Location: Birmingham, England

Re: [Ruby] Blocks explained

Postby RJHollins » Thu Apr 26, 2018 9:31 am

Prior to this .... I had never heard of Ruby Blocks.

Once again ... Thanks T !!
RJHollins
 
Posts: 1571
Joined: Thu Mar 08, 2012 7:58 pm


Return to User Examples

Who is online

Users browsing this forum: No registered users and 45 guests