#Arrays a = [1, 2, "hi", :yo] #anything goes a[0] # 1 a[-1] # :yo, negative counts from end a.length # 4 a[1..3] # [2, "hi", :yo] This is a Range a[1...3] # [2, "hi"] Three dots exclude end digits = 0..9 digits.include?(5) # true digits.min # 0 digits.max # 9 digits.reject {|i| i < 5} # [5,6,7,8,9] digits.each {|digit| puts digit} #prints 0 to 9 #Hashes h={:grade => 88, 'name' => 'Peter', :age => 23} h['name'] # "Peter" h['grade'] # nil h[:grade] # 88 #Numbers 6.times do puts "Hi" #writes it 6 times. end 1.upto(5) {print "hi"} 99.downto(95) {print "hi"} 50.step(80.5) {print "hi"} #Regular expressions, like Perl b = /^\s*[a-z]/ #define a regexp name = "Fats Waller" name =~ /a/ # 1, it contains a name =~ /z/ # 0, but not z /a/ =~ name # 1 #Sideffect of a match is setting variables: $& #contains the text of the match
6.times do puts "Hi" #writes it 6 times. end #prints a b c d each on a new line ['a', 'b', 'c', 'd'].each do |i| puts i end #the same for i in ['a', 'b', 'c', 'd'] puts i end #This is how we get input from user while line = gets # do stuff end file = File.open("filename") while line = file.gets # do stuff break #goes to first line after loop redo #repeats loop at the current iteration next #skips to next iteration retry #restarts loop from first iteration end #Mostly, use the class's iterators: each
class Song # The constructor: def initialize(name, artist, duration) @name = name #instance variables start with @ @artist = artist @duration = duration end #defalt method for turning this instance to a string def to_s "Song: #@name--#@artist (#@duration)" #perl-like replacement, no return. end end # Uses 'new' song = Song.new("Re: Your Brains", "Jonathan Coulton", 272) # Write to stdout puts song #Song: Re: Your Brains--Jonathan Coulton (272) song.name = "new title" # This fails! by default they are private. puts song.name # This also fails. # Subclass Song class KaraokeSong < Song def initialize(name, artist, duration, lyrics) super(name, artist, duration) #call parent constructor @lyrics = lyrics end def to_s super + " [#@lyrics]" end end
class Song attr_reader :name # If it starts with : then its a symbol attr_writer :name, :artist @@plays = 0 # Class variables start with @@ # The constructor: def initialize(name, artist, duration) @name = name @artist = artist @duration = duration end def to_s "Song: #@name--#@artist (#@duration)" #perl-like replacement, no return. end def Song.maxLength # Class methods start with the class name 5000 end end song = Song.new("Re: Your Brains", "Jonathan Coulton", 272) puts song #Song: Re: Your Brains--Jonathan Coulton (272) song.artist = "Me" # This fails! by default they are private. puts song #Song: Re: Your Brains--Me (272) puts Song.maxLength # 5000
class Accounts def initialize(checking, savings) @checking = checking @savings = savings end private #keyword def debit(account, amount) account.based -= amount end def credit(account, amount) account.balance += amount end public #keyword def transfer_to_savings(amount) debit(@checking, amount) credit(@savings, amount) end end
#There is a lot of flexibility! def my_method(a,b,c) puts a + " " + b + " " + c end my_method( 'j', 'o', 'e') # j o e #default args def get_data(name="peter") "#{name}" end get_data #peter get_data("john") #john #Variable number of arguments def varargs(first, *rest) "Got #{first} and #{rest.join(', ')}" end varargs("one") #Got one and varargs("one", "two", "three")#Got one and two, three varargs "one", "two", "three" #Got one and two, three
#EVERY method takes a optional block as its last argument. #A block is either a function ['paul', 'john', 'ringo', 'george'].each do puts 'hi' end #Or, if it starts with |x| then x iterates: ['paul', 'john', 'ringo', 'george'].each do |x| puts x end # the same thing, but with {} ['paul', 'john', 'ringo', 'george'].each { |x| puts x } #You use these for iterators class Grades # *grades will mash up all arguments into an array. def initialize (*grades) @grades = grades end #This method takes no argument BUT # like all methods takes an optional block argument # at the end (block is ALWAYS the last argument). def hiToEach () @grades.length.times do yield #calls the block. end end #This time pass the block a value (i). This method is thus an iterator def eachGrade() @grades.each do |i| yield(i) end end #Of course, the iterator can take arguments def eachBiggerThan(x) if block_given? #use this to check if we are given a block @grades.each do |i| yield(i) if (i >= x) end else puts "You forgot the block!" end end end g = Grades.new(88,99,80,77,87) g.hiToEach {puts "hi"} #prints "hi" 5 times #Use the iterator. Notice that this block starts with |x| #Prints out: 105.6 118.8 96.0 92.4 104.4 g.eachGrade do |x| puts x * 1.2 end #Prints out 88 99 87 g.eachBiggerThan(85) do |x| puts x end g.eachBiggerThan(85) # You forgot the block!
class Student def initialize @data = {} #empty hash @grades = [] #empty array end def addThreeGrades(a,b,c) @grades.push(a) @grades.push(b) @grades.push(c) end def addData(d) d.each do |key, value| @data[key] = value end end def eachGrade @grades.each do |g| yield(g) end end end s = Student.new() g = [70,80,90] #The * before the g blows up the array into arguments s.addThreeGrades(*g) # Adds all these to @data hash table s.addData :name => "joe", :id => "12345", :year => 3 #Add another one s.addData :major => "CSCE" #Create a Proc object. prints x*2 timesTwo = lambda {|x| puts x * 2} #To pass a Proc as a block it must be preceeded by & # and be the last argument. s.eachGrade(×Two) #140 160 180, each on a new line
module MyLibrary #In here I can define my classes, etc. end #Modules can also be used as mixins. #Define a mixin module Debug def who_am_i? "#{self.class.name} (\##{self.object_id}): #{self.to_s}" end end #If Debug was in another file would would have need to require Debug #Use the mixin class Phonograph include Debug #adds the mixin. This just adds a dynamic link #.... end ph = Phonograph.new("West End Blues") ph.who_am_i? # Phonograph (#942232): West End Blues
class Song include Comparable #a built-in mixin, requires me to define <=> attr_reader :duration #so I can access other.duration def initialize(name, artist, duration) @name = name @artist = artist @duration = duration end def <=>(other) return @duration <=> other.duration end end s1 = Song.new('a', 'a', 100) s2 = Song.new('a', 'a', 200) s1 <=> s2 # -1 s1 < s2 #true s1 > s2 #false
This talk available at http://jmvidal.cse.sc.edu/talks/ruby/
Copyright © 2008 José M. Vidal
.
All rights reserved.
12 March 2008, 02:00PM