name name2 n2

71
Ruby for Perl programmers All material Copyright Hal E. Fulton, 2002. Use freely but acknowledge the source.

description

sferferf

Transcript of name name2 n2

Page 1: name name2 n2

Ruby for Perl programmers

All material Copyright Hal E. Fulton, 2002.Use freely but acknowledge the source.

Page 2: name name2 n2

What is Ruby?

• A scripting language

• An object-oriented language

• A dynamic language

• A Very High Level Language (VHLL)

• A human-oriented language

• An open-source project

Page 3: name name2 n2

Ruby is General-Purpose

• One-liners at the command line

• “Quick and dirty” scripts

• System administration tasks

• CGI scripts

• GUI apps

• Networking and distributed apps

Page 4: name name2 n2

A Brief History of Ruby…

• 1993 Conceived by Yukihiro Matsumoto (“Matz”)• 1995 First release (Japan)• 1999 Version 1.4 released• 2000 Programming Ruby published;

comp.lang.ruby created• 2001 Version 1.6 released;

Ruby in a Nutshell published• 2001 The Ruby Way published• 2002 The Ruby Developer’s Guide published;

Teach Yourself Ruby in 21 Days published

Page 5: name name2 n2

Where does Ruby get its ideas?

• Perl (regular expressions, some syntax)

• SmallTalk (dynamic features, OOP)

• CLU (iterators)

• LISP (dynamic features)

• C (operators, printf/sprintf, etc.)

• Others

Page 6: name name2 n2

Ruby’s Design Principles

• Principle of Least Surprise (POLS), aka Law of Least Astonishment (LOLA)

• Human-oriented design• Orthogonality, “naturalness,” consistency• Flexibility and dynamism• TMTOWTDI – “There’s More Than One Way To

Do It”• TABWTDI – “There’s A Better Way To Do It”

Page 7: name name2 n2

Disclaimer:

I am not an

expert in Perl.

Page 8: name name2 n2

How is Ruby like Perl?

• Scripting language

• Interpreted, not compiled

• Minimalist philosophy

• Good at text processing

• Understands regular expressions

• Powerful and versatile

• Many features borrowed directly from Perl

Page 9: name name2 n2

How is Ruby different from Perl?

• Radically object-oriented from the start

• Extremely dynamic

• Built-in threads (non-native)

• True closures (?)

• Exception handling

• Significant syntax differences

Page 10: name name2 n2

Some Specific Similarities…

• Most operators and precedence

• Most regular expression features

