Sage-Code Laboratory
index<--

Ruby Syntax

Ruby is case sensitive and has similar naming rules to other languages. You can define identifiers that start with an alphabetic character or underscore. Some identifiers start with capital letters. 

Unlike Python that has mandatory indentation, in Ruby the indentation is optional. Multiple statements can be separated using symbol ";" but this symbol is not required for single line statements.

Unlike other languages that have one single convention for a block of code, Ruby has 2 kind of block statements. One is enclose by curly brackets {...} other blocks are using keywords.

When you write Ruby code you actually create scripts. These are text files with extension *.rb. Most script files start with a special comment: #! as in example below:

First script:

#!/usr/bin/ruby -w
puts "Hello, Ruby!";

You can run this script using ruby interpreter:

>ruby hello.rb

Example:

This is just a fancy "hello world" script that I will explain next:

# The Greeter class
class Greeter
  def initialize(name)
    @name = name.capitalize
  end

  def salute
    puts "Hello #{@name}!"
  end
end

# Create a new object
g = Greeter.new("world")

# Output "Hello World!"
g.salute

Homework: open live demo and run it:  hello world

Notes:

Clarification: This is how we learn Ruby in this tutorial. I will show you an example or more, that may be overwhelming at first glance. Then you execute the example once or several times on-line using  repl.it website. Analyze the output an read the notes to understand the new concepts.

Block Comments

In most languages block comments are enclosed in this notation: /* … */. In Ruby this kind of comment is not available. Instead you can use =begin ... =end notation. Block comments are sometimes called "embedded documentation". It is a good practice to use these kind of comments to explain code purpose.

Example:

=begin
This demo does absolutely nothing.
In Ruby the null statement is nil
=end

# define a subroutine that does nothing
def pass
  nil # nothing expression
end

pass # call subroutine pass one time

=begin
Also the simple semicolumn ';'
does absolutely nothing 
=end

;;;  # call null statement 3 times

Block Statement

In Ruby there are statements that encapsulate other statement in a linear block of code. These statements start with a significant code line followed by several indented statements. A block statement is closed with keyword end. In Ruby the indentation is optional, unlike Python where the indentation is mandatory.

Example:

# block statement
for x in 1..10 do
    next if x % 2 == 0
    print x," " # 1 3 5 7 9
end

Notes:

Keywords

Most keywords are English words. Some keywords are using uppercase but most of them are using only lowercase letters. Ruby has about 40 keywords that I will introduce step by step using examples.

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

Code Line

A code line, is simple put a text row ending with new line. It has a visual representation as: ΒΆ It is interpreted as (CR+LF) on Windows and (LF) on Linux. Most of editors do not show this hidden symbol.

In Ruby one statement is usually single code. However not all statement are on a single line. Sometimes one code line can have many statements separated by semicolumn (;). When a statement is too long, it can be continued on next lines.

There are two ways to break a statement in multiple code lines. Fitst, you can use backslash (\) at end of line the continue on the next line. Second, a code line that end with an operator like "+" may continue on next line. In this case the continuation operator "\" is not necessary.

Statements

A simple statement is usually on line of code that contains exressions and symbols. There are several kind of statements. The most usual form of statement is the assign statement. One larger statement called block statement can include several other simple statements.

Ruby is an imperative, object oriented language. Therefore, most statements are using a keyword to start, except the assign statement that start with an identifier.

Expressions

You should be familiar with this concept from mathematics. In Ruby you can use infix expressions. Here is a short reminder: Infix, Postfix and Prefix notations are three different but equivalent ways of writing expressions. It is easiest to demonstrate the differences by looking at examples of operators that take two operands:

  1. x + y  : Infix
  2. + x y  : Prefix
  3. x y +  : Postfix

In these expressions x, y are operands while "+" is an operator. The most simple expressions are using one single operator and one operand. For example "-4" is an expression while "4" is not an expression but a single constant literal.  "2 + 4" however is an expression even if there is no variable involved.

Usually expressions are used in statements. In Ruby stand alone expressions can exist and can represent the result of a function or method. I personally don’t like this approach, it can make the script harder to understand.

Elements

The most simple expressions are called "elements". Elements and small expressions can be combined in larger expressions. Order of execution can be controlled using operator precedence and round parenthesis. We will investigate this in our next examples.

Identifiers

An identifier is a name that we give to a syntax element. Think about identifiers like labels or tags you apply for things. Identifiers can be a sincle character or several characters up to 32. One identifier start with a letter and can contain letters, numbers and underscore (_).

Variables

A name that is given to a value that can be modified later is called a variable. Sometimes a variable can represent a memory address. In this case a variable represents a refference. In other words, variables are value identifiers. In Ruby all variable identifiers start with "$".

Constants

A constant is a type of variable whose value cannot be changed. It is helpful to think of constants as containers that hold information which cannot be changed later. Ruby have a convention to use start with capital letter, but usually all letters are capitalized. Ruby has these predefined constants.
# predefined constants
TRUE, FALSE
NIL
STDIN, STDOUT
STDERR
ENV
ARGF, ARGV
DATA
RUBY_VERSION
RUBY_RELEASE_DATE
RUBY_PLATFORM

Literals

A literal is a value symbol that can be a number, string or collection of values. The literal is also truly constant. You can not change value of literals during runtime. For example: 520 is a literal but "520" is also a literal. Literals represents hard coded data.

Example:

5
24
520
'a'
"test"
[1,2,3]

Numeric Operators:

Operators are data type dependent. So for each data type should have a different set of operators. However, Ruby is smart enaugh to make automatic conversion between different data types. We say numeric operators are polymorph. They can operate integers and float numbers.

