Ruby Language - A quick tour

Preview:

Citation preview

Wang_Wei@opi-corp.com

The Ruby Programming

Language- Quick Tour

TOC

1.Overview

2.Installation & IDE

3.Structure & Execution

4.Data types & Objects

5.Expression & Operators

6.Statement & Control Structure

7.Method,Block,Proc,Lambda

8.Class & Module

9.Reflection & Metaprogramming

10.Gems & Rake

11.Books & Links & Persons

Overview - Birthstone

January - Garnet February - Amethyst

March - Aquamarine April- Diamond

May - Emerald June - Pearl

July - Ruby August - Peridot

September - Sapphire October- Tourmaline

November - Yellow Topaz December - Blue Topaz

Overview

•Pure OO,Everything is Object,Yes!Everything

5.times{|i|puts i}

•Highly Dynamic

class HelloWorld;end

HelloWorld.send(:define_method,:say){puts "HelloWorld!"}

•Excute while parsing

class Klass

puts "Hello"

end

•Cross Platform

Windows,Linux,Unix,Mac,...

•Open Source

http://www.ruby-lang.org/en/downloads/

To C++ Programmer

•No variable declaration

•ONLY false & nil are falsy

•'constructor' is called 'initialize'

•All methods are always 'virtual'

•First letter is important: $,@,@@,Klass,i

•Member variables are private

•Use 'self' instead of 'this'

•?,! ARGV.size.zero? obj.nil? str.strip!

•Single Inheritance, Mixin to help

•Parentheses & semicolons are usually optional

•Classes are not sealed!can be reopen

•No Generic/Template

•Iteration are easy

•There's only two container: Array,Hash

•Almost everything is an expression

Installation & Implementations

•Windows

One-Click Installer, Zip

•Ubuntu

sudo apt-get install ruby1.8/ruby1.9

sudo apt-get install irb1.8/irb1.9

•Mac

port install ruby

•Implementations

c ruby, JRuby, IronRuby

•Version

ruby1.8 ruby1.9

"IDE"

•Windows/Linux

Eclipse+RDT, *RubyInSteel*,

NetBeans,IDEA,RadRails,3rdRails

Notepad++/Ultraedit/Editplus+irb

•Mac

Textmate

Structure & Execution

#!/usr/bin/ruby shebang comment

# -*- coding: utf-8 -*- coding comment

require 'erb' loading library

class Klass define class

include Enumerable include module

def k

require 'socket' loading library

...

end

end

if $0 == __FILE__

o=Klass.new.k create object

DATA.read

end

__END__

embeded string embeded string resource

Data types - Number

dec = 123 dec.class==Fixnum

million = 1_000_000

hex = 0xFF

binary = 0b0010

octal = 0377

float = 1_000.0 float.class==Float

2**1024 = 179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477

322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302

219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239

947245938479716304835356329624224137216

(2**1024).class==Bignum

Conversion:

other_type.to_i

other_type.to_f

Data types - Text

name = 'Jack'

name = %q[Jack]

name = %q{Jack}

name = %q!Jack!

name = %q|Jack|

name = %q+Jack+

name = %q-Jack-

name = %q=Jack=

name = %q,Jack,

name = %q.Jack.

name = %q/Jack/

name = %q\Jack\

...

all symbol on

keyboard!

variable_name = %PREFIX SYM content SYM

