Basic Ruby -Function and Block

Tram Ho

In this article, we’ll learn how to define a function, delve into blocks, and also learn about chain methods. All of them are closely related.

Function definitions

As we have learned in previous posts, a function in Ruby consists of a name and has no or more parameters:

Although it is common to ignore the parentheses, it can also be written in the following way:

One of the most important tasks in programming is involved in defining a function. In Ruby we can do this by using keyword def . Here, we will look at a simple example in the REPL. We will define a function named day_of_the_week , take the argument Time , and return the name of the weekday by that time.
Recall that the Time object has a method wday that returns the index of that day of the week. (zero-offset)

By the way, I also explain a bit about the Date library, which defines a constant for the days of the week.

And it helps us to find the day of the week name like this:

It would be very convenient, when we encapsulate this definition and logic in the day_of_the_week function, so that we can write it like this: day_of_the_week(Time.now) . Combining the above components, we have the following function:

We see that a Ruby function will start with the keyword def , followed by the function name and arbitrary arguments; then the body of the function, it determines the return value of the function; finally terminated by the keyword end. (it is equivalent to closing curly braces } as in C or Javascript). We can test the following:

The above function seems quite simple, just find the corresponding element of the array with the wday value. Like many other languages, Ruby returns the value using the return keyword, but in reality the return keyword is not necessary. Usually, Ruby will return implicitly, accordingly, the final body of the function will be automatically returned. Hence, we can rewrite the day_of_the_week function as follows:

Functions in a file

Although the function definition in the REPL is quite convenient to illustrate it to others, it is cumbersome, so the best way is to write it to the file. We will move the function defined above to the hello_app.rb file. Recall the spelling we wrote for the first time as follows:

As a first step, we need to define the function in the file.

Then, we re-edit the body in get , which will be as follows:

We try to run it to see if the application runs as expected or not. $ ruby hello_app.rb

We can make the above code neater by moving the day_of_the_week function to a separate file and include it in our app. First, we create a new file, day.rb : touch day.rb And change the code a little to make it easier to see if our code works. Note that we need to restart the Sinatra server for the code to be updated.

To check if the code is running, we will restart the server and reload the browser.
Unfortunately, our app crashes immediately, and returns the Sinatra error page, and that’s an exception of type NoMethodError. To see what we did wrong, pay attention to the error message text. It turns out that the day_of_the_week method has not been defined. And we also see the exact line of code that caused the error.

This is also a very useful debugging technique: that is, if your Ruby program fails, then the first thing to do is read the error messages carefully. And if you still do not understand exactly where the error is, then you can google the content of the error messages.

Debugging Ruby
One of the essential techniques for programming is debugging: how to quickly find and fix errors in programs. Here are some methods of finding the cause of an error in your program:

  • Trace the execution with puts : When you try to figure out why the program doesn’t work properly, it’s helpful to display the value of the variable with the puts command, and remove it when the bugs are fixed. This technique is especially useful when combined with inspect method, which returns a textual representation of the object. For example, puts array.inspect or p array
  • Stop the execution with raise : Using the raise functon, it raises an exception, which is a pretty big technique since it will stop the entire program, but when it comes to it it is a useful method. For example, raise array.inspect
  • Comment out code: This is a good idea, in case you think this code is irrelevant, and you need to focus on the code that doesn’t run properly.
  • Use the REPL: Let’s turn on the irb, and paste the problematic code in, it’s a convenient way to isolate the problem. (A more advanced technique is to use pry gem, it allows running irb right in the app)
  • Google it: If you can’t find the problem on your own, then google the error message content is a good way. (It usually leads us to some useful sites like Stack Overflow for example …)

Cause our app crash was due to have removed content in file DAY_OF_THE_WEEK hello_app.rb, so our app will not understand what that function is. The solution is to add a require statement to the file containing the function. Note that the require statement includes the relative path of the file.

Restart the Sinatra server again, and our app is working fine.

Method chaining

