Introduction to Ruby Programming Language

Post on 10-May-2015

592 views 4 download

Tags:

description

Main concepts: objects, classes, modules, inheritance, blocks, procs, lambdas

Transcript of Introduction to Ruby Programming Language

Introduction to Ruby

Nicola Calcavecchia - 19/04/2013calcavecchia@{elet.polimi.it|gmail.com}

Principles of Programming Languages

1

Main Features

• Dynamically Typed.

• Purely Object Oriented.

• Supports Meta-Programming.

• Garbage collected.

• Supports inheritance and mixins.

www.ruby-lang.org

2

History

• Created by Yukihiro Matsumoto (Matz) in 1995.

• Influenced by Smalltalk, Perl, Lisp and Python

• Current stable release: 2.0.0-p0

• Interpreters:

• MRI (Matz’s Ruby Interpreter)

• YARV (now official)

• Others: JRuby, Rubinius, IronRuby

3

Diffusion• Killer apps:

• Ruby on Rails (web framework)

• Puppet, Chef (configuration management)

• Capistrano (deploy management utility)

• and many others...

Source: https://github.com/languages (5/04/2013)

4

Getting started

• irb executable: interactive shell (i.e., REPL).

• ruby executable: language interpreter.

• File extensions: .rb

ruby hello.rb

5

Hello World (and a glimpse at Ruby Syntax)

print("Hello World");

print("Hello World")• Semicolons are optional:• Practically never used.• Use newline instead.

• Classic (and verbose)

• Parenthesis in methods are optional:• Cleaner syntax!• Works well for DSLs (will see later...).

print "Hello World"

Cool, but pay attention: f(3+2) + 1f (3+2) + 1

6

Data Types

• Ruby has many built-in data types:

• Numeric: Integer, Floats, Complex, Rational, etc.

• String: single-quoted, doubly-quoted, here documents, backtick, characters, etc.

• Array

• Hash

• Boolean and nil

• etc.

7

Data Types

• Ruby has many built-in data types:

• Numeric: Integer, Floats, Complex, Rational, etc.

• String: single-quoted, doubly-quoted, here documents, backtick, characters, etc.

• Array

• Hash

• Boolean and nil

• etc.

All are implemented by objects!

7

Numeric Types

• Implemented as objects

• All inherits from Numeric class

404 # Fixnum 1_000_000_000 # Better readability 241.1 # Float -3.7e4 # Float 0xFF # Fixnum given in hex 1 + 1.0 # Float

8

Strings

• Enclosed in single or double quotes

• Small differences between the two

• String interpolation

• Unicode escapes

• Mutable objects

"six times four is: #{6*4}" => "six times four is: 24"

"this is a string" => "this is a string"'this is a string too' => "this is a string too"

"\u20ac" => "€"

9

Arrays• Dynamically sized

• Untyped and mutable

• Example:

[1, 2, 3] # an array with three Fixnum objects[] #empty array[0] * 10 # new array containing 10 zeros["a string", 42, 3.3, []] # can hold any type of objecta = [1, 1, 2, 3, 5, 8]a[0] # first element is 1a[-1] # last element is 8a[10] # nil if exceeding limitsa[7] = 21 # extends the array (with nil)a[2,3] # subarray starting from 2, 3 elements longa[2,3] = ['A','B','C'] #substitute subarraya + [0, -1] # concatenates two arrays[1, 2, 3, 4, 5] - [2, 4] # removes elements from the first array

10

Hashes

• Unordered collection of key-value pairs

• Mutable

• Indexed by keys

a = {} # create an empty hasha['one'] = 1 # map string 'one' to Fixnum 1a['two'] = 2# map string 'two' to Fixnum 1 a = {'one' => 1, 'two' => 2} # create and initialize Hasha['one']=> 1

11

Symbols• Same as scheme symbols

• Constant, immutable strings

• I.e., placeholder for identifiers and strings

• Always prefixed by a semicolon

• Created in memory as soon as referenced

:red # create a new symbol called red"blue".to_sym # convert a string to a symbol=> :blue:"red" # same as :red

hash = {:red => "red", :blue => "blue" } # often used in hashes (i.e., fast)

12

Boolean and Nil

• true: logical true value

• Singleton instance of TrueClass

• false: logical false value

• Singleton instance of FalseClass

• nil: null value (i.e., absence of value)

• Singleton instance of NilClass

13

Rules for objects

1. All variables are references to objects (there are no primitive types!)

2. Objects communicate via messages (i.e., method calls)

3. Each object has its own (private) state