Operator Name Example Result
+ Addition x+y Sum of x and y.
Subtraction x-y Difference of x and y.
* Multiplication x*y Product of x and y.
/ Division x/y Quotient of x and y.
% Modulus x%y Remainder of x divided by y.
** Exponent x**y x**y will give x to the power y

Examples

# expressions demo:
puts (5 + 5) / 2   # 5
puts  5 + 5  / 2   # 7
puts  5 + 5  / 2.0 # 7.5
puts  5 + 2  * 2   # 9
puts (5 + 2) * 2   # 14

# unexpected result:
print [5 + 2] * 2 # [7, 7]

Notes:

  1. In this example we have used 3 numeric operators: { +, /, *}. That should be familiar to you: Addition, division and multiplication. In computer science we have a scarce number of operators due to legacy ASCII notation. { ÷  · } are Unicode symbols for division and multiplication, not available in Ruby.
  2. Square bracket […] and squiggly brackets {…} are used in mathematics to control the order of operations but not in Ruby. Notation [5 + 2] create an array with one element [7] that is replicated into [7, 7]. Totally unexpected result isn’t it?

Numeric Modifiers

Modifiers are in place operators that alter value associated to an identifier. Modifiers are also assignment statements. Python modifiers are inherited from C language. Modifiers can accept expressions not only constants.

Operator Description Example Equivalent
+= Addition and assignment operator. c += a c = c + a
-= Subtraction and assignment operator. c -= a  c = c – a
*= Multiply and assignment operator. c *= a c = c * a
/= Divide and assignment operator. c /= a c = c / a
%= Modulus and assignment operator. c %= a c = c % a
**= Exponent and assignment operator. c **= a c = c ** a
There are two common operators: increment (++) and decrement (--) available in many C like languages including JavaScript. These two operators are not available in Ruby.

Bitwise Operators

Next operators are acting at bit level. They are inherited from C language. An operator usually has 2 operands but one of these operators has only one operand. Which one? Read description for each operator to find out!

Operator Name Description Example
& Binary AND Operator copies a bit to the result if it exists in both operands (a & b)
| Binary OR It copies a bit if it exists in either operand. (a | b)
^ Binary XOR It copies the bit if it is set in one operand but not both. (a ^ b)
~ Binary Ones Complement It is unary and has the effect of 'flipping' bits (not). (~a )
<< Binary Left Shift The left operands value is moved left by the number of bits specified by the right operand. a << 2
>> Binary Right Shift The left operands value is moved right by the number of bits specified by the right operand. a >> 2

Logical Operators

In computer science, logical values; are also known as Boolean values. These values are in Ruby start with lowercase: { true, false }. In Python these values start with uppercase {True, False}. In Ruby the "true" value is an instance of a special class: TrueClass while "false" value is an instance of FalseClass. There are also two constants: {TRUE, FALSE} that are deprecated.

Several operators have a Boolean result. These operators can be combined to create logical expressions: "comparison operators", "Boolean operators" and "relation operators". Together they are called "logical operators" in this tutorial since they all produce true or false result.

Boolean Operators

Boolean operators deal with Logical values. It can be used also to combine smaller logical expressions into larger expressions. These operators produce Boolean results: true or false

Warning: In Ruby you should use operators: { &&, ||, ! } for Boolean expressions. Alternative operators {and, or, not} are used only in special occasions. Keywords {and, or, not} are available for used with "control flow" statements. Apparent the are the same, but the behavior is different due to operator precedence.

symbol keyword significance
&& and Logical AND operator
|| or Logical OR operator
! not Logucal NOT operator

The table of truth for Ruby operators:

A B !A !B A || B A && B
false false true true false false
true false false true true false
false true true false true false
true true false false true true

Comparison Operators

A comparison operator can be used to compare two values. Usually values are numeric but can be also strings or objects. These operators produce a Boolean result.

Symbol Description Expression Result
== equal to x == 8 False
x == 5 True
x == "5" False
!= not equal x != 8 True
> greater than x > 8 False
< less than x < 8 True
>= greater than or equal to x >= 8 False
<= less than or equal to x <= 8 True
<=> combined comparison 0 <=> 1 # -1 True

Example:

In the next example we initialize value x, called "test fixture" and we use this value to create relation x==5 to demonstrate how a relation produce a Boolean response. In the next table, we use variable x = 5 to demonstrate various comparison expressions.

#example of identity relation
x = 5    # create a test fixture
puts x;  # check x value
puts "is x equal to 5? ", x == 5;

Examples:

In next example, we use operators: { < , >, <=, >=, ==, !=, <=>}

# equal and different
1 == 0 # false
1 != 0 # true

# less than and greater than
4 < 5 # true
5 > 4 # true

# greater then or equal to
0 >= 0 #true
0 >= 1 #false

# less then or equal to
1 <= 1 #true
1 <= 0 #true

# combined comparison
0 <=> 1 # -1
1 <=> 0 # 0
1 <=> 0 # 1

Relation Operators

Relation operators can verify if there is any relation between a literal constant or variable and a collection. This operator also produce a Boolean result.

Symbol Description Expression Result
=== range include operator (1..5) === 5 True

Example:

In this example we verify membership of collections

# range include operator
(1..5)  === 5 # true
(1...5) === 5 # false

# range exclusion expression
!((1..5)  === 3) # false
Note: There is no exclusion operator "!==". If you want to negate result of relation operator "===" you can use round brackets !(expression) to negate the result.

Read next: Variables