ruby language - a quick tour
TRANSCRIPT
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