4. Every object is an instance of a class

14

Object References

• It always works with references to object (i.e., similar to Scheme, Java)

• Call by object sharing:

• When an object is passed to a method, its reference is passed (i.e., the reference is copied).

s = "Ruby" # Creates a String object. Store the reference to it in st = s # Copy reference to tt[-1] = "" # Modify the object through reference to tprint s # Access (modified) object through st = "Java" # t now refers to a different objectprint s,t # Prints "RubJava"

15

Classes and methods

• class keyword to define a class

• def to define methods

class ClassName

" def method1(par1, par2)" " expression1" end

" def method2(par1, par2)" " expression2" endend

16

Constructor and instance variables

• Method initialize is the constructor

• Instance variables start with @ symbol

class Point

" def initialize(x,y)" " @x = x" " @y = y" end

" def to_s()" " return "#{@x},#{@y}"" endend

17

Cleaner version...

• Ruby supports “parallel assignments”

• Return is implicit (i.e., like Scheme):

• Last expression is returned if not specified

class Point

" def initialize(x,y)" " @x, @y = x, y" end

" def to_s()" " "#{@x},#{@y}"" endend

Instance variables are created only when stored

for the first time

18

Creating an object

• Invoke constructor with new

p = Point.new(10,20)

• Invoking a method:

print p.to_s

• Sends the to_s message to object referenced by p

19

Getters and Setters

• Lets define getters and setters for Point class

class Point" def initialize(x,y)" " @x, @y = x, y" end" def x" " @x" end" def y" " @y" end" def x=(value)" " @x = value" end" def y=(value)" " @y = value" endend

p = Point.new(10,20)p.y = 10 # notice the spacep.x= 20 # print p.x # same as p.x()print p.y

Look like variable references. They are actually method calls

(without parentheses)!

20

Getters and Setters

• Concise way to define getters and setters

• Use symbols to identify the instance variable

class Point"" attr_accessor :x, :y

" def initialize(x,y)" " @x, @y = x, y" end

end

• attr_accessor creates getters and setters• attr_reader creates getters only• attr_writer creates setters only

21

Defining new operatorsclass Point" attr_accessor :x, :y

" def initialize(x,y)" " @x, @y = x, y" end

" def +(other)" " Point.new(@x + other.x, @y + other.y)" end

" def -@ # Unary operator" " Point.new(-@x, -@y)" end

" def *(scalar)" " Point.new(@x * scalar, @y * scalar)" endend

+, - and * are just method names!

22

Class Variables and Class methods

• Class variables are shared among all instances of that class

• Introduced with @@ prefix

• Class methods are methods associated with a class (not with an instance)

• Introduced by prepending self. to the method name

class Point

" attr_accessor :x, :y

" @@total_points = 0

" def initialize(x,y)" " @x, @y = x, y" " @@total_points += 1" end

" def self.total_points" " @@total_points" endend

p1 = Point.new(10,15)p2 = Point.new(20,30)print Point.total_points

23

Inheritance

• By default a class extends the Object class

• Inherits all predefined methods

• Classic subclass/superclass relationships

• No multiple inheritance

• Methods can be overridden

• Instance variables are not inherited!

class Point3D < Point" attr_accessor :z

" def initialize(x,y,z)" " super(x,y)" " @z = z" end"end

24

Modules

• A container of:

• Methods

• Constants

• Class variables

• Modules cannot be instantiated

• Effective way to create namespaces

module Base64" DIGITS = ('A'..'Z').to_a

" def Base64.encode" end

" def Base64.decode" end

end

Base64.encodeBase64.decodeBase64::DIGITS

25

Nesting namespaces

• Modules and classes can be nested

• Better readability and avoid name clashes

module Base64" DIGITS = ('A'..'Z').to_a

" class Encoder" " def encode" " end" end

" class Decoder" " def decoder" " end" endend

a = Base64::Encoder.new

26

Mixins

• If module define some instance methods, they can be “mixed-in” a class.

• Mixin code can interact with code in the class

module A" def a" endend

module B" def b1" end" def b2" endend

class MyClass" include A" include B" def m" endend

m = MyClass.newm.am.b1m.b2

27

Control structures

• Classic control structures:

• If, else, elsif, case, etc. (terminated with “end” keyword)

• Plus some syntactic sugars:

print "greater" if Math::PI > 3Conditional modifier

Unlessunless Math::PI <= 3" print "greater"end

28

Loops

• Classic for, while, until, etc:

• The object must have an each method

x = 0puts x += 1 while x < 10

x = 0puts x += 1 until x >= 10

