Ruby Programming/Print version
This is the print version of Ruby Programming You won't see this message or any elements not part of the book's content when you print or preview this page. |
Overview
Ruby is an object-oriented scripting language originally developed by Yukihiro Matsumoto (also known as Matz). The main website of the Ruby programming language is ruby-lang.org. Development began in February 1993 and the first alpha version of Ruby was released in December 1994. It was developed as an alternative to scripting languages like Perl and Python.[1] Ruby borrows heavily from Perl and the class library is essentially an object-oriented reorganization of Perl's functionality. Ruby also borrows from Lisp and Smalltalk. While Ruby does not borrow many features from Python, reading the code for Python helped Matz develop Ruby.[1]
MacOS comes with Ruby already installed. Most Linux distributions either come with Ruby preinstalled or allow you to easily install Ruby from the distribution's repository of free software. You can also download and install Ruby on Windows. The more technically adept can download the Ruby source code[2] and compile it for most operating systems, including Unix, DOS, BeOS, OS/2, Windows, and Linux.[3]
Features
Ruby combines features from Perl, Smalltalk, Eiffel, Ada, Lisp, and Python.[3]
Object Oriented
Ruby goes to great lengths to be a purely object oriented language. Every value in Ruby is an object, even the most primitive things: strings, numbers and even true and false. Every object has a class and every class has one superclass. At the root of the class hierarchy is the class BasicObject, from which all other classes, including Object, inherit.
Every class has a set of methods which can be called on objects of that class. Methods are always called on an object — there are no “class methods”, as there are in many other languages (though Ruby does a great job at faking them).[citation needed]
Every object has a set of instance variables which hold the state of the object. Instance variables are created and accessed from within methods called on the object. Instance variables are completely private to an object. No other object can see them, not even other objects of the same class, or the class itself. All communication between Ruby objects happens through methods.
Mixins
In addition to classes, Ruby has modules. A module has methods, just like a class, but it has no instances. Instead, a module can be included, or “mixed in,” to a class, which adds the methods of that module to the class. This is very much like inheritance but far more flexible because a class can include many different modules. By building individual features into separate modules, functionality can be combined in elaborate ways and code easily reused. Mix-ins help keep Ruby code free of complicated and restrictive class hierarchies.
Dynamic
Ruby is a very dynamic programming language. Ruby programs aren’t compiled, in the way that C or Java programs are. All of the class, module and method definitions in a program are built by the code when it is run. A program can also modify its own definitions while it’s running. Even the most primitive classes of the language like String and Integer can be opened up and extended. Rubyists call this monkey patching and it’s the kind of thing you can’t get away with in most other languages.
Variables in Ruby are dynamically typed, which means that any variable can hold any type of object. When you call a method on an object, Ruby looks up the method by name alone — it doesn't care about the type of the object. This is called duck typing and it lets you make classes that can pretend to be other classes, just by implementing the same methods.
Singleton Classes
When I said that every Ruby object has a class, I lied. The truth is, every object has two classes: a “regular” class and a singleton class. An object’s singleton class is a nameless class whose only instance is that object. Every object has its very own singleton class, created automatically along with the object. Singleton classes inherit from their object’s regular class and are initially empty, but you can open them up and add methods to them, which can then be called on the lone object belonging to them. This is Ruby’s secret trick to avoid “class methods” and keep its type system simple and elegant.
Metaprogramming
Ruby is so object oriented that even classes, modules and methods are themselves objects! Every class is an instance of the class Class and every module is an instance of the class Module. You can call their methods to learn about them or even modify them, while your program is running. That means that you can use Ruby code to generate classes and modules, a technique known as metaprogramming. Used wisely, metaprogramming allows you to capture highly abstract design patterns in code and implement them as easily as calling a method.
Flexibility
In Ruby, everything is malleable. Methods can be added to existing classes without subclassing, operators can be overloaded, and even the behavior of the standard library can be redefined at runtime.
Variables and scope
You do not need to declare variables or variable scope in Ruby. The name of the variable automatically determines its scope.
- x is a local variable (or something other than a variable).
- $x is a global variable.
- @x is an instance variable.
- @@x is a class variable.
Blocks
Blocks are one of Ruby’s most unique and most loved features. A block is a piece of code that can appear after a call to a method, like this:
laundry_list.sort do |a,b|
a.color <=> b.color
end
The block is everything between the do and the end. The code in the block is not evaluated right away, rather it is packaged into an object and passed to the sort method as an argument. That object can be called at any time, just like calling a method. The sort method calls the block whenever it needs to compare two values in the list. The block gives you a lot of control over how sort behaves. A block object, like any other object, can be stored in a variable, passed along to other methods, or even copied.
Many programming languages support code objects like this. They’re called closures and they are a very powerful feature in any language, but they are typically underused because the code to create them tends to look ugly and unnatural. A Ruby block is simply a special, clean syntax for the common case of creating a closure and passing it to a method. This simple feature has inspired Rubyists to use closures extensively, in all sorts of creative new ways.
Advanced features
Ruby contains many advanced features.
- Exceptions for error-handling.
- A mark-and-sweep garbage collector instead of reference counting.
- OS-independent threading, which allows you to write multi-threaded applications even on operating systems such as DOS. (this feature will disappear in 1.9, which will use native threads)
You can also write extensions to Ruby in C or embed Ruby in other software.
References
- ↑ a b Bruce Stewart (November 29, 2001). "An Interview with the Creator of Ruby". O'Reilly. Retrieved 2006-09-11.
- ↑ "Download Ruby". Retrieved 2006-09-11.
- ↑ a b "About Ruby". Retrieved 2006-09-11.
Installing Ruby
The first step to get started in Ruby development is setting up your local environment. Due to differences between various operating systems we will cover multiple of them. If you are already able to use a terminal emulator and know how to install Ruby yourself, you can skip this chapter (after you installed Ruby). Otherwise we will guide you through the process of installing Ruby on your computer.
Terminal emulators
Knowing how to use a terminal emulator is very useful if you are programming. Usually it will provide the most straightforward access to commands and applications instead of hiding it behind graphical interfaces. On the other hand they are often daunting to beginners since they are often perceived to require a deep understanding of a computer when in fact often only knowing the very basics is already enough to get started.
Unix-like operating systems
One of the most commonly used shells in the Unix-like operating systems (i.e. macOS, GNU/Linux, BSD) is the Bash shell, in fact it is very often the default shell. To start a session you will often use a terminal emulator, which allow you to use a terminal session at the same time as other graphical applications. It doesn't really matter, which terminal emulator you use, generally you want one that has color and Unicode support. In macOS you can use Terminal.app which you can find under Applications > Utilities. A popular alternative is iTerm. On most Linux distributions you will usually be provided with at least one terminal emulator by default, otherwise you might want to try Terminator, Konsole, rxvt-unicode or something different.
When you open a new window or tab in your terminal emulator of choice you will be shown your prompt. What it looks like exactly depends a lot on configuration, which can vary greatly from OS to OS (you can configure everything to your likings, however this exceeds the scope of this short introduction). Generally it will indicate your current working directory, username and hostname. When working in the shell your session always has current working directory. Commands that accept relative filenames will use that directory as the base directory to look for files. By default you are in your user's home folder, which is often abbreviated with a tilde (~
).
To execute a command you just type it into the shell and press enter.
At first we want to look at the command ls
. If you type it in just like that it will print the files and directories in your current working directory. You can also provide a relative path to a directory you want to list, e.g. ls DIR
. If you want more detailed information about the files you can use ls -l DIR
, if you instead want to also include invisible entries (i.e. names starting with a dot) use ls -a
. Of course it is possible to combine them both by running ls -l -a DIR
or the short form ls -la DIR
. Note that this kind of concatenating multiple arguments into one is only possible with single character parameters. Parameters can also come in long form, for example the equivalent of ls -a
is ls --all DIR
. Which forms are available depends on the individual command.
Now you might be thinking how to remember all parameters for every command you will ever use. Thankfully you only want to remember the most important ones, which are the ones you use most frequently, otherwise there is a nice way to look them up. You can either use the man
command. For example run man ls
to find more information about the ls
command. Oftentimes you can find a more concise summary by trying to run the command in question followed by the parameter --help
, however this is not something you can expect to work well with every command, whereas manual pages should be always available.
Back to the topic of current working directories. If you want to change your directory you can use cd
followed by the directory you want to change to. There are two special virtual directories '.' and '..'. The single dot refers to the current directory while the double dot refers to a dir's parent directory. So executing cd ..
changes into the parent directory of the current working directory.
A very brief summary of other useful commands:
cat FILE
: display the contents of a file.
mkdir DIR
: create a directory.
System-wide installation
A common and easy way to install Ruby is to perform a system-wide installation. Depending on the operating system installation procedures will be different (if required at all).
Windows
Windows Operating System did not have Ruby programing language pre-installed (unlike other platforms listed here) . To install Ruby programming language, it is highly recommended to install it from here: https://rubyinstaller.org/ .
Refer to right side bar: WHICH VERSION TO DOWNLOAD? for guide to download which version to download. Usually it will recommend the latest stable version to be downloaded.
You might see the options of Ruby+Devkit installer version as a selectable component. This option is important as to build native C/C++ extensions for Ruby and is necessary for Ruby on Rails. Moreover it allows the download and usage of hundreds of Open Source libraries which Ruby gems (packages) often depend on.
Download it and double click the file to be installed on the local PC.
Once install it, double click of Ruby Installer to start installing it on Windows
Step 1: Select "I accept the license" and click "Next" button
Step 2: Select the directory that you wanted to install to and below , select the "Add Ruby executables to your PATH" and "Associate .rb and .rbw files with the Ruby installation". Click "Next" buttons"
Step 3: Select all the checkboxes inside the setup files. Click "Next"
Step 4: Click "ridk install" and click "Next" button to proceed
Once finished installing, type cmd into Window search bar and type ruby -v
sto see which version of ruby that are installed. If it is showing, congrats, you successfully installed Ruby language in the system.
Ruby comes preinstalled on macOS. To check which version is installed on your system, execute ruby -v
inside a shell session.
If you want to install a more recent version of Ruby, you can:
- Update to a newer version of macOS, which may have a more recent version of Ruby.
- Use RVM or RBEnv tools specifically for managing multiple ruby versions (This is the most popular way because you can manage many Ruby versions and associate them with projects)
- Use Fink, MacPorts, Homebrew general purpose packaging systems for mac.
On many Linux distributions Ruby is installed by default. To check if Ruby is installed on your system, run ruby -v
in a shell session.
Where this is not the case, or you want to update the installed version, you should use your distribution's package manager. Here we will provide information for some popular Linux distributions here, however it is recommended to users of all distributions to familiarize themselves with their distribution's package manager, since this will allow for the most efficient software management. Whether this is a command-line or graphical application depends on the offerings of the distribution and personal preference of the user.
Debian / Ubuntu
The package manager Synaptic provides graphical package management. It is installed by default under Ubuntu and has to be installed manually on Debian (by running sudo apt-get install synaptic
from the command line).
Instead of using Synaptic you can also use apt directly from the command-line (you can find further information in the Debian Wiki's article on Package Management). Execute sudo apt-get install ruby
from the command line to install Ruby.
Fedora
From the command-line you can install Ruby with DNF by executing sudo dnf install ruby
.
Arch Linux
Use pacman to install Ruby by executing pacman -S ruby
as root.
Mandriva Linux
On Mandriva Linux, install Ruby using the command-line tool urpmi.
PCLinuxOS
On PCLinuxOS, install Ruby using either the graphical tool Synaptic or the command-line tool apt.
Red Hat Linux
On Red Hat Linux, install Ruby using the command-line tool RPM.
Per-user Installation
Per-user installations allow each user of the system to utilize their own particular version of Ruby without impact to other users.
Guix
To install the latest available version of Ruby, run: guix install ruby
.
Setup Ruby in Windows
Ruby does not come preinstalled with any version of Microsoft Windows. However, there are several ways to install Ruby on Windows.
- Download and install one of the compiled Ruby binaries from the Ruby web site.
- Download and run the one click RubyInstaller.
- Install Cygwin, a collection of free software tools available for Windows. During the install, make sure that you select the "ruby" package, located in the "Devel, Interpreters" category.
Setup Ruby in Windows with Notepad++
In latest version of Ruby and Window 10 , it is much more easier to setup Ruby now more than ever.
We will be using [1] to start setup Ruby in Windows.
Once install Notepad++ in Windows, open up the programs and click on Plugins > Plugins Admin
At Plugins Admin , select Plugins , NppExec to install
Once installed, you can run NppExec by pressing F6
Building from Source
If your distro doesn't come with a ruby package or you want to build a specific version of ruby from scratch, please install it by following the directions here. Download from here.
Compile options
Building with debug symbols
If you want to install it with debug symbols built in (and are using gcc--so either Linux, cygwin, or mingw).
./configure --enable-shared optflags="-O0" debugflags="-g3 -ggdb"
Optimizations
Note that with 1.9 you can pass it --disable-install-doc
to have it build faster.
To set the GC to not run as frequently (which tends to provide a faster experience for larger programs, like rdoc and rails), precede your build with
$ export CCFLAGS=-DGC_MALLOC_LIMIT=80000000
though you might be able to alternately put those in as opt or debug flags, as well.
Testing Installation
The installation can be tested easily by executing:
$ ruby -v
This should produce an output similar to:
ruby 1.8.7 (2009-06-12 patchlevel 174) [i486-linux]
If this shows up, then you have successfully installed Ruby. However if you get an error similar to:
-bash: ruby: command not found
then you did not successfully install Ruby.
Ruby editors
What is Ruby IDE ?
Integrated development environment or IDE is a software tool generally contains at least a debugger, a source code editor, and build automation tools.
There are a few of text editor/IDE that can be used for Ruby Programming language (arranged alphabetically) as shown below :
Although you can write Ruby programs with any plain text editor, some text editors have additional features to aid the Ruby programmer. The most common is syntax highlighting.
P.S 1: For the ease of readers, the book will be dealing with Notepad++ as the more popular Ruby IDE, ATOMS will be sun-setted by GitHub in 15 Dec 2022.
P.S 2: Pulsar is fork from ATOM IDE. Listed below for conveniences.
Arcadia
Website: https://www.arcadia-ide.org/
GNU Emacs
Website: https://www.gnu.org/software/emacs/
ICEcoder
Website: https://icecoder.net/
Komodo
Website: https://www.activestate.com/products/komodo-ide/
Notepad++
Website: https://notepad-plus-plus.org/
Pulsar
Website: https://pulsar-edit.dev/
Ruby Packages: https://web.pulsar-edit.dev/packages/search?q=ruby
RubyMine
Price: (Annual subscription fee)
Website: https://www.jetbrains.com/ruby/whatsnew/
Sublime Text
Price: (One off payment and receives 3 years of continuous updates)
Website: https://www.sublimetext.com/
Vim
Website: https://www.vim.org/download.php#pc
References
Here is a link of spreadsheet of the various options available.
Notation conventions
Command-line examples
In this tutorial, examples that involve running programs on the command-line will use the dollar sign to denote the shell prompt. The part of the example that you type will appear bold. Since the dollar sign denotes your shell prompt, you should not type it in.
For example, to check what version of Ruby is on your system, run:
$ ruby -v
Again, do not type the dollar sign – you should only enter "ruby -v
" (without the quotes). Windows users are probably more familiar seeing "C:\>
" to denote the shell prompt (called the command prompt on Windows).
An example might also show the output of the program.
$ ruby -v ruby 1.8.5 (2006-08-25) [i386-freebsd4.10]
In the above example, "ruby 1.8.5 (2006-08-25) [i386-freebsd4.10]
" is printed out after you run "ruby -v
". Your actual output when you run "ruby -v
" will vary depending on the version of Ruby installed and what operating system you are using.
Running Ruby scripts
For simplicity, the following convention is used to show a Ruby script being run from the shell prompt.
$ hello-world.rb Hello world
However, the actual syntax that you will use to run your Ruby scripts will vary depending on your operating system and how it is setup. Please read through the Executable Ruby scripts section of the Hello world page to determine the best way to run Ruby scripts on your system.
Running irb
Ruby typically installs with "interactive ruby" (irb) installed along with it. This is a REPL that allows you to experiment with Ruby, for example:
$ irb >> 3 + 4 => 7 >> 'abc' => "abc"
Interactive Ruby
When learning Ruby, you will often want to experiment with new features by writing short snippets of code. Instead of writing a lot of small text files, you can use irb, which is Ruby's interactive mode.
Running irb
Run irb from your shell prompt.
$ irb --simple-prompt >>
The >> prompt indicates that irb is waiting for input. If you do not specify --simple-prompt, the irb prompt will be longer and include the line number. For example:
$ irb irb(main):001:0>
A simple irb session might look like this.
$ irb --simple-prompt >> 2+2 => 4 >> 5*5*5 => 125 >> exit
These examples show the user's input in bold. irb uses => to show you the return value of each line of code that you type in.
Cygwin users
If you use Cygwin's Bash shell on Microsoft Windows, but are running the native Windows version of Ruby instead of Cygwin's version of Ruby, read this section.
To run the native version of irb inside of Cygwin's Bash shell, run irb.bat.
By default, Cygwin's Bash shell runs inside of the Windows console, and the native Windows version of irb.bat should work fine. However, if you run a Cygwin shell inside of Cygwin's rxvt terminal emulator, then irb.bat will not run properly. You must either run your shell (and irb.bat) inside of the Windows console or install and run Cygwin's version of Ruby.
Understanding irb output
irb prints out the return value of each line that you enter. In contrast, an actual Ruby program only prints output when you call an output method such as puts
.
For example:
$ irb --simple-prompt >> x=3 => 3 >> y=x*2 => 6 >> z=y/6 => 1 >> x => 3 >> exit
Helpfully, x=3
not only does an assignment, but also returns the value assigned to x
, which irb then prints out. However, this equivalent Ruby program prints nothing out. The variables get set, but the values are never printed out.
x=3 y=x*2 z=y/6 x
If you want to print out the value of a variable in a Ruby program, use the puts
method.
x=3 puts x
Mailing List FAQ
Etiquette
There is a list of Best Practices[1].
See some more questions answered.
- ↑ https://web.archive.org/web/20160327125758/http://blog.rubybestpractices.com/posts/jamesbritt/and_your_Mom_too.html
Basic Ruby - Hello world
The classic Hello, world! program is a good way to get started with Ruby.
Hello, world!
Create a text file called hello_world.rb
containing the following code:
puts 'Hello, world!'
Now run it at the shell prompt.
$ ruby hello_world.rb Hello, world!
You can also run the short "Hello, world!" program without creating a text file at all. This is called a one-liner.
$ ruby -e "puts 'Hello, world!'" Hello, world!
Option -e
means evaluate (Ruby code). You can run this code with irb, but the output will look slightly different. puts
will print out "Hello, world!
", but irb
will also print out the return value of puts
— which is nil
.
$ irb >> puts "Hello, world!" Hello, world! => nil
Comments
Like Perl, Bash, Python, and C Shell, Ruby uses the hash symbol (also called Pound Sign, number sign) for comments. Everything from the hash to the end of the line is ignored when the program is run by Ruby. For example, here's our hello_world.rb
program with comments.
# My first Ruby program
# On my way to Ruby fame & fortune!
puts 'Hello, world!'
You can append a comment to the end of a line of code, as well. Everything before the hash is treated as normal Ruby code.
puts 'Hello, world!' # Print out "Hello, world!"
You can also comment several lines at a time:
=begin
This program will
print "Hello, world!".
=end
puts 'Hello, world!'
Although block comments can start on the same line as =begin
, the =end
must have its own line. You cannot insert block comments in the middle of a line of code as you can in C, C++, and Java, although you can have non-comment code on the same line as the =end
.
=begin This program will print 'Hello, world!'
=end puts 'Hello, world!'
Executable Ruby scripts
Typing the word ruby
each time you run a Ruby script is tedious. To avoid doing this, follow the instructions below.
Unix-like operating systems
In Unix-like operating systems – such as Linux, Mac OS X, and Solaris you will want to mark your Ruby scripts as executable using the chmod
command. This also works with the Cygwin version of Ruby.
$ chmod +x hello_world.rb
You need to do this each time you create a new Ruby script. If you rename a Ruby script, or edit an existing script, you do not need to run "chmod +x
" again.
Next, add a shebang line as the very first line of your Ruby script. The shebang line is read by the shell to determine what program to use to run the script. This line cannot be preceded by any blank lines or any leading spaces. The new hello_world.rb
program – with the shebang line – looks like this:
#!/usr/bin/ruby
puts 'Hello world'
If your ruby
executable is not in the /usr/bin
directory, change the shebang line to point to the correct path. The other common place to find the ruby
executable is /usr/local/bin/ruby
.
The shebang line is ignored by Ruby – since the line begins with a hash, Ruby treats the line as a comment. Hence, you can still run the Ruby script on operating systems such as Windows whose shell does not support shebang lines.
Now, you can run your Ruby script without typing in the word ruby
. However, for security reasons, Unix-like operating systems do not search the current directory for executables unless it happens to be listed in your PATH environment variable. So you need to do one of the following:
- Create your Ruby scripts in a directory that is already in your PATH.
- Add the current directory to your PATH (not recommended).
- Specify the directory of your script each time you run it.
Most people start with #3. Running an executable Ruby script that is located in the current directory looks like this:
$ ./hello_world.rb
Once you have completed a script, it's common to create a ~/bin
directory, add this to your PATH, and move your completed script here for running on a day-to-day basis. Then, you can run your script like this:
$ hello_world.rb
Using env
If you do not want to hard-code the path to the ruby
executable, you can use the env
command in the shebang line to search for the ruby
executable in your PATH and execute it. This way, you will not need to change the shebang line on all of your Ruby scripts if you move them to a computer with Ruby installed in a different directory.
#!/usr/bin/env ruby
puts 'Hello world'
Windows
If you install the native Windows version of Ruby using the Ruby One-Click Installer, then the installer has setup Windows to automatically recognize your Ruby scripts as executables. Just type the name of the script to run it.
$ hello_world.rb Hello world
If this does not work, or if you installed Ruby in some other way, follow these steps.
- Log in as an administrator.
- Run the standard Windows "Command Prompt",
cmd
. - At the command prompt (i.e. shell prompt), run the following Windows commands. When you run
ftype
, change the command-line arguments to correctly point to where you installed theruby.exe
executable on your computer.
$ assoc .rb=RubyScript .rb=RubyScript $ ftype RubyScript="c:\ruby\bin\ruby.exe" "%1" %* RubyScript="c:\ruby\bin\ruby.exe" "%1" %*
For more help with these commands, run "help assoc
" and "help ftype
".
Basic Ruby - Strings
Like Python, Java, and the .NET Framework, Ruby has a built-in String class.
String literals
One way to create a String is to use single or double quotes inside a Ruby program to create what is called a string literal. We've already done this with our "hello world" program. A quick update to our code shows the use of both single and double quotes.
puts 'Hello world'
puts "Hello world"
Being able to use either single or double quotes is similar to Perl, but different from languages such as C and Java, which use double quotes for string literals and single quotes for single characters.
So what difference is there between single quotes and double quotes in Ruby? In the above code, there's no difference. However, consider the following code:
puts "Betty's pie shop"
puts 'Betty\'s pie shop'
Because "Betty's
" contains an apostrophe, which is the same character as the single quote, in the second line we need to use a backslash to escape the apostrophe so that Ruby understands that the apostrophe is in the string literal instead of marking the end of the string literal. The backslash followed by the single quote is called an escape sequence.
Single quotes
Single quotes only support two escape sequences.
- \' – single quote
- \\ – single backslash
Except for these two escape sequences, everything else between single quotes is treated literally.
Double quotes
Double quotes allow for many more escape sequences than single quotes. They also allow you to embed variables or Ruby code inside of a string literal – this is commonly referred to as interpolation.
puts "Enter name"
name = gets.chomp
puts "Your name is #{name}"
Escape sequences
Below are some of the more common escape sequences that can appear inside of double quotes.
- \" – double quote
- \\ – single backslash
- \a – bell/alert
- \b – backspace
- \r – carriage return
- \n – newline
- \s – space
- \t – tab
Try out this example code to better understand escape sequences.
puts "Hello\t\tworld"
puts "Hello\b\b\b\b\bGoodbye world"
puts "Hello\rStart over world"
puts "1. Hello\n2. World"
The result:
$ double-quotes.rb Hello world Goodbye world Start over world 1. Hello 2. World
Notice that the newline escape sequence (in the last line of code) simply starts a new line.
The bell character, produced by escape code \a
, is considered a control character. It does not represent a letter of the alphabet, a punctuation mark, or any other written symbol. Instead, it instructs the terminal emulator (called a console on Microsoft Windows) to "alert" the user. It is up to the terminal emulator to determine the specifics of how to respond, although a beep is fairly standard. Some terminal emulators will flash briefly.
Run the following Ruby code to check out how your terminal emulator handles the bell character.
puts "\aHello world\a"
puts
We've been using the puts
function quite a bit to print out text. Whenever puts
prints out text, it automatically prints out a newline after the text. For example, try the following code.
puts "Say", "hello", "to", "the", "world"
The result:
$ hello-world.rb Say hello to the world
In contrast, Ruby's print
function only prints out a newline if you specify one. For example, try out the following code. We include a newline at the end of print
's argument list so that the shell prompt appears on a new line, after the text.
print "Say", "hello", "to", "the", "world", "\n"
The result:
$ hello-world.rb Sayhellototheworld
The following code produces the same output, with all the words run together.
print "Say"
print "hello"
print "to"
print "the"
print "world"
print "\n"
See also
Basic Ruby - Alternate quotes
In Ruby, there's more than one way to quote a string literal. Much of this will look familiar to Perl programmers.
These alternative methods are:
- single quotes with the
%q
operator:%q(abc)
is the same as'abc'
- double quotes with the
%Q
operator:%Q(abc's)
is the same as"abc's"
Alternate single quotes
Let's say we are using single quotes to print out the following path.
puts 'c:\bus schedules\napolean\the portland bus schedule.txt'
This will result in the following output:
c:\bus schedules\napolean\the portland bus schedule.txt
The single quotes keep the \b
, \n
, and \t
from being treated as escape sequences (the same cannot be said for wikibooks' syntax highlighting).
Now let's consider the following string literal:
puts 'c:\napolean\'s bus schedules\tomorrow\'s bus schedule.txt'
This outputs:
c:\napolean's bus schedules\tomorrow's bus schedule.txt
Escaping the apostrophes makes the code less readable and makes it less obvious what will print out.
Luckily, in Ruby, there's a better way. You can use the %q
operator to apply single-quoting rules, and choose your own delimiter. This delimiter will mark the beginning and end of the string literal.
puts %q!c:\napolean's documents\tomorrow's bus schedule.txt! puts %q/c:\napolean's documents\tomorrow's bus schedule.txt/ puts %q^c:\napolean's documents\tomorrow's bus schedule.txt^ puts %q(c:\napolean's documents\tomorrow's bus schedule.txt) puts %q{c:\napolean's documents\tomorrow's bus schedule.txt} puts %q<c:\napolean's documents\tomorrow's bus schedule.txt>
Each line will print out the same text:
c:\napolean's documents\tomorrow's bus schedule.txt
You can use any punctuation you want as a delimiter, not just the ones listed in the example.
Of course, if your chosen delimiter appears inside of the string literal, then you need to escape it.
puts %q#c:\napolean's documents\tomorrow's \#9 bus schedule.txt#
If you use matching braces to delimit the text, however, you can nest braces, without escaping them.
puts %q(c:\napolean's documents\the (bus) schedule.txt) puts %q{c:\napolean's documents\the {bus} schedule.txt} puts %q<c:\napolean's documents\the <bus> schedule.txt>
Alternate double quotes
The %Q
operator (notice the case of Q in %Q
) allows you to create a string literal using double-quoting rules, but without using the double quote as a delimiter. It works much the same as the %q
operator.
print %Q^Say:\tHello world\n\tHello world\n^
print %Q(Say:\tHello world\n\tHello world\n)
Just like double quotes, you can interpolate Ruby code inside of these string literals.
name = 'Charlie Brown'
puts %Q!Say "Hello," #{name}.!
puts %Q/What is "4 plus 5"? Answer: #{4+5}/
Basic Ruby - Here documents
For creating multiple-line strings, Ruby supports here documents (heredocs), a feature that originated in the Bourne shell and is also available in Perl and PHP.
Here documents
To construct a here document, the <<
operator is followed by an identifier that marks the end of the here document. The end mark is called the terminator. The lines of text prior to the terminator are joined together, including the newlines and any other whitespace.
puts <<GROCERY_LIST
Grocery list
------------
1. Salad mix.
2. Strawberries.*
3. Cereal.
4. Milk.*
* Organic
GROCERY_LIST
The result:
Grocery list
------------
1. Salad mix.
2. Strawberries.*
3. Cereal.
4. Milk.*
* Organic
If we pass the puts
function multiple arguments, the string literal created from the here document is inserted into the argument list wherever the <<
operator appears.
In the code below, the here-document (containing the four grocery items and a blank line) is passed in as the third argument. We get the same output as above.
puts 'Grocery list', '------------', <<GROCERY_LIST, '* Organic'
1. Salad mix.
2. Strawberries.*
3. Cereal.
4. Milk.*
GROCERY_LIST
Multiple here documents
You can also have multiple here documents in an argument list. We added a blank line at the end of each here document to make the output more readable.
puts 'Produce', '-------', <<PRODUCE, 'Dairy', '-----', <<DAIRY, '* Organic'
1. Strawberries*
2. Blueberries
PRODUCE
1. Yogurt
2. Milk*
3. Cottage Cheese
DAIRY
The output after running this code is:
Produce
-------
1. Strawberries*
2. Blueberries
Dairy
-----
1. Yogurt
2. Milk*
3. Cottage Cheese
* Organic
We have been using the puts
function in our examples, but you can pass here documents to any function that accepts Strings.
Indenting
If you indent the lines inside the here document, the leading whitespace is preserved. However, there must not be any leading whitespace before the terminator.
puts 'Grocery list', '------------', <<Grocery_list
1. Salad mix.
2. Strawberries.
3. Cereal.
4. Milk.
Grocery_list
The result:
Grocery list
------------
1. Salad mix.
2. Strawberries.
3. Cereal.
4. Milk.
Indenting the terminator
If, for readability, you want to also indent the terminator, use the <<-
operator.
puts 'Grocery list', '------------', <<-GROCERY_LIST
1. Salad mix.
2. Strawberries.
3. Cereal.
4. Milk.
GROCERY_LIST
Note, however, that the whitespace before each line of text within the here document is still preserved.
Grocery list
------------
1. Salad mix.
2. Strawberries.
3. Cereal.
4. Milk.
Quoting rules
You may wonder whether here documents follow single-quoting or double-quoting rules.
Double-quoting rules
If there are no quotes around the identifier, like in our examples so far, then the body of the here document follows double-quoting rules.
name = 'Charlie Brown'
puts <<QUIZ
Student: #{name}
1.\tQuestion: What is 4+5?
\tAnswer: The sum of 4 and 5 is #{4+5}
QUIZ
The output of this example is:
Student: Charlie Brown
1.	Question: What is 4+5?
	Answer: The sum of 4 and 5 is 9
Double-quoting rules are also followed if you put double quotes around the identifier. However, do not put double quotes around the terminator.
puts <<"QUIZ"
Student: #{name}
1.\tQuestion: What is 4+5?
\tAnswer: The sum of 4 and 5 is #{4+5}
QUIZ
Single-quoting rules
To create a here document that follows single-quoting rules, place single quotes around the identifier.
puts <<'BUS_SCHEDULES'
c:\napolean's documents\tomorrow's bus schedule.txt
c:\new documents\sam spade's bus schedule.txt
c:\bus schedules\the #9 bus schedule.txt
BUS_SCHEDULES
The result:
c:\napolean's documents\tomorrow's bus schedule.txt
c:\new documents\sam spade's bus schedule.txt
c:\bus schedules\the #9 bus schedule.txt
Basic Ruby - Introduction to objects
Like Smalltalk, Ruby is a pure object-oriented language — everything is an object. In contrast, languages such as C++ and Java are hybrid languages that divide the world between objects and primitive types. The hybrid approach results in better performance for some applications, but the pure object-oriented approach is more consistent and simpler to use.
What is an object?
Using Smalltalk terminology, an object can do exactly three things.
- Hold state, including references to other objects.
- Receive a message, from both itself and other objects.
- In the course of processing a message, send messages, both to itself and to other objects.
If you don't come from Smalltalk background, it might make more sense to rephrase these rules as follows:
- An object can contain data, including references to other objects.
- An object can contain methods, which are functions that have special access to the object's data.
- An object's methods can call/run other methods/functions.
Variables and objects
Let's fire up irb
to get a better understanding of objects.
$ irb --simple-prompt >> comedian = "Stephen Colbert" => "Stephen Colbert"
In the first line, we created a String object containing the text "Stephen Colbert
". We also told Ruby to use the variable comedian
to refer to this object.
Next, we tell Ruby to also use the variable favorite_comedian
to refer to the same String object.
>> favorite_comedian = comedian => "Stephen Colbert"
Now, we have two variables that we can use to refer to the same String object — comedian
and favorite_comedian
. Since they both refer to the same object, if the object changes (as we'll see below), the change will show up when using either variable.
Methods
In Ruby, methods that end with an exclamation mark (also called a "bang") modify the object. For example, the method upcase!
changes the letters of a String to uppercase.
>> comedian.upcase! => "STEPHEN COLBERT"
Since both of the variables comedian
and favorite_comedian
point to the same String object, we can see the new, uppercase text using either variable.
>> comedian => "STEPHEN COLBERT" >> favorite_comedian => "STEPHEN COLBERT"
Methods that do not end in an exclamation point return data, but do not modify the object. For example, downcase!
modifies a String object by making all of the letters lowercase. However, downcase
returns a lowercase copy of the String, but the original string remains the same.
>> comedian.downcase => "stephen colbert" >> comedian => "STEPHEN COLBERT"
Since the original object still contains the text "STEPHEN COLBERT
", you might wonder where the new String object, with the lowercase text, went to. Well, after irb
printed out its contents, it can no longer be accessed since we did not assign a variable to keep track of it. It's essentially gone, and Ruby will dispose of it.
Reassigning a variable
But what if your favorite comedian is not Stephen Colbert? Let's point favorite_comedian
to a new object.
>> favorite_comedian = "Jon Stewart" => "Jon Stewart"
Now, each variable points to a different object.
Let's say that we change our mind again. Now, our favorite comedian is Ellen DeGeneres.
>> favorite_comedian = "Ellen DeGeneres" => "Ellen DeGeneres"
Now, no variable points to the "Jon Stewart
" String object any longer. Hence, Ruby will dispose of it.
Basic Ruby - Ruby basics
As with the rest of this tutorial, we assume some basic familiarity with programming language concepts (i.e. if statement, while loops) and also some basic understanding of object-oriented programming.
Dealing with variables
We'll deal with variables in much more depth when we talk about classes and objects. For now, let's just say your basic local variable names should start with either a lower case letter or an underscore, and should contain upper or lower case letters, numbers, and underscore characters. Global variables start with a $.
Program flow
Ruby includes a pretty standard set of looping and branching constructs: if, while and case
For example, here's if in action:
a = 10 * rand if a < 5 puts "#{a} less than 5" elsif a > 7 puts "#{a} greater than 7" else puts "Cheese sandwich!" end
[As in other languages, the rand function generates a random number between 0 and 1]
There will be plenty more time to discuss conditional statements in later chapters. The above example should be pretty clear.
Ruby also includes a negated form of if called unless which goes something like
unless a > 5 puts "a is less than or equal to 5" else puts "a is greater than 5" end
Generally speaking, Ruby keeps an if statement straight as long as the conditional (if ...) and the associated code block are on separate lines. If you have to smash everything together on one line, you'll need to place the then keyword after the conditional
if a < 5 then puts "#{a} less than 5" end if a < 5 then puts "#{a} less than 5" else puts "#{a} greater than 5" end
Note that the if statement is also an expression; its value is the last line of the block executed. Therefore, the line above could also have been written as
puts(if a < 5 then "#{a} less than 5" else "#{a} greater than 5" end)
Ruby has also adopted the syntax from Perl where if and unless statements can be used as conditional modifiers after a statement. For example
puts "#{a} less than 5" if a < 5 puts "Cheese sandwich" unless a == 4
while behaves as it does in other languages -- the code block that follows is run zero or more times, as long as the conditional is true
while a > 5 a = 10*rand end
And like if, there is also a negated version of while called until which runs the code block until the condition is true.
Finally there is the case statement which we'll just include here with a brief example. case is actually a very powerful super version of the if ... elsif... system
a = rand(11) # Outputs a random integer between 0 and 10 case a when 0..5 puts "#{a}: Low" when 6 puts "#{a}: Six" else puts "#{a}: Cheese toast!" end
There are some other interesting things going on in this example, but here the case statement is the center of attention.
Writing functions
In keeping with Ruby's all-object-oriented-all-the-time design, functions are typically referred to as methods. No difference. We'll cover methods in much more detail when we get to objects and classes. For now, basic method writing looks something like this (save the following code in a file called func1.rb):
# Demonstrate a method with func1.rb def my_function( a ) puts "Hello, #{a}" return a.length end len = my_function( "Giraffe" ) puts "My secret word is #{len} characters long"
now run the script:
$ func1.rb Hello, Giraffe My secret word is 7 characters long
Methods are defined with the def keyword, followed by the function name. As with variables, local and class methods should start with a lower case letter.
In this example, the function takes one argument (a) and returns a value. Note that the input arguments aren't typed (i.e. a need not be a string) ... this allows for great flexibility but can also cause a lot of trouble. The function also returns a single value with the return keyword. Technically this isn't necessary -- the value of the last line executed in the function is used as the return value -- but more often than not using return explicitly makes things clearer.
As with other languages, Ruby supports both default values for arguments and variable-length argument lists, both of which will be covered in due time. There's also support for code blocks, as discussed below.
Blocks
One very important concept in Ruby is the code block. It's actually not a particularly revolutionary concept -- any time you've written if ... { ... } in C or Perl you've defined a code block, but in Ruby a code block has some hidden secret powers...
Code blocks in Ruby are defined either with the keywords do..end or the curly brackets {..}
do print "I like " print "code blocks!" end { print "Me too!" }
One very powerful usage of code blocks is that methods can take one as a parameter and execute it along the way.
[ed note: the Pragmatic Programmers actually want to point out that it's not very useful to describe it this way. Instead, the block of code behaves like a 'partner' to which the function occasionally hands over control]
The concept can be hard to get the first time it's explained to you. Here's an example:
$ irb --simple-prompt >> 3.times { puts "Hi!" } Hi! Hi! Hi! => 3
Surprise! You always thought 3 was just a number, but it's actually an object (of type Fixnum) As it's an object, it has a member function times which takes a block as a parameter. The function runs the block 3 times.
Blocks can actually receive parameters, using a special notation |..|. In this case, a quick check of the documentation for times shows it will pass a single parameter into the block, indicating which loop it's on:
$ irb --simple-prompt >> 4.times { |x| puts "Loop number #{x}" } Loop number 0 Loop number 1 Loop number 2 Loop number 3 => 4
The times function passes a number into the block. The block gets that number in the variable x (as set by the |x|), then prints out the result.
Functions interact with blocks through the yield. Every time the function invokes yield control passes to the block. It only comes back to the function when the block finishes. Here's a simple example:
# Script block2.rb def simpleFunction yield yield end simpleFunction { puts "Hello!" }
$ block2.rb Hello! Hello!
The simpleFunction simply yields to the block twice -- so the block is run twice and we get two times the output. Here's an example where the function passes a parameter to the block:
# Script block1.rb def animals yield "Tiger" yield "Giraffe" end animals { |x| puts "Hello, #{x}" }
$ block1.rb Hello, Tiger Hello, Giraffe
It might take a couple of reads through to figure out what's going on here. We've defined the function "animals" -- it expects a code block. When executed, the function calls the code block twice, first with the parameter "Tiger" then again with the parameter "Giraffe". In this example, we've written a simple code block which just prints out a greeting to the animals. We could write a different block, for example:
animals { |x| puts "It's #{x.length} characters long!" }
which would give:
It's 5 characters long! It's 7 characters long!
Two completely different results from running the same function with two different blocks.
There are many powerful uses of blocks. One of the first you'll come across is the each function for arrays -- it runs a code block once for each element in the array -- it's great for iterating over lists.
Ruby is really, really object-oriented
Ruby is very object oriented. Everything is an object -- even things you might consider constants. This also means that the vast majority of what you might consider "standard functions" aren't floating around in some library somewhere, but are instead methods of a given variable.
Here's one example we've already seen:
3.times { puts "Hi!" }
Even though 3 might seem like just a constant number, it's in fact an instance of the class Fixnum (which inherits from the class Numeric which inherits from the class Object). The method times comes from Fixnum and does just what it claims to do.
Here are some other examples
$ irb --simple-prompt >> 3.abs => 3 >> -3.abs => 3 >> "giraffe".length => 7 >> a = "giraffe" => "giraffe" >> a.reverse => "effarig"
There will be lots of time to consider how object-oriented design filters through Ruby in the coming chapters.
Basic Ruby - Data types
Ruby Data Types
As mentioned in the previous chapter, everything in Ruby is an object. Ruby has 8 primary data types and 3 more data types derived from the Numeric superclass. Everything has a class. Don't believe me? Try running this bit of code:
h = {"hash?" => "yep, it\'s a hash!", "the answer to everything" => 42, :linux => "fun for coders."}
puts "Stringy string McString!".class
puts 1.class
puts 1.class.superclass
puts 1.class.superclass.superclass
puts 4.3.class
puts 4.3.class.superclass
puts nil.class
puts h.class
puts :symbol.class
puts [].class
puts (1..8).class
displays
String
Fixnum
Integer
Numeric
Float
Numeric
NilClass
Hash
Symbol
Array
Range
See? Everything is an object. Every object has a method called class that returns that object's class. You can call methods on pretty much anything. Earlier you saw an example of this in the form of 3.times
. (Technically when you call a method you're sending a message to the object, but I'll leave the significance of that for later.)
Something that makes this extreme object oriented-ness very fun for me is the fact that all classes are open, meaning you can add variables and methods to a class at any time during the execution of your code. This, however, is a discussion of datatypes.
Constants
We'll start off with constants because they're simple. Two things to remember about constants:
1. Constants start with capital letters. Constant is a constant. constant is not a constant.
2. You can change the values of constants, but Ruby will give you a warning. (Silly, I know... but what can you do?)
Congrats. Now you're an expert on Ruby constants.
Symbols
So did you notice something weird about that first code listing? "What the heck was that colon thingy about?" Well, it just so happens that Ruby's object oriented ways have a cost: lots of objects make for slow code. Every time you type a string, Ruby makes a new object. Regardless of whether two strings are identical, Ruby treats every instance as a new object. You could have "live long and prosper" in your code once and then again later on and Ruby wouldn't even realize that they're pretty much the same thing. Here is a sample irb session which demonstrates this fact:
irb> "live long and prosper".object_id
=> -507772268
irb> "live long and prosper".object_id
=> -507776538
Notice that the object ID returned by irb Ruby is different even for the same two strings.
To get around this memory hoggishness, Ruby has provided "symbols." Symbol
s are lightweight objects best used for comparisons and internal logic. If the user doesn't ever see it, why not use a symbol rather than a string? Your code will thank you for it. Let us try running the above code using symbols instead of strings:
irb> :my_symbol.object_id
=> 150808
irb> :my_symbol.object_id
=> 150808
Symbols are denoted by the colon sitting out in front of them, like so:
:symbol_name
Hashes
Hashes are like dictionaries, in a sense. You have a key, a reference, and you look it up to find the associated object, the definition.
The best way to illustrate this, I think, is with a quick demonstration:
hash = { :leia => "Princess from Alderaan", :han => "Rebel without a cause", :luke => "Farmboy turned Jedi"}
puts hash[:leia]
puts hash[:han]
puts hash[:luke]
displays
Princess from Alderaan
Rebel without a cause
Farmboy turned Jedi
I could have also written this like so:
hash = { :leia => "Princess from Alderaan", :han => "Rebel without a cause", :luke => "Farmboy turned Jedi"}
hash.each do |key, value|
puts value
end
This code cycles through each element in the hash, putting the key in the key
variable and the value in the value
variable, which is then displayed
Princess of Alderaan
Rebel without a cause
Farmboy turned Jedi
I could have been more verbose about defining my hash; I could have written it like this:
hash = Hash.[](:leia => "Princess from Alderaan", :han => "Rebel without a cause", :luke => "Farmboy turned Jedi")
hash.each do |key, value|
puts value
end
If I felt like offing Luke, I could do something like this:
hash.delete(:luke)
Now Luke's no longer in the hash. Or lets say I just had a vendetta against farmboys in general. I could do this:
hash.delete_if {|key, value| value.downcase.match("farmboy")}
This iterates through each key-value pair and deletes it, but only if the block of code following it returns true
. In the block I made the value lowercase (in case the farmboys decided to start doing stuff like "FaRmBoY!1!") and then checked to see if "farmboy" matched anything in its contents. I could have used a regular expression, but that's another story entirely.
I could add Lando into the mix by assigning a new value to the hash:
hash[:lando] = "Dashing and debonair city administrator."
I can measure the hash with hash.length
. I can look at only keys with the hash.keys
method, which returns the hash's keys as an Array
. Speaking of which...
Arrays
Array
s are a lot like Hash
es, except that the keys are always consecutive numbers, and always starts at 0. In an Array
with five items, the last element would be found at array[4]
and the first element would be found at array[0]
. In addition, all the methods that you just learned with Hash
es can also be applied to Array
s.
Here are two ways to create an Array
:
array1 = ["hello", "this", "is", "an", "array!"]
array2 = []
array2 << "This" # index 0
array2 << "is" # index 1
array2 << "also" # index 2
array2 << "an" # index 3
array2 << "array!" # index 4
As you may have guessed, the <<
operator pushes values onto the end of an Array
. If I were to write puts array2[4]
after declaring those two Array
s the output would be array!
. Of course, if I felt like simultaneously getting array!
and deleting it from the array, I could just Array.pop
it off. The Array.pop
method returns the last element in an array and then immediately removes it from that array:
string = array2.pop
Then string
would hold array!
and array2
would be an element shorter.
If I kept doing this, array2 wouldn't hold any elements. I can check for this condition by calling the Array.empty?
method. For example, the following bit of code moves all the elements from one Array
to another:
array1 << array2.pop until array2.empty?
Here's something that really excites me: Array
s can be subtracted from, and added to, each other. I can't vouch for every language that's out there, but I know that Java, C++, C# and perl would all look at me like I was a crazy person if I tried to execute the following bit of code:
array3 = array1 - array2
array4 = array1 + array2
After that code is evaluated, all of the following are true:
array3
contains all of the elements thatarray1
did, except the ones that were also inarray2
.- All the elements of
array1
, minus the elements ofarray2
, are now contained withinarray3
. array4
now contains all the elements of botharray1
andarray2
.
You may search for a particular value in variable array1
with the Array.include?
method:
array1.include?("Is this in here?")
If you just wanted to turn the whole Array
into a String
, you could:
string = array2.join(" ")
If array2 had the value that we declared in the last example, then string
's value would be
This is also an array!
We could have called the Array.join
method without any arguments:
string = array2.join
string
's value would now be
Thisisalsoanarray!
Strings
I would recommend reading the chapters on strings and alternate quotes now if you haven't already. This chapter is going to cover some pretty spiffy things with String
s and just assume that you already know the information in these two chapters.
In Ruby, there are some pretty cool built-in functions where String
s are concerned. For example, you can multiply them:
"Danger, Will Robinson!" * 5
yields
Danger, Will Robinson!Danger, Will Robinson!Danger, Will Robinson!Danger, Will Robinson!Danger, Will Robinson!
String
s may also be compared:
"a" < "b"
yields
true
The preceding evaluation is actually comparing the ASCII values of the characters. But what, I hear you ask, is the ASCII value of an given character? With ruby versions prior to 1.9 you can find the ASCII value of a character with:
puts ?A
However, With Ruby version 1.9 or later that no longer works. Instead, you can try the String.ord
method:
puts "A".ord
Either approach will display
65
which is the ASCII value of A. Simply replace A with whichever character you wish to inquire about.
To perform the opposite conversion (from 65 to A, for instance), use the Integer.chr
method:
puts 65.chr
displays
A
Concatenation works the same as most other languages: putting a +
character between two String
s will yield a new String
whose value is the same as the others, one after another:
"Hi, this is " + "a concatenated string!"
yields
Hi, this is a concatenated string!
For handling pesky String
variables without using the concatenate operator, you can use interpolation. In the following chunk of code string1
, string2
, and string3
are identical:
thing1 = "Red fish, "
thing2 = "blue fish."
string1 = thing1 + thing2 + " And so on and so forth."
string2 = "#{thing1 + thing2} And so on and so forth."
string3 = "#{thing1}#{thing2} And so on and so forth."
If you need to iterate through (that is, step through each of) the letters in a String
object, you can use the String.scan
method:
thing = "Red fish"
thing.scan(/./) {|letter| puts letter}
Displays each letter in thing
(puts automatically adds a newline after each call):
R
e
d
f
i
s
h
But what's with that weird "/./
" thing in the parameter? That, my friend, is called a regular expression. They're helpful little buggers, quite powerful, but outside the scope of this discussion. All you need to know for now is that /./
is "regex" speak for "any one character." If we had used /../
then ruby would have iterated over each group of two characters, and missed the last one since there's an odd number of characters!
Another use for regular expressions can be found with the =~ operator. You can check to see if a String
matches a regular expression using the match operator, =~
:
puts "Yeah, there's a number in this one." if "C3-P0, human-cyborg relations" =~ /[0-9]/
displays
Yeah, there's a number in this one.
The String.match
method works much the same way, except it can accept a String
as a parameter as well. This is helpful if you're getting regular expressions from a source outside the code. Here's what it looks like in action:
puts "Yep, they mentioned Jabba in this one." if "Jabba the Hutt".match("Jabba")
Alright, that's enough about regular expressions. Even though you can use regular expressions with the next two examples, we'll just use regular old String
s. Lets pretend you work at the Ministry of Truth and you need to replace a word in a String
with another word. You can try something like:
string1 = "2 + 2 = 4"
string2 = string1.sub("4", "5")
Now string2
contains 2 + 2 = 5
. But what if the String
contains lots of lies like the one you just corrected? String.sub
only replaces the first occurrence of a word! I guess you could iterate through the String
using String.match
method and a while
loop, but there's a much more efficient way to accomplish this:
winston = %q{ Down with Big Brother!
Down with Big Brother!
Down with Big Brother!
Down with Big Brother!
Down with Big Brother!}
winston.gsub("Down with", "Long live")
Big Brother would be so proud! String.gsub
is the "global substitute" function. Every occurrence of "Down with
" has now been replaced with "Long live" so now winston is only proclaiming its love for Big Brother, not its disdain thereof.
On that happy note, lets move on to Integer
s and Float
s. If you want to learn more about methods in the String
class, look at the end of this chapter for a quick reference table.
Numbers (Integers and Floats)
You can skip this paragraph if you know all the standard number operators. For those who don't, here's a crash course. + adds two numbers together. - subtracts them. / divides. * multiplies. % returns the remainder of two divided numbers.
Alright, integers are numbers with no decimal place. Floats are numbers with decimal places. 10 / 3 yields 3 because dividing two integers yields an integer. Since integers have no decimal places all you get is 3. If you tried 10.0 / 3 you would get 3.33333... If you have even one float in the mix you get a float back. Capisce?
Alright, let's get down to the fun part. Everything in Ruby is an object, let me reiterate. That means that pretty much everything has at least one method. Integers and floats are no exception. First I'll show you some integer methods.
Here we have the venerable times method. Use it whenever you want to do something more than once. Examples:
puts "I will now count to 99..."
100.times {|number| puts number}
5.times {puts "Guess what?"}
puts "I'm done!"
This will print out the numbers 0 through 99, print out Guess what? five times, then say I'm done! It's basically a simplified for loop. It's a little slower than a for loop by a few hundredths of a second or so; keep that in mind if you're ever writing Ruby code for NASA. ;-)
Alright, we're nearly done, six more methods to go. Here are three of them:
# First a visit from The Count...
1.upto(10) {|number| puts "#{number} Ruby loops, ah-ah-ah!"}
# Then a quick stop at NASA...
puts "T-minus..."
10.downto(1) {|x| puts x}
puts "Blast-off!"
# Finally we'll settle down with an obscure Schoolhouse Rock video...
5.step(50, 5) {|x| puts x}
Alright, that should make sense. In case it didn't, upto counts up from the number it's called from to the number passed in its parameter. downto does the same, except it counts down instead of up. Finally, step counts from the number its called from to the first number in its parameters by the second number in its parameters. So 5.step(25, 5) {|x| puts x} would output every multiple of five starting with five and ending at twenty-five.
Time for the last three:
string1 = 451.to_s
string2 = 98.6.to_s
int = 4.5.to_i
float = 5.to_f
to_s converts floats and integers to strings. to_i converts floats to integers. to_f converts integers to floats. There you have it. All the data types of Ruby in a nutshell. Now here's that quick reference table for string methods I promised you.
Additional String Methods
# Outputs 1585761545
"Mary J".hash
# Outputs "concatenate"
"concat" + "enate"
# Outputs "Washington"
"washington".capitalize
# Outputs "uppercase"
"UPPERCASE".downcase
# Outputs "LOWERCASE"
"lowercase".upcase
# Outputs "Henry VII"
"Henry VIII".chop
# Outputs "rorriM"
"Mirror".reverse
# Outputs 810
"All Fears".sum
# Outputs cRaZyWaTeRs
"CrAzYwAtErS".swapcase
# Outputs "Nexu" (next advances the word up one value, as if it were a number.)
"Next".next
# After this, nxt == "Neyn" (to help you understand the trippiness of next)
nxt = "Next"
20.times {nxt = nxt.next}
Basic Ruby - Writing methods
Method definition
A method definition is started with the def
keyword and ended with the end
keyword. Some programmers find the method definition notation in Ruby very similar to the one of Python.
def myMethod
end
To define a method that takes a parameter, you can put the name of the variable in parantheses after the method name. When the method is invoked, the code in the method will be run with a local variable with the name of the specified parameter.
def myMethod(msg)
puts msg
end
If you need multiple parameters you can separate them with a comma.
def myMethod(msg, person)
puts "Hi, my name is " + person + ". Some information about myself: " + msg
end
Invoking methods
You can invoke methods with or without parentheses although it can be considered bad style if you omit them, so the safe way is to always write them in the beginning until you know when it's safe to leave them away.
# With parentheses
myMethod()
# Without parentheses
myMethod
If you want to invoke a method with parameters you need to put the parameter(s) between the brackets (or if you omit them, between the invisible brackets) and separate them with commas if there are more than one.
def myMethod(a, b)
puts a + b
end
myMethod(1, 2)
myMethod 1, 2
myMethod("abc", "xyz")
You can also use the value of a variable as a parameter.
def myMethod(a)
puts "Hello " + a
end
name = "World"
myMethod(name)
Default values
Often, a method may have parameters of which many, if not all, could have clever defaults. Having to specify all of the parameters every time you invoke the method can be an inconvenience. Because of this, it's possible to define default values. This can be actually quite easily; simply assign the parameter a value in the definition. You can combine parameters with and without default values.
def myMethod(message="This is a default value")
puts message
end
myMethod()
myMethod("Where has the default value gone?")
Returning values
You often want a method to return a value. You can do so by using the return statement.
def myMethod
return "Hello"
end
puts myMethod()
However, because Ruby developers are lazy, they developed a feature that always returns the last evaluated statement (sometimes it's a bit tricky to know which one this is). Knowing this, you can turn the above example into the following:
def myMethod
"Hello"
end
puts myMethod()
Note that a return statement finishes the execution of a method. Combined with the fact that you can return without a value this is often useful to stop a method from further execution if certain conditions are met.
def myMethod
while true
puts "Because the condition of this while loop is 'true' it will run forever, right?"
return
end
end
See also
This page was only meant to give some introduction how to work with methods in Ruby because this is a very important concept. However there is a more detailed page about methods and some other cool things that weren't mentioned here.
Basic Ruby - Classes and objects
Ruby Classes
As stated before, everything in Ruby is an object. Every object has a class. To find the class of an object, simply call that object's class method. For example, try this:
puts "This is a string".class
puts 9.class
puts ["this","is","an","array"].class
puts ({:this => "is", :a => "hash"}).class
puts :symbol.class
Anyhow, you should already know this. What you don't know however, is how to make your own classes and extend Ruby's classes.
Creating Instances of a Class
An instance of a class is an object that belongs to that class. For example, "chocolate" is an instance of the String class. You already know that you can create strings, arrays, hashes, numbers, and other built-in types by simply using quotes, brackets, curly braces, etc., but you can also create them via the new method. For example, my_string = "" is the same as my_string = String.new. Almost every class has a new method: arrays, hashes, whatever. (Some classes like Integers and Numerics do not have the new
method. These classes do not allow duplicates to exist among instantiated objects.) When you create your own classes, you'll use the new method to create instances.
Creating Classes
Classes represent a type of an object, such as a book, a whale, a grape, or chocolate. Everybody likes chocolate (may not be true), so let's make a chocolate class:
class Chocolate
def eat
puts "That tasted great!"
end
end
Let's take a look at this. Classes are created via the class keyword. After that comes the name of the class. All class names must start with a Capital Letter. By convention, we use CamelCase for class name. So we would create classes like PieceOfChocolate, but not like Piece_of_Chocolate.
The next section defines a class method. A class method is a method that is defined for a particular class. For example, the String class has the length method:
# outputs "5"
puts "hello".length
To call the eat method of an instance of the Chocolate class, we would use this code:
my_chocolate = Chocolate.new
my_chocolate.eat # outputs "That tasted great!"
You can also call a method by using send
"hello".send(:length) # outputs "5"
my_chocolate.send(:eat) # outputs "That tasted great!"
However, using send is rare unless you need to create a dynamic behavior, as we do not need to specify the name of the method as a literal - it can be a variable.
Note that the typical definition of a method in Ruby starts with the keyword def.
You can, however, also use define_method() instead, and combine this with .send, to call arbitrary methods:
class Foo
self.class_eval {
define_method(:'hey there') { puts 'Hey there man!' }
}
end
foo = Foo.new
foo.send :'hey there' # => Hey there man!
Self
Inside a method of a class, the pseudo-variable self (a pseudo-variable is one that cannot be changed) refers to the current instance. For example:
class Integer
def more
return self + 1
end
end
3.more # -> 4
7.more # -> 8
Class Methods
You can also create methods that are called on a class rather than an instance. For example:
class Strawberry
def Strawberry.color
return "red"
end
def self.size
return "kinda small"
end
class << self
def shape
return "strawberry-ish"
end
end
end
Strawberry.color # -> "red"
Strawberry.size # -> "kinda small"
Strawberry.shape # -> "strawberry-ish"
Note the three different constructions: ClassName.method_name and self.method_name are essentially the same - outside of a method definition in a class block, self refers to the class itself. The latter is preferred, as it makes changing the name of the class much easier. The last construction, class << self, puts us in the context of the class's "meta-class" (sometimes called the "eigenclass"). The meta-class is a special class that the class itself belongs to. However, at this point, you don't need to worry about it. All this construct does is allow us to define methods without the self. prefix.
Basic Ruby - Exceptions
There is no exceptions chapter at present. Instead, here is a link to a chapter about exceptions from Yukihiro Matsumoto's book, Programming Ruby: The Pragmatic Programmer's Guide [2] More detail and simpler examples about exceptions, by Satish Talim, maybe found in a tutorial at RubyLearning.com [3]
Syntax - Lexicology
Identifiers
An identifier is a name used to identify a variable, method, or class.
As with most languages, valid identifiers consist of alphanumeric characters (A-Za-z0-9) and underscores (_), but may not begin with a digit (0-9). Additionally, identifiers that are method names may end with a question mark (?), exclamation point (!), or equal sign (=).
There are no arbitrary restrictions to the length of an identifier (i.e. it may be as long as you like, limited only by your computer's memory). Finally, there are reserved words which may not be used as identifiers.
Examples:
foobar ruby_is_simple
Comments
Line comments run from a bare '#' character to the end of the line. Code commenting and documentation is best implemented with Ruby Embedded Documentation. http://www.ruby-doc.org/docs/ProgrammingRuby/html/rdtool.html
Examples:
# this line does nothing; print "Hello" # this line prints "Hello"
Embedded Documentation
Example:
=begin Everything between a line beginning with `=begin' down to one beginning with `=end' will be skipped by the interpreter. These reserved words must begin in column 1. =end
Reserved Words
The following words are reserved in Ruby:
__FILE__ and def end in or self unless __LINE__ begin defined? ensure module redo super until BEGIN break do false next rescue then when END case else for nil retry true while alias class elsif if not return undef yield
You can find some examples of using them here.
Expressions
Example:
true (1 + 2) * 3 foo() if test then okay else not_good end
All variables, literals, control structures, etcetera are expressions. Using these together is called a program. You can divide expressions with newlines or semicolons (;) — however, a newline with a preceding backslash (\) is continued to the following line.
Since in Ruby control structures are expressions as well, one can do the following:
foo = case 1
when 1
true
else
false
end
The above equivalent in a language such as C would generate a syntax error since control structures are not expressions in the C language.
Syntax - Variables and Constants
A variable in Ruby can be distinguished by the characters at the start of its name. There's no restriction to the length of a variable's name (with the exception of the heap size).
Summary
The first character indicates the scope:
- Local variables - lowercase letter or underscore
- Instance variables - @
- In class scope, instance variables belong to the object that is the class
- To define instance variables on the objects that belong to the class, use @ inside initialize()
- Class variables - @@
- Global variables - $
- Constants - uppercase letter
For more information on variable scopes related to classes, see Ruby Programming/Syntax/Classes.
Local Variables
Example:
foobar _foobar
A variable whose name begins with a lowercase letter (a-z) or underscore (_) is a local variable or method invocation.
A local variable is only accessible from within the block of its initialization. For example:
i0 = 1 loop { i1 = 2 puts defined?(i0) # true; "i0" was initialized in the ascendant block puts defined?(i1) # true; "i1" was initialized in this block break } puts defined?(i0) # true; "i0 was initialized in this block puts defined?(i1) # false; "i1" was initialized in the loop
Instance Variables
Example:
@foobar
A variable whose name begins with '@' is an instance variable of self. An instance variable belongs to the object itself. Uninitialized instance variables have a value of nil.
Class Variables
A class variable is shared by all instances of a class and begins with '@@'. Example:
@@foobar
An important note is that the class variable is shared by all the descendants of the class. Example:
class Parent
@@foo = "Parent"
end
class Thing1 < Parent
@@foo = "Thing1"
end
class Thing2 < Parent
@@foo = "Thing2"
end
>>Parent.class_eval("@@foo")
=>"Thing2"
>>Thing1.class_eval("@@foo")
=>"Thing2"
>>Thing2.class_eval("@@foo")
=>"Thing2"
>>Thing2.class_variables
=>[]
Parent.class_variables
=>[:@@foo]
This shows us that all our classes were changing the same variable. Class variables behave like global variables which are visible only in the inheritance tree. Because Ruby resolves variables by looking up the inheritance tree *first*, this can cause problems if two subclasses both add a class variable with the same name.
Global Variables
Example:
$foobar
A variable whose name begins with '$' has a global scope; meaning it can be accessed from anywhere within the program during runtime.
Constants
Usage:
FOOBAR
A variable whose name begins with an uppercase letter (A-Z) is a constant. A constant can be reassigned a value after its initialization, but doing so will generate a warning. Every class is a constant.
Trying to access an uninitialized constant raises the NameError exception.
How constants are looked up
Constants are looked up based on your scope or via the scope resolution operator (i.e. '::'). For example
class A A2 = 'a2' class B def go A2 end end end instance_of_b = A::B.new a2 = A::A2
Another example
class Foo BAR = 123 end puts Foo::BAR # => 123
Pseudo Variables
self
- Execution context of the current method, which could refer to an instance, class, or module.
nil
- The sole-instance of the
NilClass
class. Expresses nothing.
true
- The sole-instance of the
TrueClass
class. Expresses true.
false
- The sole-instance of the
FalseClass
class. Expresses false.
$1, $2 ... $9
- These are contents of capturing groups for regular expression matches. They are local to the current thread and stack frame!
(nil also is considered to be false, and every other value is considered to be true in Ruby.) The value of a pseudo variable cannot be changed. Substitution to a pseudo variable causes an exception to be raised.
Pre-defined Variables
Many pre-defined variables are useful when dealing with regular expressions or Ruby interpreter parameters.
Name | Aliases | Description |
---|---|---|
$! |
$ERROR_INFO [1] |
The exception information message set by the last 'raise' (last exception thrown). |
$@ |
$ERROR_POSITION [1] |
Array of the backtrace of the last exception thrown. |
$& |
$MATCH [1] |
The string matched by the last successful pattern match in this scope. |
$` |
$PREMATCH [1] |
The string to the left of the last successful match. |
$' |
$POSTMATCH [1] |
The string to the right of the last successful match. |
$+ |
$LAST_PAREN_MATCH [1] |
The last group of the last successful match. |
$1 to $9 |
The Nth group of the last successful regexp match. | |
$~ |
$LAST_MATCH_INFO [1] |
The information about the last match in the current scope. |
$= |
$IGNORECASE [1] |
The flag for case insensitive, nil by default (deprecated). |
$/ |
$INPUT_RECORD_SEPARATOR [1], $RS [1] or $-0 |
The input record separator, newline by default. |
$\ |
$OUTPUT_RECORD_SEPARATOR [1] or $ORS [1] |
The output record separator for the print and IO#write. Default is nil. |
$, |
$OUTPUT_FIELD_SEPARATOR [1] or $OFS [1] |
The output field separator for the print and Array#join. |
$; |
$FIELD_SEPARATOR [1], $FS [1] or $-F |
The default separator for String#split. |
$. |
$INPUT_LINE_NUMBER [1] or $NR [1] |
The current input line number of the last file that was read. |
$< |
$DEFAULT_INPUT [1] |
An object that provides access to the concatenation of the contents of all the files given as command-line arguments, or $stdin (in the case where there are no arguments). Read only. |
$FILENAME |
|
Current input file from $<. Same as $<.filename. |
$> |
$DEFAULT_OUTPUT [1] |
The destination of output for Kernel.print and Kernel.printf. The default value is $stdout. |
$_ |
$LAST_READ_LINE [1] |
The last input line of string by gets or readline. |
$0 |
|
Contains the name of the script being executed. May be assignable. |
$* |
ARGV [1] |
Command line arguments given for the script. Also known as ARGV
|
$$ |
$PROCESS_ID [1], $PID [1] or Process.pid |
The process number of the Ruby running this script. |
$? |
$CHILD_STATUS [1] |
The status of the last executed child process. |
$: |
$LOAD_PATH |
Load path for scripts and binary modules by load or require. |
$" |
$LOADED_FEATURES or $-I |
The array contains the module names loaded by require. |
$stderr |
|
The current standard error output. |
$stdin |
|
The current standard input. |
$stdout |
|
The current standard output. |
$-d |
$DEBUG |
The status of the -d switch. Assignable. |
$-K |
$KCODE |
Character encoding of the source code. |
$-v |
$VERBOSE |
The verbose flag, which is set by the -v switch. |
$-a |
|
True if option -a ("autosplit" mode) is set. Read-only variable. |
$-i |
|
If in-place-edit mode is set, this variable holds the extension, otherwise nil. |
$-l |
|
True if option -l is set ("line-ending processing" is on). Read-only variable. |
$-p |
|
True if option -p is set ("loop" mode is on). Read-only variable. |
$-w |
|
True if option -w is set. |
To avoid the criticism that two-character, punctuation-based variable names are cryptic or confusing, part of the standard library is "English
" which defines the longer names listed in the table above. To include these names, just require the English library as follows.[1]
Without ‘English’:
$\ = ' -- ' "waterbuffalo" =~ /buff/ print $", $', $$, "\n"
With English:
require "English" $OUTPUT_FIELD_SEPARATOR = ' -- ' "waterbuffalo" =~ /buff/ print $LOADED_FEATURES, $POSTMATCH, $PID, "\n"
Pre-defined Constants
Note that there are some pre-defined constants at parse time, as well, namely
__FILE__ (current file) __LINE__ (current line)
and
__dir__ (current directory) __method__ (current method)
(new in Ruby 2.0)
A list of predefined global constants can be found in the Ruby language documentation.[2] Among the notable ones are:
Global constant name | Description |
---|---|
STDIN
|
The standard input. The default value for $stdin .
|
STDOUT
|
The standard output. The default value for $stdout .
|
STDERR
|
The standard error output. The default value for $stderr .
|
ENV
|
The hash contains current environment variables. |
ARGV
|
An Array of command line arguments given for the script. |
RUBY_VERSION
|
The Ruby language version, e.g., ruby -e 'puts RUBY_VERSION' will print 2.7.0 .
|
RUBY_RELEASE_DATE
|
The release date string, e.g., 2019-12-25 .
|
RUBY_PLATFORM
|
The platform identifier, e.g., x86_64-linux-gnu
|
RUBY_PATCHLEVEL
|
The patchlevel for this Ruby, e.g., 0 . If this is a development build of Ruby the patchlevel will be -1 .
|
Notes
- ↑ a b c d e f g h i j k l m n o p q r s t u v w x y z English.rb from the Ruby 1.9.2 Standard Library Documentation
- ↑ The document on pre-defined global variables and constants from the official Ruby documentation
Syntax - Literals
Numerics
123 # Fixnum -123 # Fixnum (signed) 1_123 # Fixnum (underscore is ignored) -543 # Negative Fixnum 123_456_789_123_456_789 # Bignum 123.45 # Float 1.2e-3 # Float 123.45r # Rational, introduced in ruby 2.1 0xaabb # (Hexadecimal) Fixnum 0377 # (Octal) Fixnum -0b1010 # (Binary [negated]) Fixnum 0b001_001 # (Binary) Fixnum ?a # ASCII character code for 'a' (97) ?\C-a # Control-a (1) ?\M-a # Meta-a (225) ?\M-\C-a # Meta-Control-a (129)
Note: the meaning of "?x" notation has been changed. In ruby 1.9 this means not an ASCII numeric code but a string i.e. ?a == "a"
Strings
Examples:
"this is a string" => "this is a string" "three plus three is #{3+3}" => "three plus three is 6" foobar = "blah" "the value of foobar is #{foobar}" => "the value of foobar is blah" 'the value of foobar is #{foobar}' => "the value of foobar is \#{foobar}"
A string expression begins and ends with a double or single-quote mark. Double-quoted string expressions are subject to backslash notation and interpolation. A single-quoted string expression isn't; except for \' and \\.
Backslash Notation
Also called escape characters or escape sequences, they are used to insert special characters in a string.
Example:
"this is a\ntwo line string" "this string has \"quotes\" in it"
Escape Sequence | Meaning |
\n | newline (0x0a) |
\s | space (0x20) |
\r | carriage return (0x0d) |
\t | tab (0x09) |
\v | vertical tab (0x0b) |
\f | formfeed (0x0c) |
\b | backspace (0x08) |
\a | bell/alert (0x07) |
\e | escape (0x1b) |
\nnn | character with octal value nnn |
\xnn | character with hexadecimal value nn |
\unnnn | Unicode code point U+nnnn (Ruby 1.9 and later) |
\u{nnnnn} | Unicode code point U+nnnnn with more than four hex digits must be enclosed in curly braces |
\cx | control-x |
\C-x | control-x |
\M-x | meta-x |
\M-\C-x | meta-control-x |
\x | character x itself (for example \" is the double quote character) |
For characters with decimal values, you can do this:
"" << 197 # add decimal value 197 to a string
=> Å
or embed them thus:
"#{197.chr}"
Interpolation
Interpolation allows Ruby code to appear within a string. The result of evaluating that code is inserted into the string:
"1 + 2 = #{1 + 2}" # => "1 + 2 = 3"
#{expression}
The expression can be just about any Ruby code. Ruby is pretty smart about handling string delimiters that appear in the code and it generally does what you want it to do. The code will have the same side effects as it would outside the string, including any errors:
"the meaning of life is #{1/0}" => divided by 0 (ZeroDivisionError)
The % Notation
There is also a Perl-inspired way to quote strings: by using % (percent character) and specifying a delimiting character, for example:
%{78% of statistics are "made up" on the spot} => "78% of statistics are \"made up\" on the spot"
Any single non-alpha-numeric character can be used as the delimiter, %[including these], %?or these?, %~or even these things~. By using this notation, the usual string delimiters " and ' can appear in the string unescaped, but of course the new delimiter you've chosen does need to be escaped. However, if you use %(parentheses), %[square brackets], %{curly brackets} or %<pointy brackets> as delimiters then those same delimiters can appear unescaped in the string as long as they are in balanced pairs:
%(string (syntax) is pretty flexible) => "string (syntax) is pretty flexible"
A modifier character can appear after the %, as in %q[], %Q[], %x[] - these determine how the string is interpolated and what type of object is produced:
Modifier | Meaning |
%q[ ] | Non-interpolated String (except for \\ , \[ , and \] )
|
%Q[ ] | Interpolated String (default) |
%r[ ] | Interpolated Regexp (flags can appear after the closing delimiter) |
%i[ ] | Non-interpolated Array of symbols, separated by whitespace (after Ruby 2.0) |
%I[ ] | Interpolated Array of symbols, separated by whitespace (after Ruby 2.0) |
%w[ ] | Non-interpolated Array of words, separated by whitespace |
%W[ ] | Interpolated Array of words, separated by whitespace |
%x[ ] | Interpolated shell command |
%s[ ] | Non-interpolated symbol |
Here are some more examples:
%Q{one\ntwo\n#{ 1 + 2 }} => "one\ntwo\n3" %q{one\ntwo\n#{ 1 + 2 }} => "one\\ntwo\\n#{ 1 + 2 }" %r/#{name}/i => /nemo/i %w{one two three} => ["one", "two", "three"] %i{one two three} # after Ruby 2.0 => [:one, :two, :three] %x{ruby --copyright} => "ruby - Copyright (C) 1993-2009 Yukihiro Matsumoto\n"
"Here document" notation
There is yet another way to make a string, known as a 'here document', where the delimiter itself can be any string:
string = <<END on the one ton temple bell a moon-moth, folded into sleep, sits still. END
The syntax begins with << and is followed immediately by the delimiter. To end the string, the delimiter appears alone on a line.
There is a slightly nicer way to write a here document which allows the ending delimiter to be indented by whitespace:
string = <<-FIN on the one-ton temple bell a moon-moth, folded into sleep sits still. --Taniguchi Buson, 18th century; translated by X. J. Kennedy FIN
To use non-alpha-numeric characters in the delimiter, it can be quoted:
string = <<-"." Orchid - breathing incense into butterfly's wings. --Matsuo Basho; translated by Lucien Stryk .
Here documents are interpolated, unless you use single quotes around the delimiter.
The rest of the line after the opening delimiter is not interpreted as part of the string, which means you can do this:
strings = [<<END, "short", "strings"] a long string END => ["a long string\n", "short", "strings"]
You can even "stack" multiple here documents:
string = [<<ONE, <<TWO, <<THREE] the first thing ONE the second thing TWO and the third thing THREE
=> ["the first thing\n", "the second thing\n", "and the third thing\n"]
And you can even apply methods:
s = <<END.chomp.upcase # Stripped of ending new-line and uppercased.
abc
END
=> "ABC"
Command Expansion
You can execute shell commands and run any external programs, and get the output, with backticks-quoted strings.
# Print contents of current directory, just like in console window. puts `dir` # Resolve a domain name to its IP address. domain = 'ruby-lang.org' ip = `nslookup #{domain}`.match(/\d+\.\d+\.\d+\.\d+/).to_s # => 151.101.85.178 # Download this web-page with "curl", displaying the progress, then find and print an example from it. puts `curl https://en.wikibooks.org/w/index.php?title=Ruby_Programming/Syntax/Literals`.encode('utf-8') .match(%r(<h2(?:.(?!</h2>))*Numerics.*?(?=<h2))imsu).to_s # Reducing to one section. .match(%r((?<=<pre>).*?(?=</pre>))imsu ).to_s # Reducing to an example in it.
Regular Expressions
regex_one = /chapter_\d+/i #=> /chapter_\d+/i regex_two = %r(/chapter_\d+)i #=> /\/chapter_\d+/i
Arrays
An array is a collection of objects indexed by a non-negative integer.
You can create an array object by writing Array.new
, by writing an optional
comma-separated list of values inside square brackets, or if the array will only contain string objects, a space-delimited string preceded by %w
.
array_one = Array.new array_two = [] # shorthand for Array.new array_three = ["a", "b", "c"] # array_three contains "a", "b" and "c" array_four = %w[a b c d e f g] # array_four also contains "a", "b" and "c"
array_three[0] # => "a" array_three[2] # => "c" array_four[0] # => "a" #negative indices are counted back from the end array_four[-2] # => "f" #[start, count] indexing returns an array of count objects beginning at index start array_four[1,3] # => ["b", "c", "d"] #using ranges. The end position is included with two periods but not with three array_four[0..4] # => ["a", "b", "c", "d", "e"] array_four[0...4] # => ["a", "b", "c", "d"]
The last method, using %w
, is in essence shorthand for the String
method split
when the substrings are separated by whitespace only. In the following example, the first two ways of creating an array of strings are functionally identical while the last two create very different (though both valid) arrays.
array_one = %w'apple orange pear' # => ["apple", "orange", "pear"] array_two = 'apple orange pear'.split # => ["apple", "orange", "pear"] array_one == array_two # => true
array_three = %w'dog:cat:bird' # => ["dog:cat:bird"] array_four = 'dog:cat:bird'.split(':') # => ["dog", "cat", "bird"] array_three == array_four # => false
Hashes
Hashes are basically the same as arrays, except that a hash not only contains values,
but also keys pointing to those values. Each key can occur only once in a hash. A hash object
is created by writing Hash.new
or by writing an optional list of comma-separated
key => value
pairs inside curly braces.
hash_one = Hash.new hash_two = {} # shorthand for Hash.new hash_three = {"a" => 1, "b" => 2, "c" => 3} #=> {"a"=>1, "b"=>2, "c"=>3}
Usually Symbols are used for Hash keys (allows for quicker access), so you will see hashes declared like this:
hash_sym = { :a => 1, :b => 2, :c => 3} #=> {:b=>2, :c=>3, :a=>1} hash_sym = { a: 1, b: 2, c: 3} #=> {:b=>2, :c=>3, :a=>1}
The latter form was introduced in Ruby 1.9.
Hash ordering
Note that with 1.8, iterating over hashes will iterate over the key value pairs in a "random" order. Beginning with 1.9, it will iterate over them in the order they were inserted. Note however, that if you reinsert a key without first deleting it, or change an existing key's value, the key's order in iteration does not change.
>> a = {:a => 1, :b => 2, :c => 3} => {:a=>1, :b=>2, :c=>3} >> a.keys # iterate over, show me the keys => [:a, :b, :c] >> a[:b] = 2 > a.keys => [:a, :b, :c] # same order >> a.delete(:b) >> a[:b] = 4 # re insert now => 4 >> a.keys => [:a, :c, :b] # different order
Ranges
A range represents a subset of all possible values of a type, to be more precise, all possible values between a start value and an end value.
This may be:
- All integers between 0 and 5.
- All numbers (including non-integers) between 0 and 1, excluding 1.
- All characters between 't' and 'y'.
In Ruby, these ranges are expressed by:
0..5 0.0...1.0 't'..'y'
Therefore, ranges consist of a start value, an end value, and whether the end value is included or not (in this short syntax, using two . for including and three . for excluding).
A range represents a set of values, not a sequence. Therefore,
5..0
though syntactically correct, produces a range of length zero.
Ranges can only be formed from instances of the same class or subclasses of a common parent, which must be Comparable (implementing <=>).
Ranges are instances of the Range class, and have certain methods, for example, to determine whether a value is inside a range:
r = 0..5 puts r === 4 # => true puts r === 7 # => false
For detailed information of all Range methods, consult the Range class reference.
Here is a tutorial on their use.
Syntax - Operators
Operators
Complete List and Precedence
Operator | Name/meaning | Arguments | Precedence[1] | Association |
---|---|---|---|---|
! | Boolean NOT | Unary | 1 | Right |
~ | Bitwise complement | Unary | 1 | Right |
+ | Unary plus (no effect) | Unary | 1 | Right |
** | Exponentiation | Binary | 1 | Right |
- | Unary minus (reverse sign) | Unary | 2 | Right |
* | Multiplication | Binary | 3 | Left |
/ | Division | Binary | 3 | Left |
% | Modulo (remainder) | Binary | 3 | Left |
+ | Addition or concatenation | Binary | 4 | Left |
- | Subtraction | Binary | 4 | Left |
<< | Bitwise shift left or append (<< and <<- are also used in "here doc" notation) | Binary | 5 | Left |
>> | Bitwise shift right | Binary | 5 | Left |
& | Bitwise AND | Binary | 6 | Left |
| | Bitwise OR | Binary | 7 | Left |
^ | Bitwise XOR | Binary | 7 | Left |
< | Less-than | Binary | 8 | Left |
<= | Less-than or equal-to | Binary | 8 | Left |
> | Greater-than | Binary | 8 | Left |
>= | Greater-than or equal to | Binary | 8 | Left |
== | Equal (evaluate to the same value) | Binary | 9 | N/A |
=== | "Case equality", "case subsumption" or "three equals" operator. A === B if B is a member of the set of A. Operation varies considerably depending on the data types of A and B. |
Binary | 9 | N/A |
!= | Not equal | Binary | 9 | N/A |
=~ | Pattern match | Binary | 9 | N/A |
!~ | Negative pattern match | Binary | 9 | N/A |
<=> | A <=> B evaluates to -1, 0, or 1; if A is less-than, equal-to, or greater-than B, respectively | Binary | 9 | N/A |
&& | Boolean AND | Binary | 10 | Left |
|| | Boolean OR | Binary | 11 | Left |
.. | Range creation, boolean flip-flop | Binary | 12 | N/A |
... | Open-ended range creation, boolean flip-flop | Binary | 12 | N/A |
?: | A?B:C evaluates to B if A is true, or C if A is false | Trinary | 13 | Right |
rescue | Modifier for catching exceptions e.g. array[3] rescue nil |
Binary | 14 | Left |
= | Assignment | Binary | 15 | Right |
**= | A **=B does A = A ** B | Binary | 15 | Right |
*= | A *=B does A = A * B | Binary | 15 | Right |
/= | A /=B does A = A / B | Binary | 15 | Right |
%= | A %=B does A = A % B | Binary | 15 | Right |
+= | A +=B does A = A + B | Binary | 15 | Right |
-= | A -=B does A = A – B | Binary | 15 | Right |
<<= | A <<=B does A = A << B | Binary | 15 | Right |
>>= | A >>=B does A = A >> B | Binary | 15 | Right |
&&= | A &&=B assigns B to A if A is true or not nil | Binary | 15 | Right |
&= | A &=B does A = A & B | Binary | 15 | Right |
||= | A ||=B assigns B to A if A is nil or false | Binary | 15 | Right |
|= | A |= B does A = A | B | Binary | 15 | Right |
^= | A ^=B does A = A ^ B | Binary | 15 | Right |
defined? | nil if the expression cannot be evaluated (e.g. unset variable) | Unary | 16 | N/A |
not | Boolean NOT | Unary | 17 | Right |
and | Boolean AND | Binary | 18 | Left |
or | Boolean OR | Binary | 18 | Left |
if | Conditional, e.g. print x if x |
Binary | 19 | N/A |
unless | Negative conditional, e.g. x = 0 unless x |
Binary | 19 | N/A |
while | Loop conditional, e.g. print x += 1 while (x < 10) |
Binary | 19 | N/A |
until | Loop conditional, e.g. print x += 1 until (x == 10) |
Binary | 19 | N/A |
Higher precedence (lower number in the above table) operators have their immediate arguments evaluated first. Precedence order can be altered with () blocks. For example, because *
has higher precedence than +, then:
1 + 2 * 3 == 7
(1 + 2) * 3 == 9
Association direction controls which operators have their arguments evaluated first when multiple operators with the same precedence appear in a row. For example, because -
has left association:
1 – 2 – 3 == (1 – 2) – 3 == -1 – 3 == -4
instead of:
1 – 2 – 3 == 1 – (2 – 3) == 1 - -1 == 0
Because **
has right association:
2 ** 3 ** 2 == 2 ** (3 ** 2) == 2 ** 9 == 512
instead of:
2 ** 3 ** 2 == (2 ** 3) ** 2 == 8 ** 2 == 64
{} blocks have lower precedence than the above operators, followed by do/end blocks. Array accesses with [] can be thought of as having a higher precedence than any above operator.
The operators ** through !~ can be overridden (defined for new classes, or redefined for existing operations).
Note that rescue, if, unless, while, and until are operators when used as modifiers in one-liners (as in the above examples) but can also be used as keywords.
Other operators
The dot operator .
is used for calling methods on objects, also known as passing a message to the object.
Ruby 2.3.0 introduced the safe navigation operator &.
, also known as the "lonely operator".[2] This allows replacing
x = foo && foo.bar && foo.bar.baz
with
x = foo&.bar&.baz
An equivalent .dig()
method was introduced for hashes and arrays:
hash_variable.dig(:foo, :bar, :baz)
array_variable.dig(1, 0, 2)
are safer versions of:
hash_variable[:foo][:bar][:baz]
array_variable[1][0][2]
The safe navigation operator will raise an error if a requested method, key, or index is not available; unlike the technique of using try() for this purpose, which will return nil.[3]
Yukihiro Matsumoto considered !
?.
and .?
before settling on &.
because:[4]
- ?. conflicts with *?
- ?. is used by other languages, thus .? is confusingly similar but different
- ! conflicts with "not" logic
- ? is already used by convention for functions that return booleans
- &. is reminiscent of the && syntax the operator is replacing
!!
is sometimes seen, but this is simply the !
operator twice. It is used to force the following expression to evaluate to a boolean. This technique is considered non-idiomatic and poor programming practice, because there are more explicit ways to force such a conversion (which is rarely needed to begin with).
Assignment
Assignment in Ruby is done using the equal operator "=". This is both for variables and objects, but since strings, floats, and integers are actually objects in Ruby, you're always assigning objects.
Examples:
myvar = 'myvar is now this string'
var = 321
dbconn = Mysql::new('localhost','root','password')
Self assignment
x = 1 #=>1
x += x #=>2
x -= x #=>0
x += 4 #=>x was 0 so x= + 4 # x is positive 4
x *= x #=>16
x **= x #=>18446744073709551616 # Raise to the power
x /= x #=>1
A frequent question from C and C++ types is "How do you increment a variable? Where are ++ and -- operators?" In Ruby, one should use x+=1 and x-=1 to increment or decrement a variable.
x = 'a'
x.succ! #=>"b" : succ! method is defined for String, but not for Integer types
Multiple assignments
Examples:
var1, var2, var3 = 10, 20, 30
var1 #=> 10
var2 #=> 20
var3 #=> 30
myArray=%w(John Michel Fran Doug) # %w() can be used as syntactic sugar to simplify array creation
var1,var2,var3,var4=*myArray
puts var1 #=>John
puts var4 #=>Doug
names,school=myArray,'St. Whatever'
names #=>["John", "Michel", "Fran", "Doug"]
school #=>"St. Whatever"
Conditional assignment
x = find_something() #=>nil
x ||= "default" #=>"default" : value of x will be replaced with "default", but only if x is nil or false
x ||= "other" #=>"default" : value of x is not replaced if it already is other than nil or false
Operator ||= is a shorthand form that closely resembles the expression:[5]
x = x || "default"
Operator ||= can be shorthand for code like:
x = "(some fallback value)" unless respond_to? :x or x
In same way &&= operator works:
x = get_node() #=>nil
x &&= x.next_node #=> nil : x will be set to x.next_node, but only if x is NOT nil or false
x = get_node() #=>Some Node
x &&= x.next_node #=>Next Node
Operator &&= is a shorthand form of the expression:
x && x = x.get_node()
Scope
In Ruby there's a local scope, a global scope, an instance scope, and a class scope.
Local Scope
Example:
var = 2 4.times do |x| puts x = x*var end #=> 0 2 4 6 puts x #=> undefined local variable or method `x' for main:Object (NameError)
This error appears because this x(toplevel) is not the x(local) inside the do..end block the x(local) is a local variable to the block, whereas when trying the puts x(toplevel) we're calling a x variable that is in the top level scope, and since there's not one, Ruby protests.
Global scope
$global = 0 4.times do |var| $global = $global + var puts "var #{var} global #{$global}" end #=> var 0 global 0 var 1 global 1 var 2 global 3 var 3 global 6 puts $global #=> 6
This output is given because prefixing a variable with a dollar sign makes the variable a global.
Instance scope
Within methods of a class, you can share variables by prefixing them with an @.
class A def setup @instvar = 1 end def go @instvar = @instvar*2 puts @instvar end end instance = A.new instance.setup instance.go #=> 2 instance.go #=> 4
Class scope
A class variable is one that is like a "static" variable in Java. It is shared by all instances of a class.
class A @@classvar = 1 def go @@classvar = @@classvar*2 puts @@classvar end end instance = A.new instance.go #=> 2 instance = A.new instance.go #=> 4 -- variable is shared across instances
Here's a demo showing the various types:
$variable class Test def initialize(arg1='kiwi') @instvar=arg1 @@classvar=@instvar+' told you so!!' localvar=@instvar end def print_instvar puts @instvar end def print_localvar puts @@classvar puts localvar end end var=Test.new var.print_instvar #=>"kiwi", it works because a @instance_var can be accessed inside the class var.print_localvar #=>undefined local variable or method 'localvar' for #<Test:0x2b36208 @instvar="kiwi"> (NameError).
This will print the two lines "kiwi" and "kiwi told you so!!", then fail with a undefined local variable or method 'localvar' for #<Test:0x2b36208 @instvar="kiwi"> (NameError). Why? Well, in the scope of the method print_localvar there doesn't exists localvar, it exists in method initialize(until GC kicks it out). On the other hand, class variables '@@classvar' and '@instvar' are in scope across the entire class and, in the case of @@class variables, across the children classes.
class SubTest < Test def print_classvar puts @@classvar end end newvar=SubTest.new #newvar is created and it has @@classvar with the same value as the var instance of Test!! newvar.print_classvar #=>kiwi told you so!!
Class variables have the scope of parent class AND children, these variables can live across classes, and can be affected by the children actions ;-)
class SubSubTest < Test
def print_classvar
puts @@classvar
end
def modify_classvar
@@classvar='kiwi kiwi waaai!!'
end
end
subtest=SubSubTest.new
subtest.modify_classvar #lets add a method that modifies the contents of @@classvar in SubSubTest
subtest.print_classvar
This new child of Test also has @@classvar with the original value newvar.print_classvar. The value of @@classvar has been changed to 'kiwi kiwi waaai!!' This shows that @@classvar is "shared" across parent and child classes.
Default scope
When you don't enclose your code in any scope specifier, ex:
@a = 33
it affects the default scope, which is an object called "main".
For example, if you had one script that says
@a = 33 require 'other_script.rb'
and other_script.rb says
puts @a
#=> 33
They could share variables.
Note however, that the two scripts don't share local variables.
Local scope gotchas
Typically when you are within a class, you can do as you'd like for definitions, like.
class A a = 3 if a == 3 def go 3 end else def go 4 end end end
And also, procs "bind" to their surrounding scope, like
a = 3 b = proc { a } b.call # 3 -- it remembered what a was
However, the "class" and "def" keywords cause an *entirely new* scope.
class A a = 3 def go return a # this won't work! end end
You can get around this limitation by using define_method, which takes a block and thus keeps the outer scope (note that you can use any block you want, to, too, but here's an example).
class A a = 3 define_method(:go) { a } end
Here's using an arbitrary block
a = 3 PROC = proc { a } # gotta use something besides a local # variable because that "class" makes us lose scope. class A define_method(:go, &PROC) end
or here
class A end a = 3 A.class_eval do define_method(:go) do puts a end end
Logical And
The binary "and" operator will return the logical conjunction of its two operands. It is the same as "&&" but with a lower precedence. Example:
a = 1 b = 2 c = nil puts "yay all my arguments are true" if a and b puts "oh no, one of my argument is false" if a and c
Logical Or
The binary "or" operator will return the logical disjunction of its two operands. It is the same as "||" but with a lower precedence. Example:
a = nil b = "foo" c = a || b # c is set to "foo" it's the same as saying c = (a || b) c = a or b # c is set to nil it's the same as saying (c = a) || b which is not what you want.
References
- ↑ http://ruby-doc.org/core-2.4.0/doc/syntax/precedence_rdoc.html
- ↑ https://www.ruby-lang.org/en/news/2015/12/25/ruby-2-3-0-released/
- ↑ http://blog.rubyeffect.com/ruby-2-3s-lonely-operator/
- ↑ https://bugs.ruby-lang.org/issues/11537
- ↑ http://www.rubyinside.com/what-rubys-double-pipe-or-equals-really-does-5488.html
Syntax - Control Structures
Control Structures
Conditional Branches
Ruby can control the execution of code using Conditional branches. A conditional Branch takes the result of a test expression and executes a block of code depending whether the test expression is true or false. If the test expression evaluates to the constant false
or nil
, the test is false; otherwise, it is true. Note that the number zero
is considered true, whereas many other programming languages consider it false.
In many popular programming languages, conditional branches are statements. They can affect which code is executed, but they do not result in values themselves. In Ruby, however, conditional branches are expressions. They evaluate to values, just like other expressions do. An if
expression, for example, not only determines whether a subordinate block of code will execute, but also results in a value itself. If no block is executed, the if expression results in nil. For instance, the following if
expression evaluates to 3:
if true 3 end
Ruby's conditional branches are explained below.
if expression
Examples:
a = 5 if a == 4 a = 7 end print a # prints 5 since the if-block isn't executed
You can also put the test expression and code block on the same line if you use then
:
if a == 4 then a = 7 end #or if a == 4: a = 7 end #Note that the ":" syntax for if one line blocks do not work anymore in ruby 1.9. Ternary statements still work
This is equal to:
a = 5 a = 7 if a == 4 print a # prints 5 since the if-block isn't executed
unless expression
The unless-expression is the opposite of the if-expression, the code-block it contains will only be executed if the test expression is false.
Examples:
a = 5 unless a == 4 a = 7 end print a # prints 7 since the unless-block is executed
The unless expression is almost exactly like a negated if expression:
if !expression # is equal to using unless expression
The difference is that the unless does not permit a following elsif. And there is no elsunless.
Like the if-expression you can also write:
a = 5 a = 7 unless a == 4 print a # prints 7 since the unless-block is executed
The "one-liners" are handy when the code executed in the block is one line only.
if-elsif-else expression
The elsif (note that it's elsif
and not elseif
) and else blocks give you further control of your scripts by providing the option to accommodate additional tests.
The elsif
and else
blocks are considered only if the if
test is false. You can have any number of elsif
blocks but only one if
and one else
block.
Syntax:
if expression ...code block... elsif another expression ...code block... elsif another expression ...code block... else ...code block... end
short-if expression (aka ternary operator)
The "short-if" statement provides you with a space-saving way of evaluating an expression and returning a value.
The format is:
result = (condition) ? (expression-if-true) : (expression-if-false)
It is also known as the ternary operator and it is suggested to only use this syntax for minor tasks, such as string formatting, because of poor code readability that may result.
irb(main):037:0> true ? 't' : 'f' => "t" irb(main):038:0> false ? 't' : 'f' => "f"
This is very useful when doing string concatenation among other things.
Example:
a = 5 plus_or_minus = '+' print "The number #{a}#{plus_or_minus}1 is: #{plus_or_minus == '+' ? (a+1).to_s : (a-1).to_s}."
Also, this can be written as:
result = if condition then expression-1 else expression-2 end
Assignments can be made as:
result = (value-1 if expression-1) || (value-2 if expression-2)
case expression
An alternative to the if-elsif-else expression (above) is the case expression. Case in Ruby supports a number of syntaxes. For example, suppose we want to determine the relationship of a number (given by the variable a) to 5. We could say:
a = 1 case when a < 5 then puts "#{a} is less than 5" when a == 5 then puts "#{a} equals 5" when a > 5 then puts "#{a} is greater than 5" end
Note that, as with if, the comparison operator is ==. The assignment operator is =. Though Ruby will accept the assignment operator:
when a = 5 then puts "#{a} equals 5" # WARNING! This code CHANGES the value of a!
this is not what we want! Here, we want the comparison operator.
A more concise syntax for case is to imply the comparison:
case a when 0..4 then puts "#{a} is less than 5" when 5 then puts "#{a} equals 5" when 5..10 then puts "#{a} is greater than 5" else puts "unexpected value #{a} " # Just in case "a" is bigger than 10 or negative. end
Note: because the ranges are explicitly stated, it is a good coding practice to handle unexpected values of a. This concise syntax is perhaps most useful when we know in advance what values to expect. For example:
a = "apple" case a when "vanilla" then "a spice" when "spinach" then "a vegetable" when "apple" then "a fruit" else "an unexpected value" end
If entered into IRB this gives:
=> "a fruit"
Other ways to use case and variations on its syntax may be seen at Linuxtopia Ruby Programming [4]
Loops
while
The while
statement in Ruby is very similar to if
and to other languages' while
(syntactically):
while <expression> <...code block...> end
The code block will be executed again and again, as long as the expression evaluates to true
.
Also, like if
and unless
, the following is possible:
<...code...> while <expression>
Note the following strange case works...
line = readline.chomp while line != "what I'm looking for"
So if local variable line
has no existence prior to this line, on seeing it for the first time it has the value nil
when the loop expression is first evaluated.
until
The until
statement is similar to the while
statement in functionality. Unlike the while
statement, the code block for the until
loop will execute as long as the expression evaluates to false
.
until <expression> <...code block...> end
Keywords
return
return value
causes the method in which it appears to exit at that point and return the value specified.
Note that if a method has no return statement then the value of the last statement is implicitly returned.
Syntax - Method Calls
A method in Ruby is a set of expressions that returns a value. With methods, one can organize their code into subroutines that can be easily invoked from other areas of their program. Other languages sometimes refer to this as a function. A method may be defined as a part of a class or separately.
Method Calls
Methods are called using the following syntax:
method_name(parameter1, parameter2,…)
With or without parameters, Ruby allows method calls without parentheses:
method_name
results = method_name parameter1, parameter2
Parentheses are needed to chain method calls; for example:
results = method_name(parameter1, parameter2).reverse
Method Definitions
Methods are defined using the keyword def
followed by the method name.
Method parameters are specified between parentheses following the method name. The method body is enclosed by this definition on the top and the word end
on the bottom. By convention method names that consist of multiple words have each word separated by an underscore.
Example:
def output_something(value)
puts value
end
Return Values
Methods return the value of the last statement executed. The following code returns the value x+y
.
def calculate_value(x,y)
x + y
end
An explicit return statement can also be used to return from function with a value, prior to the end of the function declaration. This is useful when you want to terminate a loop or return from a function as the result of a conditional expression.
Note, if you use "return" within a block, you actually will jump out from the function, probably not what you want. To terminate block, use break. You can pass a value to break which will be returned as the result of the block:
six = (1..10).each {|i| break i if i > 5}
In this case, six will have the value 6.
Default Values
A default parameter value can be specified during method definition to replace the value of a parameter if it is not passed into the method.
def some_method(value='default', arr=[])
puts value
puts arr.length
end
some_method('something')
The method call above will output:
something
0
The following is a syntax error in Ruby 1.8
def foo( i = 7, j ) # Syntax error in Ruby 1.8.7 Unexpected ')', expecting '='
return i + j
end
The above code will work in 1.9.2 and will be logically equivalent to the snippet below
def foo( j, i = 7)
return i + j
end
Variable Length Argument List, Asterisk Operator
The last parameter of a method may be preceded by an asterisk(*), which is sometimes called the 'splat' operator. This indicates that more parameters may be passed to the function. Those parameters are collected up and an array is created.
def calculate_value(x,y,*otherValues)
puts otherValues
end
calculate_value(1,2,'a','b','c')
In the example above the output would be ['a', 'b', 'c'].
The asterisk operator may also precede an Array argument in a method call. In this case the Array will be expanded and the values passed in as if they were separated by commas.
arr = ['a','b','c']
calculate_value(*arr)
has the same result as:
calculate_value('a','b','c')
Another technique that Ruby allows is to give a Hash when invoking a function, and that gives you best of all worlds: named parameters, and variable argument length.
def accepts_hash( var )
print "got: ", var.inspect # will print out what it received
end
accepts_hash :arg1 => 'giving arg1', :argN => 'giving argN'
# => got: {:argN=>"giving argN", :arg1=>"giving arg1"}
You see, the arguments for accepts_hash got rolled up into one hash variable. This technique is heavily used in the Ruby On Rails API.
Also note the missing parenthesis around the arguments for the accepts_hash function call, and notice that there is no { } Hash declaration syntax around the :arg1 => '...' code, either. The above code is equivalent to the more verbose:
accepts_hash( :arg1 => 'giving arg1', :argN => 'giving argN' ) # argument list enclosed in parens
accepts_hash( { :arg1 => 'giving arg1', :argN => 'giving argN' } ) # hash is explicitly created
Now, if you are going to pass a code block to function, you need parentheses.
accepts_hash( :arg1 => 'giving arg1', :argN => 'giving argN' ) { |s| puts s }
accepts_hash( { :arg1 => 'giving arg1', :argN => 'giving argN' } ) { |s| puts s }
# second line is more verbose, hash explicitly created, but essentially the same as above
In versions of Ruby since Ruby 2.0, it is also possible to use the new built-in keyword arguments that make above technique somewhat easier. The new syntax is as follows:
def test_method(a, b, c:true, d:false)
puts a,b,c,d
end
Above function can now be called as test_method(1,2), test_method(1,2, c: somevalue), test_method(1,2, d:someothervalue), test_method(1,2, c:somevalue, d:someothervalue) or even test_method(1,2, d: someothervalue, c: somevalue) . In this example, parentheses are again not required unless you want to chain the result to another function or method right away. Note that this does mean that you 'have' to pass on names for (in this case) the 'c' and 'd' values you pass into the function, whenever you want to include them Calling the method like test_method(1,2,3,4) will not work.
Keyword Arguments are especially helpful whenever there is a lot of non-required options that might be passed into a function. Specifying the names whenever they are used makes the resulting function calls very readable.
The Ampersand Operator
Much like the asterisk, the ampersand(&) may precede the last parameter of a function declaration. This indicates that the function expects a code block to be passed in. A Proc object will be created and assigned to the parameter containing the block passed in.
Also similar to the ampersand operator, a Proc object preceded by an ampersand during a method call will be replaced by the block that it contains. Yield
may then be used.
def method_call
yield
end
method_call(&someBlock)
Understanding blocks, Procs and methods
Introduction
Ruby provides the programmer with a set of very powerful features borrowed from the domain of functional programming, namely closures, higher-order functions, and first-class functions [1]. These features are implemented in Ruby by means of code blocks, Proc objects, and methods (that are also objects)—concepts that are closely related and yet differ in subtle ways. In fact, I found myself quite confused about this topic, having difficulty understanding the difference between blocks, procs, and methods as well as unsure about the best practices of using them. Additionally, having some background in Lisp and years of Perl experience, I was unsure of how the Ruby concepts map to similar idioms from other programming languages like Lisp’s functions and Perl’s subroutines. Sifting through hundreds of newsgroup posts, I saw that I am not the only one with this problem and, in fact, quite a lot of “Ruby Nubies” struggle with the same ideas.
In this article I lay out my understanding of this facet of Ruby, which comes as a result of extensive research of Ruby books, documentation, and comp.lang.ruby, in sincere hope that other people will find it useful as well.
Procs
Shamelessly ripping from the Ruby documentation, Procs are defined as follows: Proc objects are blocks of code that have been bound to a set of local variables. Once bound, the code may be called in different contexts and still access those variables.
A useful example is also provided:
def gen_times(factor)
return Proc.new {|n| n*factor }
end
times3 = gen_times(3) # 'factor' is replaced with 3
times5 = gen_times(5)
times3.call(12) #=> 36
times5.call(5) #=> 25
times3.call(times5.call(4)) #=> 60
Procs play the role of functions in Ruby. It is more accurate to call them function objects, since like everything in Ruby they are objects. Such objects have a name in the folklore - functors. A functor is defined as an object to be invoked or called as if it were an ordinary function, usually with the same syntax, which is exactly what a Proc is.
On Wikipedia, a closure is defined as a function that refers to free variables in its lexical context. From the example and the previous definitions, it is obvious that Ruby Procs can also act as closures. Note how closely it maps to the Ruby definition blocks of code that have been bound to a set of local variables.
More on Procs
Procs in Ruby are first-class objects, since they can be created during runtime, stored in data structures, passed as arguments to other functions and returned as the value of other functions. Actually, the gen_times example demonstrates all of these criteria, except for “passed as arguments to other functions”. This one can be presented as follows:
def foo (a, b)
a.call(b)
end
putser = Proc.new {|x| puts x}
foo(putser, 34)
There is also a shorthand notation for creating Procs - the Kernel method lambda [2] (we’ll come to methods shortly, but for now assume that a Kernel method is something akin to a global function, which can be called from anywhere in the code). Using lambda the Proc object creation from the previous example can be rewritten as:
putser = lambda {|x| puts x}
Actually, there are two slight differences between lambda and Proc.new. First, argument checking. The Ruby documentation for lambda states: Equivalent to Proc.new, except the resulting Proc objects check the number of parameters passed when called. Here is an example to demonstrate this:
pnew = Proc.new {|x, y| puts x + y}
lamb = lambda {|x, y| puts x + y}
# works fine, printing 6
pnew.call(2, 4, 11)
# throws an ArgumentError
lamb.call(2, 4, 11)
Second, there is a difference in the way returns are handled from the Proc. A return from Proc.new returns from the enclosing method (acting just like a return from a block, more on this later):
def try_ret_procnew
ret = Proc.new { return "Baaam" }
ret.call
"This is not reached"
end
# prints "Baaam"
puts try_ret_procnew
While return from lambda acts more conventionally, returning to its caller:
def try_ret_lambda
ret = lambda { return "Baaam" }
ret.call
"This is printed"
end
# prints "This is printed"
puts try_ret_lambda
With this in light, I would recommend using lambda instead of Proc.new, unless the behavior of the latter is strictly required. In addition to being a whopping two characters shorter, its behavior is less surprising.
Methods
Simply put, a method is also a block of code. However, unlike Procs, methods are not bound to the local variables around them. Rather, they are bound to some object and have access to its instance variables [3]:
class Boogy
def initialize
@id = 15
end
def arbo
puts "The id is #{@id}"
end
end
# initializes an instance of Boogy
b = Boogy.new
b.arbo
# prints "The id is 15"
A useful idiom when thinking about methods is that you are sending messages to the object that the method is defined for. Given a receiver - an object that has some method defined - we send it a message, which contains the name of the method, and optionally provides the arguments that the method would receive. In the example above, calling the method arbo without any arguments, is akin to sending a message with just “arbo” as the argument.
Ruby supports the message sending idiom more directly, by including the send method in class Object (which is the parent of all objects in Ruby). So the following three lines are equivalent to the arbo method call:
# method is called on the object, with no arguments
b.arbo
# method/message name is given as a string
b.send("arbo")
# method/message name is given as a symbol
b.send(:arbo)
Note that methods can also be defined in the so-called “top-level” scope, which is not inside any user-defined class. For example:
def say (something)
puts something
end
say "Hello"
While it seems that the method say is “free-standing”, it is not - Ruby silently tucks it into the Object class, which represents the scope of your application:
def say (something)
puts something
end
say "Hello"
Object.send(:say, "Hello") # this will be the same as the above line
But this doesn’t really matter, and for all practical purposes say can be seen as an independent method. Which is, by the way, just what’s called a “function” in some languages (like C and Perl). The following Proc is, in many ways similar:
say = lambda {|something| puts something}
say.call("Hello")
# same effect
say["Hello"]
The [] construct is a synonym to call in the context of Proc [4]. Methods, however, are more versatile than procs and support a very important feature of Ruby, which I will present right after explaining what blocks are.
Blocks
Blocks are so closely related to Procs that it gives many newbies a headache trying to decipher how they actually differ. I will try to ease on comprehension with a (hopefully not too corny) metaphor. Blocks, as I see them, are unborn Procs. Blocks are the larval, Procs are the insects. A block does not live on its own - it prepares the code for when it will actually become alive, and only when it is bound and converted to a Proc, it starts living:
# a naked block can't live in Ruby
# this is a compilation error !
{puts "hello"}
# now it's alive, having been converted
# to a Proc !
pr = lambda {puts "hello"}
pr.call
Is that it, is that what all the fuss is about, then ? No, not at all. The designer of Ruby, Matz saw that while passing Procs to methods (and other Procs) is nice and allows high-level functions and all kinds of fancy functional stuff, there is one common case that stands high above all other cases - passing a single block of code to a method that makes something useful out of it, for example iteration. And as a very talented designer, Matz decided that it is worthwhile to emphasize this special case, and make it both simpler and more efficient.
Passing a block to a method
No doubt that any programmer who has spent at least a couple of hours with Ruby has been shown the following examples of Ruby glory (or something very similar):
10.times do |i|
print "#{i} "
end
numbers = [1, 2, 5, 6, 9, 21]
numbers.each do |x|
puts "#{x} is " + (x >= 3 ? "many" : "few")
end
squares = numbers.map {|x| x * x}
(Note that do |x| ... end
is equivalent to { |x| ... }
.)
Such code is, in my opinion, the part of what makes Ruby the clean, readable, and wonderful language it is. What happens here behind the scenes is quite simple, or at least may be depicted in a very simple way. Perhaps Ruby may not implement it exactly the way I am going to describe it, since there are optimization considerations surely playing their role, but it is definitely close enough to the truth to serve as a metaphor for understanding.
Whenever a block is appended to a method call, Ruby automatically converts it to a Proc object but one without an explicit name. The method, however, has a way to access this Proc, by means of the yield statement. See the following example for clarification:
def do_twice
yield
yield
end
do_twice {puts "Hola"}
The method do_twice is defined and called with an attached block. Although the method did not explicitly ask for the block in its arguments list, the yield can call the block. This can be implemented in a more explicit way using a Proc argument:
def do_twice(what)
what.call
what.call
end
do_twice lambda {puts "Hola"}
This is equivalent to the previous example but using blocks with yield is cleaner and better optimized since only one block is passed to the method. Using the Proc approach, any amount of code blocks can be passed:
def do_twice(what1, what2, what3)
2.times do
what1.call
what2.call
what3.call
end
end
do_twice( lambda {print "Hola, "},
lambda {print "querido "},
lambda {print "amigo\n"})
This is important to note that many people frown at passing blocks and prefer explicit Procs instead. Their rationale is that a block argument is implicit and one has to look through the whole code of the method to see if there are any calls to yield there, while a Proc is explicit and can be immediately spotted in the argument list. While this is simply a matter of taste, understanding both approaches is vital.
The ampersand (&)
The ampersand operator can be used to explicitly convert between blocks and Procs in a couple of cases. It is worthy to understand how these work.
Remember how I said that although an attached block is converted to a Proc under the hood, it is not accessible as a Proc from inside the method ? Well, if an ampersand is prepended to the last argument in the argument list of a method, the block attached to this method is converted to a Proc object and gets assigned to that last argument:
def contrived(a, &f)
# the block can be accessed through f
f.call(a)
# but yield also works !
yield(a)
end
# this works
contrived(25) {|x| puts x}
# this raises ArgumentError, because &f
# isn't really an argument - it's only there
# to convert a block
contrived(25, lambda {|x| puts x})
Another (IMHO far more efficacious) use of the ampersand is the other-way conversion - converting a Proc into a block. This is very useful because many of Ruby’s great built-ins, and especially the iterators, expect to receive a block as an argument, and sometimes it’s much more convenient to pass them a Proc. The following example is taken right from the excellent “Programming Ruby” book by the pragmatic programmers:
print "(t)imes or (p)lus: "
times = gets
print "number: "
number = Integer(gets)
if times =~ /^t/
calc = lambda {|n| n*number }
else
calc = lambda {|n| n+number }
end
puts((1..10).collect(&calc).join(", "))
The collect method expects a block, but in this case it is very convenient to provide it with a Proc, since the Proc is constructed using knowledge gained from the user. The ampersand preceding calc makes sure that the Proc object calc is turned into a code block and is passed to collect as an attached block.
The ampersand also allows the implementation of a very common idiom among Ruby programmers: passing method names into iterators. Assume that I want to convert all words in an Array to upper case. I could do it like this:
words = %w(Jane, aara, multiko)
upcase_words = words.map {|x| x.upcase}
p upcase_words
This is nice, and it works, but I feel it’s a little bit too verbose. The upcase method itself should be given to map, without the need for a separate block and the apparently superfluous x argument. Fortunately, as we saw before, Ruby supports the idiom of sending messages to objects, and methods can be referred to by their names, which are implemented as Ruby Symbols. For example:
p "Erik".send(:upcase)
This, quite literally, says send the message/method upcase to the object “Erik”. This feature can be utilized to implement the map {|x| x.upcase} in an elegant manner, and we’re going to use the ampersand for this! As I said, when the ampersand is prepended to some Proc in a method call, it converts the Proc to a block. But what if we prepend it not to a Proc, but to another object? Then, Ruby’s implicit type conversion rules kick in, and the to_proc method is called on the object to try and make a Proc out of it. We can use this to implement to_proc for Symbol and achieve what we want:
class Symbol
# A generalized conversion of a method name
# to a proc that runs this method.
#
def to_proc
lambda {|x, *args| x.send(self, *args)}
end
end
# Voilà !
words = %w(Jane, aara, multiko)
upcase_words = words.map(&:upcase)
Dynamic methods
You can define a method on "just one object" in Ruby.
a = 'b'
def a.some_method
'within a singleton method just for a'
end
>> a.some_method
=> 'within a singleton method just for a'
Or you can use define_(singleton_)method, which preserves the scope around the definition, as well.
a = 'b'
a.define_singleton_method(:some_method) {
'within a block method'
}
a.some_method
Special methods
Ruby has a number of special methods that are called by the interpreter. For example:
class Chameleon
alias __inspect__ inspect
def method_missing(method, *arg)
if (method.to_s)[0..2] == "to_"
@identity = __inspect__.sub("Chameleon", method.to_s.sub('to_','').capitalize)
def inspect
@identity
end
self
else
super #method_missing overrides the default Kernel.method_missing
#pass on anything we weren't looking for so the Chameleon stays unnoticed and uneaten ;)
end
end
end
mrlizard = Chameleon.new
mrlizard.to_rock
This does something silly but method_missing
is an important part of meta-programming in Ruby. In Ruby on Rails it is used extensively to create methods dynamically.
Another special method is initialize
that ruby calls whenever a class instance is created, but that belongs in the next chapter: Classes.
Conclusion
Ruby doesn’t really have functions. Rather, it has two slightly different concepts - methods and Procs (which are, as we have seen, simply what other languages call function objects, or functors). Both are blocks of code - methods are bound to Objects, and Procs are bound to the local variables in scope. Their uses are quite different.
Methods are the cornerstone of object-oriented programming, and since Ruby is a pure-OO language (everything is an object), methods are inherent to the nature of Ruby. Methods are the actions Ruby objects do - the messages they receive, if you prefer the message sending idiom.
Procs make powerful functional programming paradigms possible, turning code into a first-class object of Ruby allowing to implement high-order functions. They are very close kin to Lisp’s lambda forms (there’s little doubt about the origin of Ruby’s Proc constructor lambda)
The construct of a block may at first be confusing, but it turns out to be quite simple. A block is, as my metaphor goes, an unborn Proc - it is a Proc in an intermediate state, not bound to anything yet. I think that the simplest way to think about blocks in Ruby, without losing any comprehension, would be to think that blocks are really a form of Procs, and not a separate concept. The only time when we have to think of blocks as slightly different from Procs is the special case when they are passed as the last argument to a method which may then access them using yield.
That’s about it, I guess. I know for sure that the research I conducted for this article cleared many misunderstandings I had about the concepts presented here. I hope others will learn from it as well. If you see anything you don’t agree with - from glaring errors to small inaccuracies, feel free to amend the book.
Notes
[1] It seems that in the pure, theoretical interpretation what Ruby has isn’t first-class functions per se. However, as this article demonstrates, Ruby is perfectly capable of fulfilling most of the requirements for first-class functions, namely that functions can be created during the execution of a program, stored in data structures, passed as arguments to other functions, and returned as the values of other functions.
[2] lambda has a synonym - proc, which is considered ‘mildly deprecated’ (mainly because proc and Proc.new are slightly different, which is confusing). In other words, just use lambda.
[3] These are ‘instance methods’. Ruby also supports ‘class methods’, and ‘class variables’, but that is not what this article is about.
[4] Or more accurately, call and [] both refer to the same method of class Proc. Yes, Proc objects themselves have methods!
Syntax - Classes
Classes are the basic templates from which object instances are created. A class is made up of a collection of variables representing internal state and methods providing behaviours that operate on that state.
Class Definition
Classes are defined in Ruby using the class
keyword followed by a name. The name must begin with a capital letter and by convention names that contain more than one word are run together with each word capitalized and no separating characters (CamelCase). The class definition may contain method, class variable, and instance variable declarations as well as calls to methods that execute in the class context at read time, such as attr_accessor. The class declaration is terminated by the end
keyword.
Example:
class MyClass
def some_method
end
end
Instance Variables
Instance variables are created for each class instance and are accessible only within that instance. They are accessed using the @ operator. Outside of the class definition, the value of an instance variable can only be read or modified via that instance's public methods.
Example:
class MyClass
@one = 1
def do_something
@one = 2
end
def output
puts @one
end
end
instance = MyClass.new
instance.output
instance.do_something
instance.output
Surprisingly, this outputs:
nil 2
This happens (nil in the first output line) because @one defined below class MyClass is an instance variable belonging to the class object (note this is not the same as a class variable and could not be referred to as @@one), whereas @one defined inside the do_something method is an instance variable belonging to instances of MyClass. They are two distinct variables and the first is accessible only in a class method.
Accessor Methods
As noted in the previous section, an instance variable can only be directly accessed or modified within an instance method definition. If you want to provide access to it from outside, you need to define public accessor methods, for example
class MyClass
def initialize
@foo = 28
end
def foo
return @foo
end
def foo=(value)
@foo = value
end
end
instance = MyClass.new
puts instance.foo
instance.foo = 496
puts instance.foo
Note that ruby provides a bit of syntactic sugar to make it look like you are getting and setting a variable directly; under the hood
a = instance.foo
instance.foo = b
are calls to the foo and foo= methods
a = instance.foo()
instance.foo=(b)
Since this is such a common use case, there is also a convenience method to autogenerate these getters and setters:
class MyClass
attr_accessor :foo
def initialize
@foo = 28
end
end
instance = MyClass.new
puts instance.foo
instance.foo = 496
puts instance.foo
does the same thing as the above program. The attr_accessor method is run at read time, when ruby is constructing the class object, and it generates the foo and foo= methods.
However, there is no requirement for the accessor methods to simply transparently access the instance variable. For example, we could ensure that all values are rounded before being stored in foo:
class MyClass
def initialize
@foo = 28
end
def foo
return @foo
end
def foo=(value)
@foo = value.round
end
end
instance = MyClass.new
puts instance.foo
instance.foo = 496.2
puts instance.foo #=> 496
Class Variables
Class variables are accessed using the @@ operator. These variables are associated with the class hierarchy rather than any object instance of the class and are the same across all object instances. (These are similar to class "static" variables in Java or C++).
Example:
class MyClass
@@value = 1
def add_one
@@value= @@value + 1
end
def value
@@value
end
end
instanceOne = MyClass.new
instanceTwo = MyClass.new
puts instanceOne.value
instanceOne.add_one
puts instanceOne.value
puts instanceTwo.value
Outputs:
1 2 2
Class Instance Variables
Classes can have instance variables. This gives each class a variable that is not shared by other classes in the inheritance chain.
class Employee
class << self; attr_accessor :instances; end
def store
self.class.instances ||= []
self.class.instances << self
end
def initialize name
@name = name
end
end
class Overhead < Employee; end
class Programmer < Employee; end
Overhead.new('Martin').store
Overhead.new('Roy').store
Programmer.new('Erik').store
puts Overhead.instances.size # => 2
puts Programmer.instances.size # => 1
For more details, see MF Bliki: ClassInstanceVariables
Class Methods
Class methods are declared the same way as normal methods, except that they are prefixed by self
, or the class name, followed by a period. These methods are executed at the Class level and may be called without an object instance. They cannot access instance variables but do have access to class variables.
Example:
class MyClass
def self.some_method
puts 'something'
end
end
MyClass.some_method
Outputs:
something
Instantiation
An object instance is created from a class through the process called instantiation. In Ruby this takes place through the Class method new
.
Example:
anObject = MyClass.new(parameters)
This function sets up the object in memory and then delegates control to the initialize function of the class if it is present. Parameters passed to the new function are passed into the initialize
function.
class MyClass
def initialize(parameters)
end
end
Declaring Visibility
By default, all methods in Ruby classes are public - accessible by anyone. There are, nonetheless, only two exceptions for this rule: the global methods defined under the Object class, and the initialize method for any class. Both of them are implicitly private.
If desired, the access for methods can be restricted by public, private, protected object methods.
It is interesting that these are not actually keywords, but actual methods that operate on the class, dynamically altering the visibility of the methods, and as a result, these 'keywords' influence the visibility of all following declarations until a new visibility is set or the end of the declaration-body is reached.
Private
Simple example:
class Example
def methodA
end
private # all following methods in this class are private, so are inaccessible to outside objects
def methodP
end
end
If private is invoked without arguments, it sets access to private for all subsequent methods. It can also be invoked with named arguments.
Named private method example:
class Example
def methodA
end
def methodP
end
private :methodP
end
Here private
was invoked with an argument, and set the visibility of methodP
to private.
Note that class methods---those declared using def ClassName.method_name
---must be set to private using the private_class_method
function.
A common usage of private_class_method
is to make the constructor method new
inaccessible, forcing access to an object through some getter function. A typical Singleton implementation is an obvious example:
class SingletonLike
private_class_method :new
def SingletonLike.create(*args, &block)
@@inst = new(*args, &block) unless @@inst
return @@inst
end
end
The following is another popular way to write the same declaration:
class SingletonLike
private_class_method :new
def SingletonLike.create(*args, &block)
@@inst ||= new(*args, &block)
end
end
Whereas private
means "private to this class" in C++, it means "private to this instance" in Ruby. This means that C++ allows access to the private methods of any object in a given class by any code which is also in that class. In Ruby, on the other hand, private methods are local to the instantiated objects to which they belong.
The fact that private
methods cannot be called with explicit receivers is illustrated by the following code.
class AccessPrivate
def a
end
private :a # a is private method
def accessing_private
a # sure!
self.a # nope! private methods cannot be called with an explicit receiver, even if that receiver is "self"
other_object.a # nope, a is private, so you can't get it (but if it was protected, you could!)
end
end
Here, other_object
is the "receiver" that method a
is invoked on. For private methods, it does not work. However, that is what "protected" visibility will allow.
Public
The default visibility level for a method is "public", and this visibility level can be manually specified using the public
method.
I am not sure why this is specified - maybe for completeness, maybe so that you could dynamically make some method private at some point, and later - public.
In Ruby, visibility is completely dynamic. You can change method visibility at runtime!
Protected
Now, “protected” deserves more discussion. Those of you coming from Java or C++ have learned that in those languages, if a method is “private”, its visibility is restricted to the declaring class, and if the method is “protected”, it will be accessible to children of the class (classes that inherit from parent) or other classes in that package.
In Ruby, “private” visibility is similar to what “protected” is in Java. Private methods in Ruby are accessible from children. You can’t have truly private methods in Ruby; you can’t completely hide a method.
The difference between protected and private is subtle. If a method is protected, it may be called by any instance of the defining class or its subclasses. If a method is private, it may be called only within the context of the calling object---it is never possible to access another object instance's private methods directly, even if the object is of the same class as the caller. For protected methods, they are accessible from objects of the same class (or children).
So, from within an object "a1" (an instance of Class A), you can call private methods only for instance of "a1" (self). And you cannot call private methods of object "a2" (that also is of class A) - they are private to a2. But you can call protected methods of object "a2" since objects a1 and a2 are both of class A.
Ruby FAQ gives following example - implementing an operator that compares one internal variable with a variable from the same class (for purposes of comparing the objects):
def <=>(other)
self.age <=> other.age
end
If age is private, this method will not work, because other.age is not accessible. If "age" is protected, this will work fine, because self and other are of same class, and can access each other's protected methods.
To think of this, protected actually reminds me of the "internal" accessibility modifier in C# or "default" accessibility in Java (when no accessibility keword is set on method or variable): method is accessible just as "public", but only for classes inside the same package.
Instance Variables
Note that object instance variables are not really private, you just can't see them. To access an instance variable, you need to create a getter and setter.
Like this (no, don't do this by hand! See below):
class GotAccessor
def initialize(size)
@size = size
end
def size
@size
end
def size=(val)
@size = val
end
end
# you could access the @size variable as
# a = GotAccessor.new(5)
# x = a.size
# a.size = y
Luckily, we have special functions to do just that: attr_accessor, attr_reader, attr_writer. attr_accessor will give you get/set functionality, reader will give only getter and writer will give only setter.
Now reduced to:
class GotAccessor
def initialize(size)
@size = size
end
attr_accessor :size
end
# attr_accessor generates variable @size accessor methods automatically:
# a = GotAccessor.new(5)
# x = a.size
# a.size = y
Inheritance
A class can inherit functionality and variables from a superclass, sometimes referred to as a parent class or base class. Ruby does not support multiple inheritance and so a class in Ruby can have only one superclass. The syntax is as follows:
class ParentClass
def a_method
puts 'b'
end
end
class SomeClass < ParentClass # < means inherit (or "extends" if you are from Java background)
def another_method
puts 'a'
end
end
instance = SomeClass.new
instance.another_method
instance.a_method
Outputs:
a b
All non-private variables and methods are inherited by the child class from the superclass.
If your class overrides a method from parent class (superclass), you still can access the parent's method by using 'super' keyword.
class ParentClass
def a_method
puts 'b'
end
end
class SomeClass < ParentClass
def a_method
super
puts 'a'
end
end
instance = SomeClass.new
instance.a_method
Outputs:
b a
(because a_method also did invoke the method from parent class).
If you have a deep inheritance line, and still want to access some parent class (superclass) methods directly, you can't. super only gets you a direct parent's method. But there is a workaround! When inheriting from a class, you can alias parent class method to a different name. Then you can access methods by alias.
class X
def foo
"hello"
end
end
class Y < X
alias xFoo foo
def foo
xFoo + "y"
end
end
class Z < Y
def foo
xFoo + "z"
end
end
puts X.new.foo
puts Y.new.foo
puts Z.new.foo
Outputs
hello helloy helloz
Mixing in Modules
First, you need to read up on modules Ruby modules. Modules are a way of grouping together some functions and variables and classes, somewhat like classes, but more like namespaces. So a module is not really a class. You can't instantiate a Module, and a module cannot use Self to refer to itself. Modules can have module methods (as classes can have class methods) and instances methods as well.
We can, though, include the module into a class. Mix it in, so to speak.
module A
def a1
puts 'a1 is called'
end
end
module B
def b1
puts 'b1 is called'
end
end
module C
def c1
puts 'c1 is called'
end
end
class Test
include A
include B
include C
def display
puts 'Modules are included'
end
end
object=Test.new
object.display
object.a1
object.b1
object.c1
Outputs:
Modules are included
a1 is called
b1 is called
c1 is called
Modules can be mixed into classes in a few different ways. Before diving into this section, it's important to understand the way that objects resolve messages into method names.
Include
module A
def a1
puts "a1 from module"
end
end
class Test
include A
def a1
puts "a1 from class"
end
end
test = Test.new
test.a1
Outputs:
a1 from class
When using include the methods provided by the class are searched before the methods provided by the module. This means that the method from the class will be found first and executed.
Prepend
module A
def a1
puts "a1 from module"
end
end
class Test
prepend A
def a1
puts "a1 from class"
end
end
test = Test.new
test.a1
Outputs:
a1 from module
When using prepend the methods provided by the module are searched before the methods provided by the class. This means that the method from the prepended module will be found first and executed.
The code shows Multiple Inheritance using modules.
Ruby Class Meta-Model
In keeping with the Ruby principle that everything is an object, classes are themselves instances of the class Class. They are stored in constants under the scope of the module in which they are declared. A call to a method on an object instance is delegated to a variable inside the object that contains a reference to the class of that object. The method implementation exists on the Class instance object itself. Class methods are implemented on meta-classes that are linked to the existing class instance objects in the same way that those classes instances are linked to them. These meta-classes are hidden from most Ruby functions.
Syntax - Hooks
Ruby provides callbacks, to, for example, know when a new method is defined (later) in a class.
Here is a list of known callbacks.
const_missing
class Object def self.const_missing c p 'missing const was', c end end
or more
class Object class << self alias :const_missing_old :const_missing def const_missing c p 'const missing is', c const_missing_old c end end end
See also some rdoc documentation on the various keywords.
References
Built-In Functions
By default many methods are available. You can see the available ones by running methods
in an irb session, ex:
>> class A; end >> A.instance_methods [:nil?, :===, :=~, :!~, :eql?, :class, :clone, :dup, :taint, :tainted?, :untaint, :untrust, :untrusted?, :trust, :freeze, :frozen?, :to_s, :inspect, :methods, :singleton_methods, :protected_methods, :private_methods, :public_methods, :instance_variables, :instance_variable_get, :instance_variable_set, :instance_variable_defined?, :instance_of?, :kind_of?, :is_a?, :tap, :send, :public_send, :respond_to?, :extend, :display, :method, :public_method, :define_singleton_method, :hash, :__id__, :object_id, :to_enum, :enum_for, :gem, :==, :equal?, :!, :!=, :instance_eval, :instance_exec, :__send__]
You can see where most of those methods are defined by inspecting the object hierarchy:
>> A.ancestors => [A, Object, Kernel, BasicObject]
1.9 introduced a few more has __method__
(the current method name), as well as require_relative
, which requires a file relative to the dir of the current file.
To see where each methods was defined, you can run something like:
>> A.instance_methods.map{|m| [m, A.instance_method(m).owner] } => [[:nil?, Kernel], ...
Predefined Variables
Ruby's predefined (built-in) variables affect the behavior of the entire program, so their use in libraries isn't recommended.
The values in most predefined variables can be accessed by alternative means.
$!
- The last exception object raised. The exception object can also be accessed using => in rescue clause.
$@
- The stack backtrace for the last exception raised. The stack backtrace information can retrieved by Exception#backtrace method of the last exception.
$/
- The input record separator (newline by default). gets, readline, etc., take their input record separator as optional argument.
$\
- The output record separator (nil by default).
$,
- The output separator between the arguments to print and Array#join (nil by default). You can specify separator explicitly to Array#join.
$;
- The default separator for split (nil by default). You can specify separator explicitly for String#split.
$.
- The number of the last line read from the current input file. Equivalent to ARGF.lineno.
$<
- Synonym for ARGF.
$>
- Synonym for $defout.
$0
- The name of the current Ruby program being executed.
$$
- The process.pid of the current Ruby program being executed.
$?
- The exit status of the last process terminated.
$:
- Synonym for $LOAD_PATH.
$DEBUG
- True if the -d or --debug command-line option is specified.
$defout
- The destination output for print and printf ($stdout by default).
$F
- The variable that receives the output from split when -a is specified. This variable is set if the -a command-line option is specified along with the -p or -n option.
$FILENAME
- The name of the file currently being read from ARGF. Equivalent to ARGF.filename.
$LOAD_PATH
- An array holding the directories to be searched when loading files with the load and require methods.
$SAFE
- The security level.
0 No checks are performed on externally supplied (tainted) data. (default) 1 Potentially dangerous operations using tainted data are forbidden. 2 Potentially dangerous operations on processes and files are forbidden. 3 All newly created objects are considered tainted. 4 Modification of global data is forbidden.
$stdin
- Standard input (STDIN by default).
$stdout
- Standard output (STDOUT by default).
$stderr
- Standard error (STDERR by default).
$VERBOSE
- True if the -v, -w, or --verbose command-line option is specified.
$- x
- The value of interpreter option -x (x=0, a, d, F, i, K, l, p, v).
The following are local variables:
$_
- The last string read by gets or readline in the current scope.
$~
- MatchData relating to the last match. Regex#match method returns the last match information.
The following variables hold values that change in accordance with the current value of $~ and can't receive assignment:
$ n ($1, $2, $3...)
- The string matched in the nth group of the last pattern match. Equivalent to m[n], where m is a MatchData object.
$&
- The string matched in the last pattern match. Equivalent to m[0], where m is a MatchData object.
$`
- The string preceding the match in the last pattern match. Equivalent to m.pre_match, where m is a MatchData object.
$'
- The string following the match in the last pattern match. Equivalent to m.post_match, where m is a MatchData object.
$+
- The string corresponding to the last successfully matched group in the last pattern match.
Predefined Classes
In ruby even the base types (also predefined classes) can be hacked.[5] In the following example, 5 is an immediate,[6] a literal, an object, and an instance of Fixnum.
class Fixnum
alias other_s to_s
def to_s()
a = self + 5
return a.other_s
end
end
a = 5
puts a.class ## prints Fixnum
puts a ## prints 10 (adds 5 once)
puts 0 ## prints 5 (adds 5 once)
puts 5 ## prints 10 (adds 5 once)
puts 10 + 0 ## prints 15 (adds 5 once)
b = 5+5
puts b ## puts 15 (adds 5 once)
Footnotes
- ^ Which means the 4 VALUE bytes are not a reference but the value itself. All 5 have the same object id (which could also be achieved in other ways).
- ^ Might not always work as you would like, the base types don't have a constructor (
def initialize
), and can't have singleton methods. There are some other minor exceptions.
Objects
Object is the base class of all other classes created in Ruby. It provides the basic set of functions available to all classes, and each function can be explicitly overridden by the user.
This class provides a number of useful methods for all of the classes in Ruby.
Object inherits from BasicObject which allows creating alternate object hierarchies. Methods on object are available to all classes unless explicitly overridden.
In Ruby, everything is an Object including classes and modules. Object and BasicObject are the most low-level class.
Constants
ARGF
ARGF is a stream designed for use in scripts that process files given as command-line arguments or passed in via STDIN.
ARGV
ARGV contains the command line arguments used to run ruby with the first value containing the name of the executable.
DATA
DATA is a File that contains the data section of the executed file. To create a data section use __END__:
ENV
ENV is a Hash-like accessor for environment variables.
STDERR
Holds the original stderr
STDIN
Holds the original stdin
STDOUT
Holds the original stdout
Array
Class Methods
Method: [ ] Signature: Array[ [anObject]* ] -> anArray
Creates a new array whose elements are given between [ and ].
Array.[]( 1, 2, 3 ) -> [1,2,3] Array[ 1, 2, 3 ] -> [1,2,3] [1,2,3] -> [1,2,3]
Class
Ruby Programming/Reference/Objects/Class
Comparable
Ruby Programming/Reference/Objects/Comparable
Encoding
Encoding is basically a new concept introduced in Ruby 1.9
Strings now have "some bytes" and "some encoding" associated with them.
In 1.8, all strings were just "some bytes" (so basically treated as what BINARY/ASCII-8BIT encoding is in 1.9). You had to use helper libraries to use any m18n style stuff.
By default, when you open a file and read from it, it will read as strings with an encoding set to
Encoding.default_external
(which you can change).
This also means that it double checks the strings "a bit" for correctness on their way in.
In windows, it also has to do conversion from "\r\n" to "\n" which means that when you read a file in non-binary mode in windows, it has to first analyze the incoming string for correctness, then (second pass) convert its line endings, so it is a bit slower.
Recommend 1.9.2 for windows users loading large files, as it isn't quite as slow. Or read them as binary (File.binread or a=File.open('name', 'rb').
External links
here is one good tutorial. here is another. [7] is another.
Enumerable
Enumerable
Enumerator appears in Ruby as Enumerable::Enumerator in 1.8.x and (just) Enumerator in 1.9.x.
Forms of Enumerator
There are several different ways in which an Enumerator can be used:
- As a proxy for “each”
- As a source of values from a block
- As an external iterator
1. As a proxy for “each”
This is the first way of using Enumerator, introduced in ruby 1.8. It solves the following problem: Enumerable methods like #map and #select call #each on your object, but what if you want to iterate using some other method such as #each_byte or #each_with_index?
An Enumerator is a simple proxy object which takes a call to #each and redirects it to a different method on the underlying object.
require 'enumerator' # needed in ruby <= 1.8.6 only src = "hello" puts src.enum_for(:each_byte).map { |b| "%02x" % b }.join(" ")
The call to ‘enum_for’ (or equivalently ‘to_enum’) creates the Enumerator proxy. It is a shorthand for the following:
newsrc = Enumerable::Enumerator.new(src, :each_byte) puts newsrc.map { |b| "%02x" % b }.join(" ")
In ruby 1.9, Enumerable::Enumerator has changed to just Enumerator
2. As a source of values from a block
In ruby 1.9, Enumerator.new can instead take a block which is executed when #each is called, and directly yields the values.
block = Enumerator.new {|g| g.yield 1; g.yield 2; g.yield 3} block.each do |item| puts item end
“g << 1” is an alternative syntax for “g.yield 1”
No fancy language features such as Fiber or Continuation are used, and this form of Enumerator is easily retro-fitted to ruby 1.8
It is quite similar to creating your own object which yields values:
block = Object.new def block.each yield 1; yield 2; yield 3 end block.each do |item| puts item end
However it also lays the groundwork for “lazy” evaluation of enumerables, described later.
3. As an external iterator
ruby 1.9 also allows you turn an Enumerator around so that it becomes a “pull” source of values, sometimes known as “external iteration”. Look carefully at the difference between this and the previous example:
block = Enumerator.new {|g| g.yield 1; g.yield 2; g.yield 3} while item = block.next puts item end
The flow of control switches back and forth, and the first time you call #next a Fiber is created which holds the state between calls. Therefore it is less efficient that iterating directly using #each.
When you call #next and there are no more values, a StopIteration exception is thrown. This is silently caught by the while loop. StopIteration is a subclass of IndexError which is a subclass of StandardError.
The nearest equivalent feature in ruby 1.8 is Generator, which was implemented using Continuations.
require 'generator' block = Generator.new {|g| g.yield 1; g.yield 2; g.yield 3} while block.next? puts block.next end
Lazy evaluation
In an Enumerator with a block, the target being yielded to is passed as an explicit parameter. This makes it possible to set up a chain of method calls so that each value is passed left-to-right along the whole chain, rather than building up intermediate arrays of values at each step.
The basic pattern is an Enumerator with a block which processes input values and yields (zero or more) output values for each one.
Enumerator.new do |y| source.each do |input| # filter INPUT ... y.yield output # filter OUTPUT end end
So let’s wrap this in a convenience method:
class Enumerator def defer(&blk) self.class.new do |y| each do |*input| blk.call(y, *input) end end end end
This new method ‘defer’ can be used as a ‘lazy’ form of both select and map. Rather than building an array of values and returning that array at the end, it immediately yields each value. This means you start getting the answers sooner, and it will work with huge or even infinite lists. Example:
res = (1..1_000_000_000).to_enum. defer { |out,inp| out.yield inp if inp % 2 == 0 }. # like select defer { |out,inp| out.yield inp+100 }. # like map take(10) p res
Although we start with a list of a billion items, at the end we only use the first 10 values generated, so we stop iterating once this has been done.
You can get the same capability in ruby 1.8 using the facets library. For convenience it also provides a Denumberable module with lazy versions of familiar Enumerable methods such as map, select and reject.
Methods which return Enumerators
From 1.8.7 on, many Enumerable methods will return an Enumerator if not given a block.
>> a = ["foo","bar","baz"] => ["foo", "bar", "baz"] >> b = a.each_with_index => #<Enumerable::Enumerator:0xb7d7cadc> >> b.each { |args| p args } ["foo", 0] ["bar", 1] ["baz", 2] => ["foo", "bar", "baz"] >>
This means that usually you don’t need to call enum_for explicitly. The very first example on this page reduces to just:
src = "hello" puts src.each_byte.map { |b| "%02x" % b }.join(" ")
This can lead to somewhat odd behaviour for non-map like methods - when you call #each on the object later, you have to provide it with the “right sort” of block.
=> ["foo", "bar", "baz"] >> b = a.select => #<Enumerable::Enumerator:0xb7d6cfb0> >> b.each { |arg| arg < "c" } => ["bar", "baz"] >>
More Enumerator readings
- ticket 707
- enum_for in Strictly Untyped blog
- Generator in Anthony Lewis’ blog
each_with_index
each_with_index calls its block with the item and its index.
array = ['Superman','Batman','The Hulk'] array.each_with_index do |item,index| puts "#{index} -> #{item}" end # will print # 0 -> Superman # 1 -> Batman # 2 -> The Hulk
find_all
find_all returns only those items for which the called block is not false
range = 1 .. 10 # find the even numbers array = range.find_all { |item| item % 2 == 0 } # returns [2,4,6,8,10]
array = ['Superman','Batman','Catwoman','Wonder Woman'] array = array.find_all { |item| item =~ /woman/ } # returns ['Catwoman','Wonder Woman']
Exception
Exception is the superclass for exceptions
Instance Methods
backtrace
- Returns the backtrace information (from where exception occurred) as an array of strings.
exception
- Returns a clone of the exception object. This method is used by raise method.
message
- Returns the exception message.
FalseClass
The only instance of FalseClass is false.
Methods:
false & other - Logical AND, without short circuit behavior false | other - Logical OR, without short circuit behavior false ^ other - Exclusive Or (XOR)
IO - Fiber
A Fiber is a unit of concurrency (basically a manually controlled thread). It is a new construct in 1.9
1.8 basically used green threads similar, to fibers, but would pre-empt them, which 1.9 does not do.
See its description.
Several useful things have been built using fibers, like neverblock, the revactor gem, et al.
IO
The IO class is basically an abstract class that provides methods to use on streams (for example, open files, or open sockets).
Basically, you can call several different things on it.
Encoding
Note that with 1.9, each call will return you a String with an encoding set, based on either how the connection was established, ex:
a = File.new('some filename', 'rb:ASCII-8BIT') # strings from this will be read in as ASCII-8BIT b = File.new('some filename', 'r') # strings from this will be read in as whatever the Encoding.default_external is # you can change what the encoding will be a.set_encoding "UTF-8" # from now on it will read in UTF-8
gets
gets
reads exactly one line, or up to the end of the file/stream (and includes the trailing newline, if one was given). A blocking call.
recv
recv(1024)
reads up to at most 1024 bytes and returns your the String. A blocking call. Reads "" if a socket has been closed gracefully from the other end. It also has non blocking companions.
read
read
reads up to the end of the file or up to when the socket is closed. Returns any number of bytes. Blocking.
For information on how to avoid blocking, see Socket.
IO - File
File
The file class is typically used for opening and closing files, as well as a few methods like deleting them and stat'ing them.
If you want to manipulate a file, not open it, also check out the Pathname class, as well as the FileUtils class.
To create a directory you'll need to use the Dir.mkdir method.
File#chmod
Here's how to do the equivalent of "chmod u+x filename"
File.class_eval do def self.addmod(flags, filename) themode=stat(filename).mode | flags chmod(themode, filename) end end
Although there's no error checking and the return value could probably be something better (like themode).
So after defining that, your 'u+w' would be: @File.addmod(0200, 'filename')@ from http://www.ruby-forum.com/topic/196999#new
File#grep
This is actually Enumerable#grep, and I believe it just works piece-wise, like
File.each_line{|l|yield l if l=~ /whatever/ }
File.join
This is useful for combining objects that aren't (or might not be) strings into a path. See here.
IO - File::Stat
File::Stat
A File::Stat object is one that contains a file's status information.
Example:
stat = File.stat('/etc') # a File::Stat object if stat.directory? puts '/etc is a directory last modified at ' + stat.mtime.to_s end
You can also get a stat object for open file descriptors.
a = File.open('some file') a.stat # File::Stat object
IO - GC
GC
Ruby does automatic Garbage Collection.
Tuning the GC
MRI's GC is a "full mark and sweep" and is run whenever it runs out of memory slots (i.e. before adding more memory, it will sweep the existing to see if it can free up some first--if not it adds more memory). It also is triggered after GC_MALLOC_LIMIT of bytes has been allocated by extensions. Unfortunately this causes a traversal of all memory, which is typically slow. See a good description.
The GC is known to typically take 10% of cpu, but if you have a large RAM load, it could take much more.
GC can be tuned at "compile time" (MRI/KRI's < 1.9) http://blog.evanweaver.com/articles/2009/04/09/ruby-gc-tuning or can be tuned by using environment variables (REE, MRI/KRI's >= 1.9).
Some tips:
You can set the compiler variable GC_MALLOC_LIMIT to be a very high value, which causes your program to use more RAM but to traverse it much less frequently. Good for large apps, like rails.
You can use jruby/rubinius which use more sophisticated GC's.
You can use "native" libraries which store the values away so that Ruby doesn't have to keep track of them and collect them. Examples: "NArray" gem and "google_hash" gem.
To turn it off: @GC.disable@
To force it to run once: @GC.start@
Conservative
Ruby's (MRI's) GC is mark and sweep, which means it is conservative. To accomplish this, it traverses the stack, looking for any section of memory which "looks" like a reference to an existing ruby object, and marks them as live. This can lead to false positives, even when there are no references to an object remaining.
This problem is especially bad in the 1.8.x series, when they don't have the MBARI patches applied (most don't, REE does). This is because, when you use threads, it actually allocates a full copy of the stack to each thread, and as the threads are run, their stack is copied to the "real" stack, and they can pick up ghost references that belong to other threads, and also because the 1.8 MRI interpreter contains huge switch statements, which leave a lot of memory on the stack untouched, so it can continue to contain references to "ghost" references in error.
This all means that if you call a GC.start, it's not *guaranteed* to collect anything.
Some hints around this:
- If you call your code from within a method, and come *out* of that method, it might collect it more readily.
- You can do something of your own GC by using an ensure block, like
a = SomeClass.new begin ... ensure a.cleanup end
- If you write a "whole lot more" memory it might clear the stack of its old references.
Tunning Jruby's GC.
"here":http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/27550 is an example of how to tune Jruby's GC. The G1GC is theoretically a "never pause" GC, though in reality most of them are pretty good at being speedy. For long running apps you'll probably want to run in server mode (--server), for increased performance, though decreased startup time.
Rubinius is also said to have a better GC.
How to avoid performance penalty
Since MRI's GC is basically O(N) as it grows, you get a performance penalty when GC's occur and you are using a lot of RAM in your app (and MRI almost never gives its RAM back to the system). Workarounds:
- use less RAM by allocating fewer objects
- do work in a forked "child process" which returns back the values desired. The child will die, freeing up its memory.
- use Jruby et al (jruby has an excellent GC which doesn't slow things down much, even with larger apps).
- use a gem that allows for native types, like NArray or the RubyGoogle Hash.
- use REE instead of 1.8.6 (since it incorporates the MBARI patches which make the GC much more efficient).
- use 1.9.x instead of 1.8.6 (since it uses true threads there is much less reference ghosting on the stack, thus making the GC more efficient).
- set your app to restart periodically (passenger can do this).
- create multiple apps, one designed to be large and slow, the others nimble (run your GC intensive all in the large one).
- call GC.start yourself, or mix it with GC.disable
- use memprof gem to see where the leaks are occurring (or the dike gem or the like).
IO - GC - Profiler
This is a class in 1.9 MRI
GC::Profiler.enable # ... stuff GC::Profiler.report # outputs to stdout # or report = GC::Profiler.result # a is set to a verbose ascii string GC::Profiler.disable # stop it </code> Note also the existence of GC.count (number of times it has run). Note that you can get a more report by setting a compiler flag <pre>GC_PROFILE_MORE_DETAIL=1
Note that the outputs "invoke Time(sec)" is actually the sum of user cpu time until that invoke occurred—i.e. a sleep 1 will result it is increasing by 0, but a busy loop for one second will result in it increasing by 1.
Marshal
Marshal
The Marshal class is used for serializing and de-serializing objects to disk:
ex
serialized = Marshal.dump(['an', 'array', 'of', 'strings']) unserialized = Marshal.restore(serialized)
With 1.9, each dump also includes an encoding, so you *must* use Marshal's stream read feature if you wish to read it from an IO object, like a file.
a = File.open("serialized_data", "w") a.write Marshal.dump(33) b = File.open("serialized_data", "r") unserialized = Marshal.restore(b) b.close
Method
Ruby Programming/Reference/Objects/Method
Math
Ruby Programming/Reference/Objects/Math
Module
Ruby Programming/Reference/Objects/Module
Module - Class
Ruby Programming/Reference/Objects/Module/Class
NilClass
Ruby Programming/Reference/Objects/NilClass
Numeric
Numeric provides common behavior of numbers. Numeric is an abstract class, so it should not be instantiated.
Included Modules:
Comparable
Instance Methods:
+ n
Returns n.
- n
Returns n negated.
n + num
n - num
n * num
n / num
Performs arithmetic operations: addition, subtraction, multiplication, and division.
n % num
Returns the modulus of n.
n ** num
Exponentiation.
n.abs
Returns the absolute value of n.
n.ceil
Returns the smallest integer greater than or equal to n.
n.coerce( num)
Returns an array containing num and n both possibly converted to a type that allows them to be operated on mutually. Used in automatic type conversion in numeric operators. |
n.divmod( num)
Returns an array containing the quotient and modulus from dividing n by num.
n.floor
Returns the largest integer less than or equal to n. |
1.2.floor #=> 1 2.1.floor #=> 2 (-1.2).floor #=> -2 (-2.1).floor #=> -3
n.integer?
Returns true if n is an integer.
n.modulo( num)
Returns the modulus obtained by dividing n by num and rounding the quotient with floor. Equivalent to n.divmod(num)[1].
n.nonzero?
Returns n if it isn't zero, otherwise nil.
n.remainder( num)
Returns the remainder obtained by dividing n by num and removing decimals from the quotient. The result and n always have same sign. |
(13.modulo(4)) #=> 1 (13.modulo(-4)) #=> -3 ((-13).modulo(4)) #=> 3 ((-13).modulo(-4)) #=> -1 (13.remainder(4)) #=> 1 (13.remainder(-4)) #=> 1 ((-13).remainder(4)) #=> -1 (-13).remainder(-4)) #=> -1
n.round
Returns n rounded to the nearest integer.
1.2.round #=> 1 2.5.round #=> 3 (-1.2).round #=> -1 (-2.5).round #=> -3
n.truncate
Returns n as an integer with decimals removed.
1.2.truncate #=> 1 2.1.truncate #=> 2 (-1.2).truncate #=> -1 (-2.1).truncate #=> -2
n.zero?
Returns zero if n is 0.
Numeric - Integer
Integer provides common behavior of integers (Fixnum and Bignum). Integer is an abstract class, so you should not instantiate this class.
Inherited Class: Numeric Included Module: Precision
Class Methods:
Integer::induced_from(numeric)
Returns the result of converting numeric into an integer.
Instance Methods:
Bitwise operations: AND, OR, XOR, and inversion.
~i
i & int
i | int
i ^ int
i << int
i >> int
Bitwise left shift and right shift.
i[n]
Returns the value of the nth bit from the least significant bit, which is i[0].
5[0] # => 1 5[1] # => 0 5[2] # => 1
i.chr
Returns a string containing the character for the character code i.
65.chr # => "A" ?a.chr # => "a"
i.downto( min) {| i| ...}
Invokes the block, decrementing each time from i to min.
3.downto(1) {|i| puts i }
# prints: # 3 # 2 # 1
i.next
i.succ
Returns the next integer following i. Equivalent to i + 1.
i.size
Returns the number of bytes in the machine representation of i.
i.step( upto, step) {| i| ...}
Iterates the block from i to upto, incrementing by step each time.
10.step(5, -2) {|i| puts i } # prints: # 10 # 8 # 6
i.succ
See i.next
i.times {| i| ...}
Iterates the block i times.
3.times {|i| puts i } # prints: # 0 # 1 # 2
i.to_f
Converts i into a floating point number. Float conversion may lose precision information.
1234567891234567.to_f # => 1.234567891e+15
i.to_int
Returns i itself. Every object that has to_int method is treated as if it's an integer.
i.upto( max) {| i| ...}
Invokes the block, incrementing each time from i to max.
1.upto(3) {|i| puts i } # prints: # 1 # 2 # 3
Numeric - Integer - Bignum
Ruby Programming/Reference/Objects/Numeric/Integer/Bignum
Numeric - Integer - Fixnum
Ruby Programming/Reference/Objects/Numeric/Integer/Fixnum
Numeric - Float
Ruby Programming/Reference/Objects/Numeric/Float
Range
Ruby Programming/Reference/Objects/Range
Regexp
Regexp Regular Expressions
Class Regexp holds a regular expression, used to match a pattern of strings.
Regular expressions can be created using /your_regex_here/ or by using the constructor "new".
>> /a regex/ >> /a case insensitive regex/i
or use the new constructor with constants, like
>> Regexp.new('a regex') >> Regexp.new('a regex', MULTILINE)
To see all available creation options, please see the regex rdoc.
oniguruma
Starting with 1.9, ruby has a new Regular Expression engine (oniguruma), which is slightly faster and more powerful, as well as encoding aware/friendly. To see a good explanation of how it works, please see its rdoc.
Simplifying regexes
Strategy: name them, then combine them.
float = /[\d]+\.[\d]+/ complex = /[+-]#{float}\.#{float}/
Helper websites
"rubular":http://rubular.com lets you test your regexps online
Alternative Regular Expression Libraries
Some other wrappers exist:
RubyVM
RubyVM is (as noted) very VM dependent. Currently it is defined only for 1.9.x MRI.
RubyVM::InstructionSequence.disassemble
Available on 1.9 only, this is basically a wrapper for yarv.
>> class A; def go; end; end >> b = A.new.method(:go) => # >> print RubyVM::InstructionSequence.disassemble b == disasm: ======================= 0000 trace 8 ( 1) 0002 putnil 0003 trace 16 ( 1) 0005 leave
I believe those trace methods represent calls to any Kernel#set_trace_func (or the C sibling to that ruby method).
Also note that with 1.9.2 you can pass in a proc.
String
String Class
Methods:
crypt(salt). Returns an encoded string using crypt(3). salt is a string with minimal length 2. If salt starts with "$1$", MD5 encryption is used, based on up to eight characters following "$1$". Otherwise, DES is used, based on the first two characters of salt.
Struct
Struct
A structure (Struct) is a:
- data container, convenient way to bundle a number of attributes together without having to write an explicit class.
- named collection of data (set of variables) representing a single idea or object.
Inside a 'structure' there is a list of fields - example:
- Contact: first name, last name, phone, email, birthday.
- Address: street, city, state, region, postal code, GPS location/coordinates.
Structures are similar to arrays in that they contain multiple data. However, instead of an Index to each piece of data, we have a variable "name". Using the above example:
- structure (collection of data) = Contact
- first field in structure 'Contact' is 'first name'
Struct can be used without any additional require statement.
Creating a structure
In Ruby Struct.new takes a set of field names as arguments and returns a new Class.
Newtype = Struct.new(:data1, :data2)
n = Newtype.new # => <struct Newtype data1=nil, data2=nil>
Class Struct has a method new like other classes. But that method does not return an instance of Struct but rather a class which is a subclass of class Struct. Example:
pnt = Struct.new(:x, :y) # => #<Class:0x143ce50>
pnt.ancestors #=> [#<Class:0x143d6f0>, Struct, Enumerable, Object, Kernel, BasicObject]
Arguments to Struct.new are names of fields that the generated class will have. These names must be provided as Symbols.
- approach / method 1
Struct.new("Point", :x, :y) #=> Struct::Point
origin = Struct::Point.new(0,0) # #<struct Struct::Point x=0, y=0>
- approach / method 2
Structure_example = Struct.new(:filed1, :field2, :field3)
se = Structure_example.new("abc", "xyz", 123) => #<struct Structure_example filed1="abc", field2="xyz", field3=123>
Struct::new returns a new Class object, which can then be used to create specific instances of the new structure. The number of actual parameters must be less than or equal to the number of attributes defined for this class; unset parameters default to nil. Passing too many parameters will raise an ArgumentError.
Changing structure values
se[:field3] = 456
Printing structure values and members
p se => #<struct Structure_example filed1="abc", field2="xyz", field3=456>
p se.values => ["abc", "xyz", 456]
p se.members => [:field1, :field2, :field3]
Comparing structures
Customer = Struct.new(:name, :address)
joe1 = Customer.new("Joe", "adr1")
joe2 = Customer.new("Joe", "adr1")
jane = Customer.new("Jane", "adr2")
joe1 == joe2 #=> true
joe1.eql?(joe2) #=> true
joe1.equal?(joe2) #=> false
joe1 == jane #=> false
print joe1[:name], joe1["name"], joe1[0] # same result in each case - => "Joe"
Please see the rdoc for Struct. Add any further examples/tutorials here.
Struct - Struct::Tms
Ruby Programming/Reference/Objects/Struct/Struct::Tms
Symbol
A Ruby symbol is the internal representation of a name. You construct the symbol for a name by preceding the name with a colon. A particular name will always generate the same symbol, regardless of how that name is used within the program.
:Object :myVariable
Other languages call this process "interning," and call symbols "atoms."
Time
class Tuesdays
attr_accessor :time, :place
def initialize(time, place)
@time = time
@place = place
end
end
feb12 = Tuesdays.new("8:00", "Rice U.")
As for the object, it is clever let me give you some advice though. Firstly, you don't ever want to store a date or time as a string. This is always a mistake. -- though for learning purposes it works out, as in your example. In real life, simply not so. Lastly, you created a class called Tuesdays without specifying what would make it different from a class called Wednesday; that is to say the purpose is nebulous: there is nothing special about Tuesdays to a computer. If you have to use comments to differentiate Tuesdays from Wednesdays you typically fail.
class Event
def initialize( place, time=Time.new )
@place = place
case time.class.to_s
when "Array"
@time = Time.gm( *time )
when "Time"
@time = time
else
throw "invalid time type"
end
end
attr_accessor :time, :place
end
## Event at 5:00PM 2-2-2009 CST
funStart = Event.new( "evan-hodgson day", [0,0,17,2,2,2009,2,nil,false,"CST"] )
## Event now, (see time=Time.new -- the default in constructor)
rightNow = Event.new( "NOW!" );
## You can compaire Event#time to any Time object!!
if Time.new > funStart.time
puts "We're there"
else
puts "Not yet"
end
## Because the constructor takes two forms of time, you can do
## Event.new( "Right now", Time.gm(stuff here) )
Thread
Thread
The Thread class in Ruby is a wrapper/helper for manipulating threads (starting them, checking for status, storing thread local variables).
Here is a good tutorial.
Note that with MRI 1.8, Ruby used "green threads" (pseudo threads--really single threaded). With 1.9, MRI uses "native threads with a global interpeter lock" so "typically single threaded". Jruby uses true concurrent threads. IronRuby uses true concurrent threads. Rubinius has threading currently like MRI 1.9. See here for a good background.
Because 1.8 uses green threads this means that, for windows, any "C" call (like gets, puts, etc.) will block all other threads until it returns. The scheduler can only switch from thread to thread when it is running ruby code. However, you can run sub processes in a thread and it will work, and you can run select and it will still be able to switch among threads. For Linux this means that you can select on $stdin and thus not block for input. For windows, though, you're really stuck. Any keyboard input will block all other threads. With 1.9 this isn't as much of a problem because of the use of native threads (the thread doing the IO call releases its hold on the GIL until the IO call returns). You can use Jruby[1] for a non blocking 1.8.
With 1.9 you can get "around" the global thread lock by wrapping a C call in rb_thread_blocking_region (this will basically allow that thread to "go off and do its thing" while the other ruby threads still operate, one at a time. When the method returns, it will enter ruby land again and be one of the "globally locked" (one at a time) threads).
Thread local variables
If you want to start a thread with a specific parameter that is unique to that thread, you could use Thread.current
Thread.new { puts Thread.current # unique! }
Or you can start it with a parameter, like
th = Thread.new(33) {|parameter| thread_unique_parameter = parameter }
This avoids concurrency issues when starting threads, for example
# BROKEN for x in [1,2,3] do Thread.new { puts x # probably always outputs 3 because x's value changes due to the outside scope } end
Joining on multiple threads
For this one, use the ThreadsWait class.
require 'thwait' ThreadsWait.join_all(th1, th2, th3) do |th_that_just_exited| # could also call it like join_all([th1, th2, ...]) puts 'thread just exited', th_that_just_exited end # at this point they will all be done
Controlling Concurrency
See the Mutex class for how to control interaction between threads.
TrueClass
The only instance of TrueClass is true.
Methods:
true & other - Logical AND, without short circuit behavior true | other - Logical OR, without short circuit behavior true ^ other - Logical exclusive Or (XOR)