Introduction to Ruby Programming Language
-
Upload
nicolo-calcavecchia -
Category
Technology
-
view
592 -
download
4
description
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