array = [1,2,3,4]for element in array" puts elementend

hash = {:a => 1, :b => 2, :c => 3}for key, value in hash" puts "#{key} => #{value}"end

Also with modifiers version of loops (one line)

29

Iterators and yield• Allow to loop over a collection (or value)

• Receive a block of code which is executed with the current element

• Use yield to execute the passed block

30

Iterators and yield• Allow to loop over a collection (or value)

• Receive a block of code which is executed with the current element

• Use yield to execute the passed block

3.times{ puts "thank you!"}data.each{|x| puts x}[1,2,3].map{|x| x * x }factorial = 12.upto(n) {|x| factorial *= x}

30

Iterators and yield• Allow to loop over a collection (or value)

• Receive a block of code which is executed with the current element

• Use yield to execute the passed block

3.times{ puts "thank you!"}data.each{|x| puts x}[1,2,3].map{|x| x * x }factorial = 12.upto(n) {|x| factorial *= x}

30

Yield examples

def my_method" yieldend

my_method{ puts "hello!"}

Yield without parameters

31

Yield examples

def my_method" yieldend

my_method{ puts "hello!"}

# This method expects a block. # It generates n values# of the form m*i + c for 0..n-1, # and yields them, one at a timedef sequence(n, m, c)" i = 0" while i < n" " yield m * i + c" " i += 1" endend

sequence(5,3,20){|y| puts y}

Yield without parameters Yield with parameters

31

Blocks

• Delimited with curly braces or do end keywords (i.e., multi line).

• If method does not “yield”, the block is ignored.

• Value returned from a block is the the value of the last expression.

• Invoking return within a block returns from the calling method!

def print_sequence" SPECIAL_VALUE = 5" s = sequence(5,3,20) do |y|" " if y == SPECIAL_VALUE" " " return 0" " end" " y * 2" end" print send

The return statement exits from the print_sequence

method!

32

Procs and Lambdas

• Blocks are syntactic structures

• They are not objects!

• However, it is possible to create block objects:

• Proc

• Lambda

• Invoke method call

33

Procs and Lambdas

• Blocks are syntactic structures

• They are not objects!

• However, it is possible to create block objects:

• Proc

• Lambda

• Invoke method call

p = Proc.new{|x,y| x + y} puts p.call(10,20)

Creating a proc object

33

Procs and Lambdas

• Blocks are syntactic structures

• They are not objects!

• However, it is possible to create block objects:

• Proc

• Lambda

• Invoke method call

p = Proc.new{|x,y| x + y} puts p.call(10,20)

Creating a proc object

l = lambda{|x,y| x + y}puts l.call(10,20)

Creating a lambda object

33

Procs and Lambdas

• Blocks are syntactic structures

• They are not objects!

• However, it is possible to create block objects:

• Proc

• Lambda

• Invoke method call

p = Proc.new{|x,y| x + y} puts p.call(10,20)

Creating a proc object

l = lambda{|x,y| x + y}puts l.call(10,20)

Creating a lambda object

Get the “arity” of a block

l = lambda{|x,y| x + y}puts l.arity=> 2

33

Converting blocks to procs

• Blocks do not have a name

• Blocks can be converted into proc

• Use & (i.e., ampersand)

# Explicit conversion into proc def sequence3(n, m, c, &b) " i=0" while(i < n) " " b.call(i*m + c) " " i += 1" end endsequence3(5, 2, 2) {|x| puts x }

def sequence4(n, m, c, b) " i=0" while(i < n) " " b.call(i*m + c) " " i += 1" end endp = Proc.new {|x| puts x} # create procsequence4(5, 2, 2, p) # ordinary argument

34

Procs vs Lambdas

• Lambda behave similar to method calls

• Blocks behave similar to block evaluation

35

Procs vs Lambdas

• Lambda behave similar to method calls

• Blocks behave similar to block evaluation

def test" puts "entering method"" p = Proc.new { puts "entering proc"; return }" p.call # Invoking the proc makes method return " puts "exiting method" # This line is NEVER executedend

Return with proc

35

Procs vs Lambdas

• Lambda behave similar to method calls

• Blocks behave similar to block evaluation

def test" puts "entering method"" p = Proc.new { puts "entering proc"; return }" p.call # Invoking the proc makes method return " puts "exiting method" # This line is NEVER executedend

def test" puts "entering method"" p = lambda { puts "entering lambda"; return }" p.call # Invoking the lambda does not make the method return " puts "exiting method" # This line IS executedend

Return with proc

Return with lambda

35

References

36