SCRIPTING IN RUBY
Amber Bennett
CSC 415
Dr. Lyle
HISTORY
The scripting language Ruby was created in Japan by a man named Yukihiro “Matz” Matsumoto. According to Matsumoto, “Ruby is simple in appearance, but is very complex inside, just like our human body (Ruby: A Programmer's Best Friend).” It was initially released in 1995 for public use. In 2006, the language was accepted by the masses resulting in active user groups and conferences devoted to the Ruby language(Ruby: A Programmer's Best Friend). In An Interview with the Creator of Ruby, Matsumoto speaks about how impressed he was with scripting languages and “their power and possibilities.” Unable to find the object-oriented support he desired in current languages, he set out to create his own scripting language. The language was gradually growing popular in Japan during its first release in 1996, however, as of 2001 the language was still fairly new to non-Japanese people. The first English documentation of the language was created in 1997, but there wasn’t any publicizing in English until 1998 when the ruby-talk mailing list was started. Now, there are many books written about Ruby, including Ruby in a Nutshell written by Matsumoto himself (Y. Matsumoto).
OVERVIEW
Names, Bindings, and Scopes
In Ruby, variable names can consist of numbers or letters and any combination of the two; however they must start with a letter or an underscore. Unlike other languages, names in Ruby are very descriptive, making the language extremely readable (Gamble, Carneiro Jr. and Barazi). Class names in Ruby must be capitalized and variable names are begun with lowercase letters (Aerts and Law), so there is case sensitivity in the language. Ruby has class variables that exist in the scope of a class and instance variables that are unique to a given instance of a class. Constants in Ruby don’t change throughout the execution of a program. Constants can be reassigned, but the interpreter will give you a warning by doing so (Gamble, Carneiro Jr. and Barazi).
Blocks introduce a new scope for local variables. These variables, appearing first in the block, are local to that block. This new scope can also refer local variables of an outer scope unless that scope is introduced by class, module, or def. (Y. Matsumoto)
Data Types
Ruby is a dynamically-typed language, meaning type checks are performed at run time for the most part(Robbes, Röthlisberger and Tanter). Variable types are determined by the first character(s) of the variable. For example, class variables would start with @@ and instance variables would start with @. Constants begin with a capital letter, but generally you would write constant variables in all uppercase letters. Constants can also be reassigned. Local variables start with lowercase letters. These variables are used in the methods or blocks that they are defined in and nowhere else.(Gamble, Carneiro Jr. and Barazi)
A string variable is anything, including numbers, that is surrounded by quotation marks and numbers without quotation marks around them are interpreted as a number data type.(Gamble, Carneiro Jr. and Barazi)
Strings can be surrounded by single or double quotes. The difference between the two is that strings surrounded by double quotes can include substitutions. For example:
“The time is #{Time.now}”
would print out
“The time is 2014-05-23 07:26:12 +0000”
whereas
‘The time is #{Time.now}’
would print out
“The time is \#{Time.now}”
Conventionally, programmers only use double quotes when using string interpolation or if the string includes single quotes. Using the pound symbol (#) as seen above with curly braces let’s the interpreter know that it should be evaluating anything between the braces. There are many methods that a programmer needs when dealing with string manipulation, including concatenation and case-changing operations such as “downcase”, “upcase”, and “capitalize”.(Gamble, Carneiro Jr. and Barazi)
One data type Ruby has that most other languages do not use is symbols. Symbols begin with a colon and are similar to strings except that symbols are immutable, meaning they cannot be modified. (Gamble, Carneiro Jr. and Barazi)
Arrays and hashes are data types that are common among other languages and allow you to keep track of a lot of data at once. Arrays are defined by the [] notation and are 0 indexed, meaning the first element of the array is always referred to as 0. Hashes are defined by curly braces in the format
hash_name = { :key1 => “value1”, :key2 => “value2” }
Hashes are different from arrays in that items are stored using a key, which are generally symbols, but any object can be a key.(Gamble, Carneiro Jr. and Barazi)
Abstract Data Types are provided through classes in Ruby. Classes are dynamic because you are able to add members to the class at any time; even predefined classes can be extended. The dynamic classes add flexibility to the language, but sacrifices a little of the readability. (Sebesta)
Expressions and Assignment Statements
The book Introduction to the Ruby Language provides a great table that shows operators. The writers give the information as follows:
[] []=Assignment
* / % + **Arithmetic
<= => < >Comparison
.. …Range
& ^ |AND, exclusive OR, regular OR (bitwise)
|| & not or andLogical operators
They also mention a ternary operator that can be used for “if-else-end” in the form:
expression ? value_if_true : value_if_false
A special operator, “defined?” determines whether an expression has been defined or not. If the expression is not defined, then it will return “nil”. If the expression is a defined variable, then “local-variable”, “global-variable”, etc. will be returned. If a method is defined then “method” is returned; if a method exists which can be called with super, then “super” is returned; and if a code block has been passed, then “yield” is returned.(Y. Matsumoto)
Statement-Level Control Structures
In Ruby, it is conventional to control which methods are executed where. The location of these methods can depend on things such as computation or user input. Control structures in Ruby are terminated with the keyword “end”. (Gamble, Carneiro Jr. and Barazi) The structure for an if-statement with an “else” clause would look like the following:
if a > b then
sum = sum + a
acount = account + 1
else
sum = sum + b
bcount = bcount + 1
end
(Example taken from Concepts of Programming Languages)
In Ruby, “then” and “else” clauses do not consists of compound statements, they consist of statement sequences. Take the following two code samples:
1
if sum == 0 then
if count == 0 then
result = 0
else
result = 1
end
end
if sum == 0 then
if count == 0 then
result = 0
end
else
result = 1
end
1
(Examples taken from Concepts of Programming Languages)
In the first code sample, the first instance of “end” ends the inner if-statement, including the “then” clause. The second example, however, does not include the “then” clause. (Sebesta)
Case expressions are how Ruby handles multiple-selection constructs. Another example from Concepts of Programming Languagesshows how the case-statements are structured.
leap = case
when year % 400 == 0 then true
when year % 100 == 0 then false
else year % 4 == 0
end
This piece of code will execute and determine whether “year” is a leap year or not.(Sebesta)
One of Ruby’s most powerful features are its use of blocks. These are nameless functions that do not have to be defined first, making it easy to pass them to other functions. The use of the “sort_by” method illustrates the strength of blocks. The rules for sorting are taken by the “sort_by” method (Aerts and Law). The block is delimited by either braces or the reserved words “do” and “end” (Sebesta).
Subprograms
Ruby subprogram headers begin with “def” and are terminated with “end”. Ruby subprograms can be defined inside or outside class definitions. When they are defined outside of class definitions, they are “considered methods of the root object, ‘Object’”. These methods can be called in the same way that functions are call in C or C++. They do not require an object receiver and without it, “self” is assumed.(Sebesta)
Support for Object-Oriented Programming
Ruby is strictly object-oriented (Aerts and Law). There is especially a lot of functionality in Ruby when dealing with files because each file is treated as an object (Aerts and Law). In Matsumoto’s search to find the ideal syntax for Ruby, he looked at other languages to get ideas. He came up with the conclusion that he “wanted a scripting language that was more powerful than Perl, and more object-oriented than Python (Ruby: A Programmer's Best Friend).” A good representation of Ruby’s object oriented approach can be shown where a number can be used as an action. For example:
5.times { print “Hello world” }
This bit of code will print out the phrase “Hello world” five times as follows:
Hello world Hello world Hello world Hello world Hello world => 5
Giving methods and instance variables to all of its types was influenced by the language Smalltalk, which makes Ruby an easy language. The rules that apply to objects apply to everything in Ruby.
Since everything, including files, is treated as an object, there are some commands that can be used for dealing with files in Ruby. The following script reverses a series of lines from a file:
File.open( “gettysburg.txt”).each do |line|
putsline.chomp.reverse
end
To see an example output for this script, refer to Appendix a.
As stated before, this script will take all of the lines from the Gettysburg Address and print them out in reverse order, making the line beginning, “Four score and seven years ago…” appear at the end of the output.
Concurrency
Because Ruby is an interpreted language, there can only be logical concurrency, whether there are multiple processors or not. The programs themselves cannot make use of more than one processor.(Sebesta) Similar to Python, Ruby uses a GIL (Global Interpreter Lock) which is a locking mechanism that protects your data integrity. However, this prevents multiple threads from running at the same time. (Aimonetti)
Exception Handling and Event Handling
Ruby does provide language-level support for exception handling. If you were to attempt to open a file that did not exist, then an exception would be raised and the program would not run. Exceptions can be caught using “rescue”, a clause in the begin statement. For example
begin
f = open(path)
rescue
puts “#{path} does not exist.”
exit 1
end
EVALUATION
The Ruby language has shown to be a very readable language given that the convention is to write descriptive variable names. The language is very clean and easy to understand which gives it both readability and writability. The syntax optimizes both of these attributes.
There are also many resources online or in print that aim to teach the language in short amounts of time. Ruby-lang.org provides a tutorial called “Ruby in Twenty Minutes” which teaches the basics of Ruby. There is also an in-browser tutorial that simulates the Ruby command prompt and walks you through common commands that one would use in Ruby. This makes the language accessible to someone who wants to try Ruby, but doesn’t yet want to install it on their machine. Even Matsumoto says himself that the language was designed to be human-oriented, reducing the amount of work the programmer has to do and “[pushes] jobs back to machines” (Y. Matsumoto).
Because Ruby uses a GIL, it protects data integrity, which increases the reliability of the language. The exception handling also provides reliability because the program won’t run, assuming an unmet precondition (Y. Matsumoto).
APPENDIX
a. Line reverse example
gettysburg.txt
Four score and seven years ago our fathers brought forth on this continent a
new nation, conceived in Liberty, and dedicated to the proposition that all men
are created equal.
Now we are engaged in a great civil war, testing whether that nation, or any
nation, so conceived and so dedicated, can long endure. We are met on a great
battle-field of that war. We have come to dedicate a portion of that field, as
a final resting place for those who here gave their lives that that nation
might live. It is altogether fitting and proper that we should do this.
But, in a larger sense, we can not dedicate, we can not consecrate, we can not
hallow, this ground. The brave men, living and dead, who struggled here, have
consecrated it, far above our poor power to add or detract. The world will
little note, nor long remember what we say here, but it can never forget what
they did here. It is for us the living, rather, to be dedicated here to the
unfinished work which they who fought here have thus far so nobly advanced. It
is rather for us to be here dedicated to the great task remaining before us,
that from these honored dead we take increased devotion to that cause for which
they gave the last full measure of devotion, that we here highly resolve that
these dead shall not have died in vain, that this nation, under God, shall have
a new birth of freedom, and that government of the people, by the people, for
the people, shall not perish from the earth.
Output generated by script
the people, shall not perish from the earth.
a new birth of freedom, and that government of the people, by the people, for
these dead shall not have died in vain, that this nation, under God, shall have
they gave the last full measure of devotion, that we here highly resolve that
that from these honored dead we take increased devotion to that cause for which
is rather for us to be here dedicated to the great task remaining before us,
unfinished work which they who fought here have thus far so nobly advanced. It
they did here. It is for us the living, rather, to be dedicated here to the
little note, nor long remember what we say here, but it can never forget what
consecrated it, far above our poor power to add or detract. The world will
hallow, this ground. The brave men, living and dead, who struggled here, have
But, in a larger sense, we can not dedicate, we can not consecrate, we can not
might live. It is altogether fitting and proper that we should do this.
a final resting place for those who here gave their lives that that nation
battle-field of that war. We have come to dedicate a portion of that field, as
nation, so conceived and so dedicated, can long endure. We are met on a great
Now we are engaged in a great civil war, testing whether that nation, or any
are created equal.
new nation, conceived in Liberty, and dedicated to the proposition that all men
Four score and seven years ago our fathers brought forth on this continent a
BIBLIOGRAPHY
Aerts, Jan and Andy Law. "An introduction to scripting in Ruby for biologists." BMC Bioinformatics (2009).
Aimonetti, Matt. "Concurrency in Ruby Explained." 22 February 2011. Merbist. Blog. 20 October 2014.
Gamble, Adam, Cloves Carneiro Jr. and Rida Al Barazi. "Introduction to the Ruby Language." Gamble, Adam, Cloves Carneiro Jr. and Rida Al Barazi. Beginning Rails 4. Apress, 2013. 45-59.
Matsumoto, Yukihiro. An Interview with the Creator of Ruby Bruce Stewart. 29 November 2001. Blog.
Matsumoto, Yukiriho. Ruby in a Nutshell. O'Reilly, 2001. Textbook.
Robbes, Romain, David Röthlisberger and Éric Tanter. "Object-oriented software extensions in practice." Empirical Software Engineering (2014).
Ruby: A Programmer's Best Friend. n.d. 19 September 2014. <
Sebesta, Robert W. Concepts of Programming Languages, 10th Edition. Pearson, 2012. Textbook.
1