• Many special variables: $! $& $+ $` $’$0-$9 $/ $\ $, $. $$ $? $_

• Flexible quoting of strings

• Multiple assignment

• __END__, taint, and other features

Page 11: name name2 n2

Some Specific Differences…

• OOP by design: No bless, tie, tied, untie• No scope declarations (my, local)• Prefixes indicate scope, not type• True/false testing is different• Missing special variables: $| %SIG @_ $# $=

$~ $% $: $; $[• No autovivification• Better #{} support• Better support for dynamic features• No DESTROY, __PACKAGE__, __DATA__

Page 12: name name2 n2

Enough! Let’s see some code.

The Obligatory Hello, world! Program:

puts “Hello, world!”or print “Hello, world!\n”

Page 13: name name2 n2

Some Basic Syntax

# This is a comment.

str1 = “Some string.”

str2 = ‘Some other string.’

# Multiple assignment:

a, b, c = 3, 5, 7

# Interpolating values in strings:

puts “The sum is #{a+b+c}”

Page 14: name name2 n2

Some More Syntax

var = 123 # Local variable

$var = 234 # Global variable

PI = 3.14159 # Constant

# Note that variables don’t have types!

var = “xyz” # redefined

# Note that constants really aren’t.

PI = 3.1416 # Gives a warning

Page 15: name name2 n2

Loops

for index in 1..9 do puts “Iteration #{index}”end

1.upto(9) {|index| puts index }

index = 1while index < 9 do puts index index += 1end

loop { puts “Infinite loop.” }

Page 16: name name2 n2

Conditionsif x < 5 puts “yes” else puts “no” endunless x < 5 puts “no” else puts “yes” end

if x < 5 then puts “yes” else puts “no” endunless x < 5 then puts “no” else puts “yes” end

y = if x < 5 then 23 else 45 endy = unless x < 5 then 45 else 23 endy = x < 5 ? 23 : 45

Page 17: name name2 n2

Loop and condition modifier forms

puts “Error!” if x < 5

puts “Error!” unless x >= 5

do_something while notFinished

do_something until finished

Page 18: name name2 n2

Syntax Sugar and More

• for loop calls default iterator each• x += y is shorthand for x = x + y

• Most operators are methods

• Aliases or synonyms are allowed

• Flexible quoting and array literals

• Method suffixes (? and !)

Page 19: name name2 n2

OOP in Ruby

• Everything is an object – no wrappers as in Java• Standalone functions are really methods of Object

• Code can be stored as objects• Singletons are permitted• Metaclasses• Data hiding: public, private, protected• Etc. …

Page 20: name name2 n2

A Simple Class

class Person def initialize(name, number) @name, @phone = name, number end def inspect “Name=#{@name} Phone=#{@phone}” endend

# Note that “new” invokes “initialize”

a1 = Person.new(“Bill Gates”, “1-800-666-0666”)a2 = Person.new(“Jenny”, “867-5309”)

# p is like print or puts but invokes inspect

p a2 # Prints “Name=Jenny Phone=867-5309”

Page 21: name name2 n2

Defining attributes

# Adding to previous example…

class Person attr_reader :name # Defines a “name” method attr_accessor :phone # Defines “phone” and # “phone=“ methodsend

person1 = a2.name # “Jenny”phone_num = a2.phone # “867-5309”a2.phone = “512 867-5309” # Value replaced…

p a2 # Prints “Name=Jenny Phone=512 867-5309”

Page 22: name name2 n2

Class-level entitiesclass Foobar @@count = 0 # Class variable

def initialize(str) @data = str @@count += 1 end

def Foobar.population # Class method @@count endend

a = Foobar.new(“lions”)b = Foobar.new(“tigers”)c = Foobar.new(“bears”)

puts Foobar.population # Prints 3

Page 23: name name2 n2

Inheritance

class Student < Person def initialize(name, number, id, major) @name, @phone = name, number @id, @major = id, major end def inspect super + “ID=#@id Major=#@major” endend

x = Student.new(“Mike Nicholas”, “555-1234”, “000-13-5031”, “physics”)

puts “yes” if x.is_a? Student # yesputs “yes” if x.is_a? Person # yes

Page 24: name name2 n2

Singleton objects

# Assume a “Celebrity” class

newsguy = Celebrity.new(“Dan Rather”)popstar = Celebrity.new(“Britney Spears”)superman = Celebrity.new(“Superman”)

class << superman def fly puts “Look, I’m flying! Woo-hoo!” endend

superman.fly # Look, I’m flying! Woo-hoo!newsguy.fly # Error!

Page 25: name name2 n2

Garbage Collection

• No need for destructors

• No memory deallocation, etc.

• Currently “mark and sweep” technique

• Plans for generational GC

Page 26: name name2 n2

Using method_missing

class OSwrapper

def method_missing(method, *args) system(method.to_s, *args) end

end

sys = OSwrapper.newsys.date # Sat Apr 13 16:32:00…sys.du “-s”, “/tmp” # 166749 /tmp

Page 27: name name2 n2

Modules in Ruby

• Used as mixins (substitute for multiple inheritance); features are “mixed in” to an existing class

• Used for interface polymorphism; existing class defines method(s) that will be called by the module methods (and vice versa)

• Used for namespace management

Page 28: name name2 n2

Modules as mixins

• An example of a “pure” mixin is the special Kernel module

• Because Kernel is mixed into Object, its methods are universally available (without receivers)

• In most cases, module methods call methods of the class into which they are mixed (interface polymorphism)

Page 29: name name2 n2

Modules for Interface Polymorphism

• Example is Enumerable, which implements methods such as min, max, find, and select

• These methods depend on the existence of the default iterator each and a method called <=> (used for comparing).

Page 30: name name2 n2

Modules for Namespace Management

• An example is the Math module

• It has many useful mathematical functions, but these are basically independent of any class or object

• Therefore Math is really never mixed into a class

• A similar example is the Process module

Page 31: name name2 n2

Module example 1

class MyCollection include Enumerable # interface polymorphism #…

def <=>(other) # Compare self to other somehow… # Return –1, 0, or 1 end

def each # Iterate through the collection and do # a yield on each one… end

end

Page 32: name name2 n2

Module example 2

# Namespace management

def sin puts “Pride, gluttony, bad commenting…”end

x = Math.sin(theta) # unrelated to “our” sin

User = Process.uid # uid of this process

Page 33: name name2 n2

Module example 3# A user-defined module

module FlyingThing def fly puts “Look, I’m flying!” endend

class Bat < Mammal include FlyingThing # A substitute for MI? #…end

x = Bat.newx.is_a? Bat # truex.is_a? Mammal # truex.is_a? FlyingThing # true

Page 34: name name2 n2

Programming Paradigms

• Functional Programming (FP): This is possible in a limited way in Ruby (for Haskell fans, etc.)

• Aspect-Oriented Programming (AOP): A library (AspectR) exists

• Design-by-Contract (DBC) as in Eiffel: An add-on library exists

• Design Patterns: The Singleton, Observer, Delegator, and others are already implemented; new ones are relatively easy to implement

• Extreme Programming (XP): Ruby’s flexible and dynamic nature makes it a natural for XP practices

Page 35: name name2 n2

Cool Features in Ruby

• Iterators (as in CLU)• A rich class set• Open classes• Exceptions• Easy extension in Ruby• Operator overloading• Reflection or dynamic features• Threads• The Bignum class• Continuations• Easy extension in C

Page 36: name name2 n2

A Rich Set of Classes

• Array• Exception• File• Hash• IO• Proc• Range• Regexp• String• Struct

• And others…

Page 37: name name2 n2

A Closer Look at Some Classes…• Array instance methods:

& * + - << <=> == === [ ] [ ]= | assoc at clear collect collect! compact compact! concat delete delete_at delete_if each each_index empty? eql? fill first flatten flatten! include? index indexes indices join last length map! nitems pack pop push rassoc reject! replace reverse reverse! reverse_each rindex shift size slice slice! sort sort! to_a to_ary to_s uniq uniq! unshift

• IO class and instance methodsforeach new pipe popen readlines select << binmode clone close close_read close_write closed? each each_byte each_line eof eof? fcntl fileno flush getc gets ioctl isatty lineno lineno= pid pos pos= print printf putc puts read readchar readline readlines reopen rewind seek stat sync sync= sysread syswrite tell to_i to_io tty? ungetc write

• String instance methods% * + << <=> == === =~ [ ] [ ]= ~ capitalize capitalize! center chomp chomp! chop chop! concat count crypt delete delete! downcase downcase! dump each each_byte each_line empty? gsub gsub! hash hex include? index intern length ljust next next! oct replace reverse reverse! rindex rjust scan size slice slice! split squeeze squeeze! strip strip! sub sub! succ succ! sum swapcase swapcase! to_f to_i to_s to_str tr tr! tr_s tr_s! unpack upcase upcase! upto

Page 38: name name2 n2

Iterators• An iterator is a method that can take a code block

as a parameter; control is passed back and forth as though they were coroutines.

• The “standard” iterator is called each; this can also be called implicitly through a for statement. Example: list = [1, 2, 3, 4, 5] list.each do {|x| puts x if x > 3 } # Equivalently… for x in list puts x if x > 3 end

• Many classes have other predefined iterators such as foreach, each_byte, reverse_each, and so on.

Page 39: name name2 n2

Iterators That Don’t Iterate

• Sometimes the term “iterator” is not truly accurate; it may serve to enclose a block of code and isolate its context.The canonical example:

f = File.open(“somefile”) # Requires a close # But…

File.open(“somefile”) do |f| # Process the file as needed; it will be # closed automatically at end of block end

• Other examples:

mutex.synchronize do # Perform thread-sensitive operation, then # release the mutex end

Dir.chdir(“/tmp”) do # Temporarily change current directory end

Page 40: name name2 n2

Defining Your Own Iteratorsclass Array

# Iterate only over an array’s even-# numbered indices…

def every_other if block_given? self.each_with_index do |x,i| yield(x) if i % 2 == 0

end

else

raise “No block specified!”

end

end

arr = [11,23,35,47,59,61,73]

arr.every_other {|obj| puts obj }

# Prints 11 35 59 73

arr2 = []

arr.every_other {|obj| arr2 << obj }

# arr2 is now [11,35,59,73]

Page 41: name name2 n2

Interesting Example #1

• In this code fragment source.each { |line| process(line) }What is source? We can’t tell!

• It could be anything that has an iterator each and returns a line at a time.

• It could be a string with embedded newlines.

• It could be a file or other IO object.

• In a sense, we care less about its real “type” or “class” than we care about the methods it implements.

Page 42: name name2 n2

Interesting Example #2

• The POP3 email library defines a POPMail class that has a method called all (to process the entire contents of the message). This method acts as an iterator if it is used with a block: msg.all {|line| puts line }

• Otherwise it uses the append operator (<<) on whatever object was passed to it. Thus the object can be any object that responds to the << message:

arr = [] str = “” out = $stdout msg.all(arr) # Produce an array of lines msg.all(str) # or a string with embedded newlines msg.all(out) # Write each line to stdout

Page 43: name name2 n2

Open Classes

This means that predefined classes can beadded to or modified at will.

Example:

class String def rot13 self.tr(“A-Ma-mN-Zn-z”,”N-Zn-zA-Ma-m”) end end

text = “Elvis is dead.” secret = text.rot13 # Ryivf vf qrnq.

Page 44: name name2 n2

Exceptions

• Help obviate the need for return codes

• Help eliminate spaghetti “if” logic• Example forms:

raise raise “Any error message.” raise ArgumentError raise ArgumentError, “Bad data.” raise ArgumentError.new(“Bad data.”) raise ArgumentError, “Bad data”, caller[0]

Page 45: name name2 n2

Catching Exceptions, Part 1

begin

x = Math.sqrt(y/z)

# …

rescue ArgumentErrorputs “Error taking square root.”

rescue ZeroDivisionError

puts “Tried to divide by zero.”

end

Page 46: name name2 n2

Catching Exceptions, Part 2: The General Form

begin

# …

rescue SomeExceptionType

# Can attempt recovery with “retry”

rescue SomeOtherType

# Same thing, different exception…

else

# All other exception types

ensure

# Code here is ALWAYS executed

end

Page 47: name name2 n2

Other Forms of rescue• Inside a method definition:

def mymethod # Code… rescue # Handle any exceptions… end

• Capturing in a variable begin #… rescue SomeType => exc puts exc.message end

• As a one-liner (modifier form) x = y/z rescue puts “Division by zero!”

Page 48: name name2 n2

Easy Extension (in Ruby)

• Often we can “play” with new features before adding them to the core language.

• Matz doesn’t have to change the interpreter.

• We don’t have to write a C extension.

Page 49: name name2 n2

Example: Smalltalk-like inject

# A Smalltalk-like “inject” method for arraysclass Array def inject(initial) result = initial self.each {|x| result = yield(x, result) } result endend

nums = [1,2,3,4]sum = arr.inject(0) {|x,acc| acc+x }prod = arr.inject(1) {|x,acc| acc*x }

words = [“red”, “green”, “blue”]list = words.inject(“Words:”) {|x,acc| acc+“ ”+x }# list is now: “Words: red green blue”

Page 50: name name2 n2

Example: Invert Array to Form Hash

class Array

def invert

h={}

self.each_with_index{|x,i| h[x]=i}

h

end

end

a = %w[red green blue]

h = a.invert

# {“blue”=>2, “green”=>1, “red”=>0}

Page 51: name name2 n2

Example: Sorting by an Arbitrary Key

# Assume class Person with name, age, and height

class Array def sort_by(sym) self.sort {|x,y| x.send(sym) <=> y.send(sym)} end end

list = [Person.new("Hansel", 35, 69), Person.new("Gretel", 32, 64), Person.new("Ted", 36, 68), Person.new("Alice", 33, 63)]

# Sorted lists…s1 = people.sort_by(:name)s2 = people.sort_by(:age)s3 = people.sort_by(:height)

# s1 is [Alice 33 63, Gretel 32 64, Hansel 35 69, Ted 36 68] # s2 is [Gretel 32 64, Alice 33 63, Hansel 35 69, Ted 36 68] # s3 is [Alice 33 63, Gretel 32 64, Ted 36 68, Hansel 35 69]

Page 52: name name2 n2

Example: Existential Quantifiers

module Quantifier def any? self.each { |x| return true if yield x } false end

def all? self.each { |x| return false if not yield x } true end end

class Array include Quantifierend

list = [1, 2, 3, 4, 5] flag1 = list.any? {|x| x > 5 } # false flag2 = list.any? {|x| x >= 5 } # true flag3 = list.all? {|x| x <= 10 } # true flag4 = list.all? {|x| x % 2 == 0 } # false

Page 53: name name2 n2

Example: Selective File Deletion

def delete_if(dir) Dir.chdir(dir) do Dir.foreach(“.”) do |entry| next if File.directory?(entry) # Skip dirs File.unlink(entry) if yield(entry) end endend

# Delete files over 5K in sizedelete_if(“/tmp”) {|f| File.size(f) > 5000 }

# Delete log and tmp files delete_if(“/tmp”) {|f| f =~ /(log|tmp)$/i }

# Delete files over 24 hours olddelete_if(“/home/bill”) {|f| (Time.now-File.mtime(f))>86400 }

Page 54: name name2 n2

Other Possible Examples(of Extending Ruby in Ruby)

• Autovivification of hashes and arrays

• One-based arrays

• Better multidimensional array syntax

• Hash-like constructs that allow duplicates

• Design-by-contract features

• AOP features

• …and much more

Page 55: name name2 n2

Dynamic Features of Ruby

• Dynamic code evaluation (eval, instance_eval, class_eval, and module_eval)

• Queries or reflection (finding a class’s methods and so on)

• Hooks (modifying “behind the scenes” behavior)• Callbacks (finding out when something happens,

e.g., when a variable is modified)

Page 56: name name2 n2

Operator Overloading

• Most operators can be redefined• Example:

# Assume a class Length with feet and inchesclass Length #… def +(other) f = self.feet + other.feet i = self.inches + other.inches if i > 12 then i -= 12; f += 1 end Length.new(f,i) endend

board1 = Length.new(5,10)board2 = Length.new(8,9)total = board1 + board2

p total # 14’ 7”

Page 57: name name2 n2

Operator Overloading, ex. 2

class File

def <<(args) self.print(*args) self # Return the file object!

end

end

f = $stdout

f << “The time is “ << Time.now << “ currently.\n”

Page 58: name name2 n2

The Bignum class

• A Fixnum will transparently “roll over” into a Bignum – an arbitrary-precision integer

• Example: a, b, c, d, e, f = 237, 365, 451, 666, 2001, 24601

product = a*b*c*d*e*f

puts product

# Output: 1279062690897238830

square = product**2

# Output: 1636001367245285523749542918059768900

cube = product**3

# Output:

# 2092548311100316744450709557388954690847073917906387000

Page 59: name name2 n2

Threads in Ruby

• Ruby threads allow platform-independent multithreading of applications

• As such, they are non-native (not pthreads, for example)

• They do not take advantage of multiple processors• They can be started, stopped, synchronized, and

killed by means of a number of predefined methods

• For more sophisticated synchronization, there are add-on libraries available such as monitor.rb

Page 60: name name2 n2

Thread Example 1# Thinking ahead during chess…responses = {} # move-response hash humans_turn = true thinking_ahead = Thread.new(board) do predictMove do |m| responses[m] = myResponse(board,m) Thread.exit if humans_turn == false end end

human_move = getHumanMove(board) humans_turn = false # Stop the thread gracefully

# Now we can access “responses” which may contain # the move the person just made...

Page 61: name name2 n2

Thread Example 2

# A simple threaded server…

require "socket"

PORT = 9999

server = TCPServer.new(PORT)

while (session = server.accept)

Thread.new(session) do |my_session|

#…

my_session.close

end

end

Page 62: name name2 n2

ContinuationsContinuations are similar to setjmp and longjmp in C; we can do anon-local jump to another context. Contrived example:

def mymethod(cont) puts "Line 2" cont.call # "long jump" puts "Line 3" end

callcc do |cc| # a Kernel method puts "Line 1" mymethod(cc) puts "Line 4" end

puts “Line 5” # Here's the return point

# Output: # Line 1 # Line 2 # Line 5

Page 63: name name2 n2

Extending Ruby in C

• Every Ruby object is accessed as a VALUE (either an immediate value or a pointer)

• The only header file needed is ruby.h• Various rb_* functions correspond to Ruby

operations (rb_ary_push, rb_define_var, and so on)

• C datatype wrapping is accomplished with Data_Wrap_Struct, Data_Make_Struct, and Data_Make_Struct

• Rumor has it, it is much easier to extend Ruby than Perl

Page 64: name name2 n2

Ruby’s Weaknesses

• “Now, the bad news…”• Some external add-ons (libraries, tools, utilities) of

the language are immature, incomplete, or missing• Many things are still documented only in Japanese• There are some “issues” with Windows platforms• The Ruby Application Archive (RAA) is not

nearly so comprehensive as the CPAN as yet• User base is limited and expertise is rare• Industry acceptance is limited as yet• “And now, back to our regularly scheduled

program…”

Page 65: name name2 n2

Libraries and Utilities• The “one true repository” is the Ruby Application

Archive (RAA) accessible from www.ruby-lang.org; this includes…

• HTTP, CGI, XML, and related libraries• Network and distributed app libraries• Development tools (editors, browsers, simple

IDEs, syntax highlighting files, debuggers, etc.)• Database apps and interfaces• GUI, graphics, sound, multimedia in general• MS Windows-related libraries• Numerical and scientific libraries• Documentation

Page 66: name name2 n2

Ruby and MS Windows

• The WIN32API library gives access to the entire Windows API (should you be so bold)

• The WIN32OLE library provides a Ruby interface for OLE automation

• ActiveScriptRuby allows Ruby to interface (for example) with the WSH

• RubyCOM is like a Ruby-to-COM bridge, allowing Ruby to reference VB objects and vice versa

Page 67: name name2 n2

Who’s Into Ruby…

• Dave Thomas and Andy Hunt (the “Pragmatic Programmers”); authors of The Pragmatic Programmer and Programming Ruby

• Ron Jeffries and Chet Hendrickson, XP gurus and co-authors of Extreme Programming Installed

• Dan Sugalski, developer for Parrot (the upcoming Perl/Python/Ruby runtime environment)

• …and a growing user community on comp.lang.ruby!

Page 68: name name2 n2

Web Resources

• www.ruby-lang.org The master site for all things Ruby-related, including the RAA

• www.rubycentral.com Dave and Andy’s site; very useful info and links

• www.rubygarden.org A Ruby wiki and a wealth of information

• www.rubyhacker.com My personal site, still under development

Page 69: name name2 n2

Print Resources

• Programming Ruby, Dave Thomas and Andy Hunt, Addison-Wesley, 2000.

• Ruby in a Nutshell, Yukihiro Matsumoto, O’Reilly, 2001.

• The Ruby Way, Sams Publishing, Hal Fulton, 2001.

• The Ruby Developer’s Guide, Syngress, Michael Neumann et al., 2002.

• Teach Yourself Ruby in 21 Days, Sams Publishing, Mark Slagell, 2002.

Page 70: name name2 n2

The Ruby Way Table of Contents

1. Ruby in Review2. Simple Data Tasks3. Manipulating Structured Data4. External Data Manipulation5. OOP and Dynamicity in Ruby6. Graphical Interfaces for Ruby7. Ruby Threads8. Scripting and System Administration9. Network and Web Programming

A. From Perl to RubyB. From Python to RubyC. Tools and UtilitiesD. Resources on the Web (and Elsewhere)E. What’s New in Ruby 1.8

More than 300 sectionsMore than 500 code fragments and full listingsMore than 10,000 lines of codeAll significant code fragments available in an archive

Page 71: name name2 n2

exit(0) # That’s all, folks!