Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
SlideShare a Scribd company logo
Ruby for Perl programmers for Perl programmers Ruby All material Copyright Hal E. Fulton, 2002. Use freely but acknowledge the source.
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
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
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
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
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”
Disclaimer: I am not an expert in Perl.
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
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
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
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__
Enough! Let’s see some code. The Obligatory  Hello, world!  Program:   puts “Hello, world!” or   print “Hello, world!”
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}”
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
Loops   for index in 1..9 do puts “Iteration #{index}” end 1.upto(9) {|index| puts index } index = 1 while index < 9 do puts index index += 1 end loop { puts “Infinite loop.” }
Conditions if x < 5  puts “yes”  else  puts “no”  end unless x < 5  puts “no”  else  puts “yes”  end if x < 5 then puts “yes” else puts “no” end unless x < 5 then puts “no” else puts “yes” end y = if x < 5 then 23 else 45 end y = unless x < 5 then 45 else 23 end y = x < 5 ? 23 : 45
Loop and condition modifier forms puts “Error!” if x < 5 puts “Error!” unless x >= 5 do_something while notFinished do_something until finished
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  ! )
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. …
A Simple Class class Person def initialize(name, number)   @name, @phone = name, number end   def inspect “ Name=#{@name} Phone=#{@phone}” end end # 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”
Defining attributes # Adding to previous example… class Person attr_reader :name  # Defines a “name” method attr_accessor :phone  # Defines “phone” and   # “phone=“ methods end 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”
Class-level entities class Foobar @@count = 0  # Class variable def initialize(str)   @data = str @@count += 1 end   def Foobar.population  # Class method @@count end end a = Foobar.new(“lions”) b = Foobar.new(“tigers”) c = Foobar.new(“bears”) puts Foobar.population  # Prints 3
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” end end x = Student.new(“Mike Nicholas”, “555-1234”, “ 000-13-5031”, “physics”) puts “yes” if x.is_a? Student  # yes puts “yes” if x.is_a? Person  # yes
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!” end end superman.fly  # Look, I’m flying! Woo-hoo! newsguy.fly  # Error!
Garbage Collection No need for destructors No memory deallocation, etc. Currently “mark and sweep” technique Plans for generational GC
Using  method_missing class OSwrapper def method_missing(method, *args) system(method.to_s, *args) end end sys = OSwrapper.new sys.date  # Sat Apr 13 16:32:00… sys.du “-s”, “/tmp”  # 166749 /tmp
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
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)
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).
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
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
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
Module example 3 # A user-defined module module FlyingThing def fly   puts “Look, I’m flying!” end end class Bat < Mammal include FlyingThing  # A substitute for MI? #… end x = Bat.new x.is_a? Bat  # true x.is_a? Mammal  # true x.is_a? FlyingThing  # true
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
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
A Rich Set of Classes Array Exception File Hash IO Proc Range Regexp String Struct And others…
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 methods foreach 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
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.
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
Defining Your Own Iterators class 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]
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.
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
Open Classes This means that predefined classes can be added 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.
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]
Catching Exceptions, Part 1 begin x = Math.sqrt(y/z) # … rescue ArgumentError puts “Error taking square root.” rescue ZeroDivisionError puts “Tried to divide by zero.” end
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
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!”
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.
Example: Smalltalk-like  inject # A Smalltalk-like “inject” method for arrays class Array def inject(initial) result = initial self.each {|x| result = yield(x, result) } result end end 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”
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}
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(&quot;Hansel&quot;, 35, 69),  Person.new(&quot;Gretel&quot;, 32, 64), Person.new(&quot;Ted&quot;, 36, 68),  Person.new(&quot;Alice&quot;, 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]
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 Quantifier end 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
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 end end # Delete files over 5K in size delete_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 old delete_if(“/home/bill”) {|f| (Time.now-File.mtime(f))>86400 }
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
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)
Operator Overloading Most operators can be redefined Example: # Assume a class Length with feet and inches class 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)   end end board1 = Length.new(5,10) board2 = Length.new(8,9) total  = board1 + board2 p total  # 14’ 7”
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.”
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
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
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...
Thread Example 2 # A simple threaded server… require &quot;socket&quot;  PORT = 9999 server = TCPServer.new(PORT)  while (session = server.accept)  Thread.new(session) do |my_session|  #… my_session.close  end  end
Continuations Continuations are similar to  setjmp  and  longjmp  in C; we can do a non-local jump to another context. Contrived example: def mymethod(cont) puts &quot;Line 2&quot; cont.call  # &quot;long jump&quot; puts &quot;Line 3&quot; end callcc do |cc|  # a Kernel method puts &quot;Line 1&quot; mymethod(cc) puts &quot;Line 4&quot; end puts “Line 5”  # Here's the return point # Output: # Line 1 # Line 2 # Line 5
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
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…”
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
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
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!
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
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.
The Ruby Way Table of Contents 1.  Ruby in Review 2.  Simple Data Tasks 3.  Manipulating Structured Data 4.  External Data Manipulation 5.  OOP and Dynamicity in Ruby 6.  Graphical Interfaces for Ruby 7.  Ruby Threads 8.  Scripting and System Administration 9.  Network and Web Programming A.  From Perl to Ruby B.  From Python to Ruby C.  Tools and Utilities D.  Resources on the Web (and Elsewhere) E.  What’s New in Ruby 1.8 More than 300 sections More than 500 code fragments and full listings More than 10,000 lines of code All significant code fragments available in an archive
exit(0)  # That’s all, folks!