SYM = [~`!@#$%^&*_-+=|\:;"',.?/] + [] {} ()

No Escape!

PREFIX = [%q,%Q,%x,%r,%s]

Backtick command Execute

%x[notepad] `notepad`

Regular expression

%r[hello] /hello/

Array literal

%w[hello world] => ['hello','world']

%W[hello world] => ["hello","world"]

Symbol literal

%s[symbol]

Data types - Text

a = "Hello" + "World" => "HelloWorld"

a.sub("World","There") => "HelloThere" sub!

a.gsub(/o/,"*") => "Hell*W*rld" gsub!

a.chomp("d") => "HelloWorl"

a.center(15,"=") => "===HelloWorld==="

a.ljust(16) => "HelloWorld "

a.rjust(16) => " HelloWorld"

a.capitalize => "Helloworld"

a.upcase => "HELLOWORLD"

a.downcase => "helloworld"

a.reverse => "dlroWolleH"

a.swapcase => "hELLOwORLD"

a.length => 10

a.size => 10

a.count('o') => 2

a.include?('o') => true

"BBBBBaaaaaadddd".squeeze => "Bad"

Data types - Text

a = "Hello World!"

a[index] a[0] => "H"

a[from,count] a[0,5] => "Hello"

a[range] a[0...-1] => "Hello World"

a[-6..-1] => "World!"

a[regex] a[/W.*?!/] => "World!"

a.split(/[ !]/) => ["Hello", "World"]

a.split.join(",").concat("~") => "Hello,World!~"

a.sub(" ",",") << "~" => "Hello,World!~"

Conversion:

everything.to_s

Data types - Here Document

str = <<-STR.gsub("world","there")

hello world

hello world hello world hello world

hello world

hello world

hello world

STR

cpp_tepmlate = <<-CPPTPL

class <%=name%> : public <%=basename>

{

public:

<% methods.join("\n") %>

};

CPPTPL

result = ERB.new(cpp_template).result(binding)

Data types - Array

As Vector:a = [1,"h",3.14]

n = %w[1 2 3] => ['1','2','3']

e = %W[\s \t \r \n] => ["\s","\t","\r","\n"]

empty = Array.new=> []

nils = Array.new(3) => [nil,nil,nil]

[0]*3 => [0,0,0]

copy = Array.new(nils) => [nil,nil,nil]

Array.new(3){|i|i} => [0,1,2]

As Set:[1,2]+[3,4] => [1,2,3,4]

[1,2,3,4] - [1,2] => [3,4]

[1,2] | [2,3] => [1,2,3]

[1,2] & [2,3] => [2]

As Stack:[1,3].push(3,4) => [1,2,3,4]

[1,2,3].pop => [1,2]

As Queue:[1,2,3,4].shift => [2,3,4]

[3,4,5].unshift(2) => [2,3,4,5]

Data types - Array

As List:a = [1,2]

a.concat(3) => [1,2,3]

a << 1 => [1,2,3,1]

a.insert(a.index(2),'a') => [1,'a',2,3,1]

a.delete("a") => [1,2,3,1]

a.delete(1) => [2,3]

[1,2,3,4].reject{|e|e%2==0} => [1,3]

As Sequence:a = ('a'..'c').to_a => ['a','b','c']

a[0,1] => ['a']

a[0..2] => ['a',b','c']

a[0..-2] => ['a','b']

Iteration:a = [1,2,3]

a.each{|e| print(e)} => 123

a.each_with_index{|e,i| print("#{i}:#{e},")} => 0:1,1:2,2:3,

a.inject(0){|s,e|s+=e} => 6

for i in a

print(i)

end => 123

Data types - Array

Conversion:

other_type.to_a

(1..10).to_a => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

('a'..'c').to_a => ['a','b','c']

('ab'..'bf').to_a => ["ab", "ac", "ad", "ae", "af", "ag",

"ah", "ai", "aj", "ak", "al", "am", "an", "ao", "ap", "aq",

"ar", "as", "at", "au", "av", "aw", "ax", "ay", "az", "ba",

"bb", "bc", "bd", "be", "bf"]

{:a=>1,:b=>2}.to_a => [[:b, 2], [:a, 1]]

Data types - Hash

As HashTable:

j = {"name"=>"jack",:age=>25}

j["gender"] = "male"

Iteration:

j.each{|k,v| ... }

for k,v in j

...

end

Conversion:

j.to_a => [["name", "jack"], [:age, 25]]

j.to_s => "namejackage25"

Data types - Range

1..10 => 1..10 (iterable, to_a)

1.0..1.5 => 1.0..1.5 (un-iterable,no to_a)

cold_war => 1945..1989

letter = 'a'..'z' => 'a'..'z' (to_a)

Iteration:

n = 3

(1..n).each{|i|print(i)} => 123

for i in (1..n)...

Membership test:

(1..100).member?(50) => true

(1..100).include?(50) => true

(1..100).cover?(2..50) => true (1.9)

Data types - Symbols

:symbol => :symbol

:name => :name

:'with quote' => :'with quote'

:"hello #{:name}" => :"hello name"

Conversion:

:name.to_s => "name"

"name".to_sym => :name

"name".intern => :name

"name".id2name => :name

Symbol Table:

symbols are entris in symbol table of interpreter

symbols have an index in symbol table while string have not

Data types - True,False,Nil

Ruby has NO Boolean type!!!

true.class => TrueClass

false.class => FalseClass

nil.class => NilClass

true.nil? => false

false.nil? => false

nil.nil? => true

Only false&nil are falsy,everything else are truthy:

puts "hi" if nil => nil

puts "hi" if false => nil

puts "hi" if true => "hi"

puts "hi" if 0 => "hi"

puts "hi" if 0.0 => "hi"

puts "hi" if "" => "hi"

puts "hi" if [] => "hi"

puts "hi" if {} => "hi"

Expression & Operators

Class Variable @@[_a-z][_a-zA-Z0-9]*

Instance Variable @[_a-z][_a-zA-Z0-9]*

Global Variable $[_a-z][_a-zA-Z0-9]*

Local Variable [_a-z][_a-zA-Z0-9]*

Constant [A-Z][_a-zA-Z0-9]*

class Klass;end Klass is constant!

Expression & Operators

Assignment:

a = [1,2,3]

Parallel assignment:

x,y,z,u = a -> x=1,y=2,z=3,u=nil

u,x,y,z = 4,*a -> u=4,x=1,y=2,z=3

Default operator:

port = port || 80 -> if port==nil then port=90

port ||= 80

Guard operator:

port = port && 8080 -> if port!=nil then port=8080

port &&= 8080

Equality:

==,!= -> equality operator

=~,!~ -> pattern-matching operator

"hello"=~/[a-z]+/

Expression & Operators

Boolean Operator:

&& and

|| or

! not

Conditional:

msg = "you have #{n} #{n==1? "message" : "messages"}"

defined? operator:

y = f(x) if defined? f

Statement & Control Structure

Conditional:

[result = ]if expression [then]

end

[result = ]if expression

elsif

else

end

if/unless as statment modifer:

... if expression

... unless expression

Statement & Control Structure

case:

result = case expression

when ...,... then ...

next

when ...,... then ...

break

else ...

end

Loops:(can be statement modifer)

while expression do

...

end

until expression do

...

end

for var in collection do

...

end

Method,Block,Proc,Lambda

Method Invocation:

puts "hello" -> self,puts,"hello"

Math.sqrt(2) -> Math(Module),sqrt,2

"a".size -> "a",size

[1,2,3].each{|e|...}-> [1,2,3],each, {|e| ...}

object.method(arg1,arg2,...){|a1,a2,..|...}

def object.method(*args,&block)

arg1,arg2,arg3 = *args

block.call(1,2,3...)

end

receiver.send(:private_message,arg1,arg2,...)

Method,Block,Proc,Lambda

Block:

One of the most powerfull feature of Ruby!

[1,2,3].each {|i| ... }

[1,2,3].each do |i|

...

end

def say_hello

print("Jack said:")

yield 1,2 if block_given?

end

say_hello{|a,b| print "hello",a,b} => Jack said:hello12

b = Proc.new{|a,b|print "hello",a,b}

l = lambda{|a,b|print "hello",a,b}

say_hello(&b)

say_hello(&l)

Class

The class keyword in Ruby is more like a scope operator than a

class declaration. the core job is to move you in the context of the

class, where you can define methods.

Class Constructor:

Class Person

def initialize(name)

@name = name

end

end

Person.new("Jack").name =>

undefined method `name' for #<Person:0x28406f0 @name="Jack"> (NoMethodError)

class Person

def name;return @name;end

def name=(value);@name=value;end

end

class Person

attr_reader :name

end

attr_writer , attr_reader , attr_accessor

Class

Class method(Static function):Class Person

def Person.class_func

end

def self.class_func

end

end

Method of object(singleton_method):j = Person.new("jack")

def j.say_hi

puts "hi, i'am jack"

end

Define operators:class Person

def +();end +-*/

def [];end

def <=>;end

end

j

Person

---------

methods

j

Person

---------

methods

???

---------

say_hi

Class

Method Visibility:class Person

def initialize(name,age)

@name,@age = name,age

end

def introduce

"my name is #{@name},i'm #{@age} years old"

end

protected #every method below will be protected!

def privacy;"my nick name is jacky";end

def secret;end

end

j = Person.new("jack",24)

puts j.introduce

puts j.privacy

class Person

private :privacy #Moduel.private/protected/public

private :secret

end

class Person

private *[:privacy,:secret] #OK!

end

Person.send(:private,:privacy,:secret) #OK!

every time you call a private method,

it must be on the implicit receiver—self.

Class

Make class on-the-fly:Person = Class.new

[:name,:age].each do |attr|

Person.send(:attr_accessor,attr)

end

Person.send(:define_method,:hi) do

print "I'm #{@name}"

end

class Person

def bye

"bye bye!"

end

end

j = Person.new

j.name = "jack"

j.hi => "I'm jack"

j.bye => "bye bye!"

Class

Inheritance:class Person;end

class Student < Person

end

s = Student.new

s.class => Student

s.class.class => Class

s.class.superclass => Person

Person.superclass => Object

Student.ancestors => [Student, Person, Object, Kernel]

Module

As namespace:

module Util

PI = 3.14

def area

self.radius**2 * PI

end

def Util.pi2

PI**2

end

end

PI2 = Util.pi2 => 9.8596

As mixin:

class Shape;end

class Pie < Shape

include Util

def initialize(r);@radius=r;end

def radius;@radius;end

end

Pie.new(2).area => 12.56

template<class T>

class Util

{

public:

double area() {

float r = ((T*)this)->radius;

return r*r*3.14;

}

};

class Shape{};

class Pie : public Util<Pie>, public Shape

{

public:

float radius;

Pie():radius(2){}

};

#include <iostream>

void main()

{

using namespace std;

Pie p;

cout<<p.area()<<endl;

}

Module

Loading and Requring:

require 'win32/clipboard'

load("c:/a.rb")

load("c:/extension.dll")

load("/home/jack/rb_extension/ext.so")

$LOAD_PATH ($:)

$LOAD_PATH.class => Array

$LOAD_PATH << "d:/my_library"

Reflection & Metaprogramming

Methods:

object.methods

object.private_methods(false)

object.protected_methods

object.public_methods

object.singleton_methods

Variables:

object.instance_variable_defined?

object.instance_variable_get

object.instance_variable_set

object.instance_variables

object.class.class_variables

Parents:

object.superclass

object.ancestors

Reflection & Metaprogramming

*eval (evaluate):

eval(string[,bindings])

Klass.class_eval(&block)

Mod.mod_eval(&block)

object.instance_eval(&block)

def object.hi

puts "hi"

end

object.instance_eval do

def hi

puts "hi"

end

end

alias:

class Klass

def hi;puts("hi");end

alias :greeting,:hi

end

alias :old_method :method

def method(*args,&block)

...

old_method(*args,&block)

...

end

Reflection & Metaprogramming

method_missing:

class Klass

def method_missing(m)

m.to_s

end

end

k = Klass.new

k.any_thing! => "any_thing!"

const_missing:class Unicode

def self.const_missing(name)

if name.to_s=~/^U[0-9a-fA-F]{4,5}|10[0-9a-fA-F]{4}$/

codepoint = $1.to_i(16)

utf8 = [codepoint].unpack("U").freeze

const_set(name,utf8)

else

raise NameError,"Uninitialized Constant : Unicode::#{name}"

end

end

end

copyright = Unicode::U00A9 (©)

Gems & Rake

Rake:

Make for ruby - Rake

c - make

java - ant

...

Gems: (Jar,Egg)

gem install gem_name

gem uninstall gem_name

gem list --local

parseOpts-0.0.2 net-ssh-2.0.14 mysql-2.8.1-x86 log4r-1.0.5

nokogiri-1.4.1-x86 win32-api-1.3.0 oniguruma-1.1.0 RubyInline-3.8.4

rubyzip-0.9.1 sqlite-2.0.1 Redmine RMagic

wxruby-2.0.1-x86 coderay-0.9.5 ffi-0.5.4-x86 flvtool2-1.0.6

pdf-toolkit-0.5.0 opencv-0.0.6 rubyrss-1.1 *Rails*

FOX,Qt,Tcl/Tk Hpricot .........

Books & Links & Persons

http://www.ruby-lang.org

http://rubyforge.net

https://github.com/languages/Ruby

http://www.sf.net

http://confreaks.net/

http://confreaks.net/presenters/137-dave-thomas

http://www.rubyconf.org/

Books & Links & Persons

Programming Ruby by Dave Thomas

The Ruby Programming Language

by David Flanagan and Yukihiro Matsumoto

The Ruby Way 3nd

by Hal Edwin Fulton

Design Patterns in Ruby by Russ Olsen

Ruby Cookbook

by Lucas Carlson and Leonard Richardson

Metaprogramming Ruby by Paolo Perrotta

Books & Links & Persons

YUKIHIRO

MATSUMOTO

DAVE THOMAS DAVID

HEINEMEIER

HANSSON

Wang_Wei@opi-corp.com