In this section we will build the palindrome? function, this function returns true if the input argument is the same for both forward and reverse readings. Otherwise, false will be returned. Or we can understand palindrome simply as “A string and the reverse of that string are the same.” And, the chaning method is meant to call a sequence of messages of a particular object. Also, in the previous articles we learned how to create an array of characters that is split by an empty string:

And the way to reverse an array is as follows:

And the join method to undo the split method:

And, we can reverse a string using the chaining method like so:

Or we can use a simpler method than the String # chars method, which will return the characters of the string as an array:

This method is perfectly suited to use, and is essential in languages ​​that do not support a dedicated method to reverse a string (such as Javascript …). However, Ruby has built-in support for string reversal, through the String # reverse method:

However, to detect palindromes as “Racecar”, we need to combine reversing and downcasing :

With the above knowledge, let’s try to create the palindrome method. First, we need to create a file palindrome.rb to write our function: $ touch palindrome.rb The $ touch palindrome.rb function will take a string and return true if the string is palindrome, otherwise it will return false.

Above, we used the == comparison, so Ruby will automatically return the boolean value. We can test the code using irb like this: >> load './palindrome.rb'
Using load is better than require as used in the previous sections. Because, it allows reloading the file if changed, while require does not allow us to. And through that, can we access the palindrome? from REPL:

The palindrome method indicated that “Racecar” is not a palindrome, so to make our function more general we need to downcase string before comparing like this:

We try to run it again and test:

-> Returns true.
Finally, we will apply the DRY (Don’t Repeat Yourself) principle to eliminate duplication in the code above. Reviewing the above code, we see that string.downcase has been used 2 times. Therefore, we will declare a new variable called processed_content to hold the string value for comparison with the reverse string.

The above code has helped us reduce 1 call downcase , but must write one more line. It may not seem like much of an improvement, but the declaration of a separate variable gives us much more flexibility in detecting and handling a complex palindromes.
Finally, we run again to see the palindrome function? is it still working correctly?

Blocks

Blocks are one of the most useful features and structures in Ruby. We’ve seen it in previous sections and articles. However, in this section we will focus on digging deeper into how it works.
We’ll start with a simple block that prints out the powers of 2:

The code above calls each function in scope (1..5) and has blocks of {| i | puts 2 * i} . In it, vertical bars surround variable name | i | That’s Ruby’s syntax called block variable . In this case, the each method can process the block with the single local variable, which we set as i , and only execute this block within the specified scope.
We can use curly braces to delineate a block like above, or we can write in the following way:

Blocks can be one or more lines. Normally, we will follow convention of using curly braces for short method (in 1 line) and use do..end for long method (written on multiple lines).

Above, we changed the variable name from i to number , to emphasize that the variable name is optional, you can name anything.
And we can think of blocks as anonymous (unnamed) functions that we can create right away. If you have learned about Javascript, you will find this usage quite familiar, which is that it includes an unnamed function to print out elements in the Javascript array:

A Ruby block can be seen as a way to do the same Js code above without having to include a separate function.

Perhaps, each is the most common method to use in a block, but there are many other similar functions, such as the times method, which iterates over a given block a certain number of times:

Yield

We can develop our understanding of blocks by using them in some of our functions. Note that (1) every Ruby method can take a block and (2) we can call the block using the yield keyword. Let’s take a look at a few specific examples to understand how it works:
First, we create a new file: $ touch blocks.rb .
Then, we define a function called sandwich , and yield a block that will lie between two puts commands

So what does a block mean? It’s a one-block sandwich run.

Running the above file, we have the following results:

One advantage of Ruby’s block is that it will not display until the yield keyword appears.
The next example is about the tag function, which will wrap the text into the passed HTML tag. In this example, we learn how to use block variables.

Above, we have defined a function with many parameters, separated by commas between parameters. Then we pass the tag function two required parameters, tagname and text, and a block representing the HTML markup.

Running the above code, we get the following result:

 

Over. We will learn together about other topics in Ruby in the next posts.
Source: Learn-enough

Share the news now

Source : Viblo