More Related Content

ppt2

  • 1. Ruby for Perl programmers for Perl programmers Ruby All material Copyright Hal E. Fulton, 2002. Use freely but acknowledge the source.
  • 2. 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
  • 3. 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
  • 4. 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
  • 5. 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
  • 6. 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”
  • 7. Disclaimer: I am not an expert in Perl.
  • 8. 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
  • 9. 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
  • 10. 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
  • 11. 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__
  • 12. Enough! Let’s see some code. The Obligatory Hello, world! Program: puts “Hello, world!” or print “Hello, world!”
  • 13. 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}”
  • 14. 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
  • 15. Loops for index in 1..9 do puts “Iteration #{index}” end 1.upto(9) {|index| puts index } index = 1 while index < 9 do puts index index += 1 end loop { puts “Infinite loop.” }
  • 16. Conditions if x < 5 puts “yes” else puts “no” end unless x < 5 puts “no” else puts “yes” end if x < 5 then puts “yes” else puts “no” end unless x < 5 then puts “no” else puts “yes” end y = if x < 5 then 23 else 45 end y = unless x < 5 then 45 else 23 end y = x < 5 ? 23 : 45
  • 17. Loop and condition modifier forms puts “Error!” if x < 5 puts “Error!” unless x >= 5 do_something while notFinished do_something until finished
  • 18. 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 ! )
  • 19. 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. …
  • 20. A Simple Class class Person def initialize(name, number) @name, @phone = name, number end def inspect “ Name=#{@name} Phone=#{@phone}” end end # 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”
  • 21. Defining attributes # Adding to previous example… class Person attr_reader :name # Defines a “name” method attr_accessor :phone # Defines “phone” and # “phone=“ methods end 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”
  • 22. Class-level entities class Foobar @@count = 0 # Class variable def initialize(str) @data = str @@count += 1 end def Foobar.population # Class method @@count end end a = Foobar.new(“lions”) b = Foobar.new(“tigers”) c = Foobar.new(“bears”) puts Foobar.population # Prints 3
  • 23. 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” end end x = Student.new(“Mike Nicholas”, “555-1234”, “ 000-13-5031”, “physics”) puts “yes” if x.is_a? Student # yes puts “yes” if x.is_a? Person # yes
  • 24. 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!” end end superman.fly # Look, I’m flying! Woo-hoo! newsguy.fly # Error!
  • 25. Garbage Collection No need for destructors No memory deallocation, etc. Currently “mark and sweep” technique Plans for generational GC
  • 26. Using method_missing class OSwrapper def method_missing(method, *args) system(method.to_s, *args) end end sys = OSwrapper.new sys.date # Sat Apr 13 16:32:00… sys.du “-s”, “/tmp” # 166749 /tmp
  • 27. 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
  • 28. 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)
  • 29. 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).
  • 30. 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
  • 31. 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
  • 32. 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
  • 33. Module example 3 # A user-defined module module FlyingThing def fly puts “Look, I’m flying!” end end class Bat < Mammal include FlyingThing # A substitute for MI? #… end x = Bat.new x.is_a? Bat # true x.is_a? Mammal # true x.is_a? FlyingThing # true
  • 34. 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
  • 35. 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
  • 36. A Rich Set of Classes Array Exception File Hash IO Proc Range Regexp String Struct And others…
  • 37. 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 methods foreach 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
  • 38. 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.
  • 39. 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
  • 40. Defining Your Own Iterators class 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]
  • 41. 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.
  • 42. 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
  • 43. Open Classes This means that predefined classes can be added 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.
  • 44. 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]
  • 45. Catching Exceptions, Part 1 begin x = Math.sqrt(y/z) # … rescue ArgumentError puts “Error taking square root.” rescue ZeroDivisionError puts “Tried to divide by zero.” end
  • 46. 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
  • 47. 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!”
  • 48. 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.
  • 49. Example: Smalltalk-like inject # A Smalltalk-like “inject” method for arrays class Array def inject(initial) result = initial self.each {|x| result = yield(x, result) } result end end 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”
  • 50. 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}
  • 51. 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(&quot;Hansel&quot;, 35, 69), Person.new(&quot;Gretel&quot;, 32, 64), Person.new(&quot;Ted&quot;, 36, 68), Person.new(&quot;Alice&quot;, 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]
  • 52. 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 Quantifier end 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
  • 53. 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 end end # Delete files over 5K in size delete_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 old delete_if(“/home/bill”) {|f| (Time.now-File.mtime(f))>86400 }
  • 54. 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
  • 55. 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)
  • 56. Operator Overloading Most operators can be redefined Example: # Assume a class Length with feet and inches class 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) end end board1 = Length.new(5,10) board2 = Length.new(8,9) total = board1 + board2 p total # 14’ 7”
  • 57. 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.”
  • 58. 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
  • 59. 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
  • 60. 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...
  • 61. Thread Example 2 # A simple threaded server… require &quot;socket&quot; PORT = 9999 server = TCPServer.new(PORT) while (session = server.accept) Thread.new(session) do |my_session| #… my_session.close end end
  • 62. Continuations Continuations are similar to setjmp and longjmp in C; we can do a non-local jump to another context. Contrived example: def mymethod(cont) puts &quot;Line 2&quot; cont.call # &quot;long jump&quot; puts &quot;Line 3&quot; end callcc do |cc| # a Kernel method puts &quot;Line 1&quot; mymethod(cc) puts &quot;Line 4&quot; end puts “Line 5” # Here's the return point # Output: # Line 1 # Line 2 # Line 5
  • 63. 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
  • 64. 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…”
  • 65. 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
  • 66. 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
  • 67. 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!
  • 68. 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
  • 69. 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.
  • 70. The Ruby Way Table of Contents 1. Ruby in Review 2. Simple Data Tasks 3. Manipulating Structured Data 4. External Data Manipulation 5. OOP and Dynamicity in Ruby 6. Graphical Interfaces for Ruby 7. Ruby Threads 8. Scripting and System Administration 9. Network and Web Programming A. From Perl to Ruby B. From Python to Ruby C. Tools and Utilities D. Resources on the Web (and Elsewhere) E. What’s New in Ruby 1.8 More than 300 sections More than 500 code fragments and full listings More than 10,000 lines of code All significant code fragments available in an archive
  • 71. exit(0) # That’s all, folks!

Editor's Notes

  1. Ruby for Perl programmers