ESA:Ruby
• Today:1.RubyintroducDon2.BasicRuby:types,variables,statements,...
3.ObjectOrientedRuby:class,modules,…4.DocumentaDon
IntroducDontoRuby
• RubywascreatedbyYukihiro• Matsumoto()a.k.a.“Matz”• Introducedin1994• OfficiallyreleasedbyMatsumotoin1995.• “Ruby”wasnamedasagemstoneasajoke...• TheTIOBEindex,whichmeasuresthegrowthof
programminglanguages,ranksRubyas#9amongprogramminglanguagesworldwide(2006)
“tryingtomakeRubynatural,notsimple,”“Rubyissimpleinappearance,butisverycomplex
inside,justlikeourhumanbody”
IntroducDontoRuby
• Rubyis"aninterpretedscrip9nglanguageforquickandeasyobject‐orientedprogramming"‐‐whatdoesthismean?
• interpretedscrip+nglanguage:– abilitytomakeoperaDngsystemcallsdirectly– powerfulstringopera9onsandregularexpressions– immediatefeedbackduringdevelopment
h`p://www.rubyist.net/~slagell/ruby/index.html
IntroducDontoRuby
• Rubyis"aninterpretedscripDnglanguageforquickandeasyobject‐orientedprogramming"‐‐whatdoesthismean?
• quickandeasy:– variabledeclaraDonsareunnecessary– variablesarenottyped– syntaxissimpleandconsistent
– memorymanagementisautomaDc
h`p://www.rubyist.net/~slagell/ruby/index.html
IntroducDontoRuby
• Rubyis"aninterpretedscripDnglanguageforquickandeasyobject‐orientedprogramming"‐‐whatdoesthismean?
• objectorientedprogramming:– everythingisanobject– classes,methods,inheritance,etc.
– "mixin"funcDonalitybymodule– iteratorsandclosures(h`p://www.arDma.com/intv/closures.html)
h`p://www.rubyist.net/~slagell/ruby/index.html
IntroducDontoRuby
• Rubyis"aninterpretedscripDnglanguageforquickandeasyobject‐orientedprogramming"‐‐whatdoesthismean?
• also:– mulDpleprecisionnumbers– convenientexcep9onprocessing– dynamicloading– threadingsupport.
h`p://www.rubyist.net/~slagell/ruby/index.html
Ruby,PerlandPython
• Designgoals– Expressivelikeperlbutbe`erObject‐OrientaDon– LikepythonbutimplemenDngtrueObject‐OrientaDon
– Noprimi9vetypes,everythingisanobject/class– Fullyscriptable
SimpleExample
#!/usr/bin/ruby
def power(x,n) result = 1
x = x*x n = n/2
end
return result end
RubyBasics
• NormalmethodforscripDngusing#!/usr/bin/ruby
• irbisaninteracDverubyinterpreter– Youcaninterpretsinglelinesofcode– Goodforsimplecheckinganddebugging
• YoucandocumentRubycodeusingtheRDocsystem– ThedocumentaDonisinsidethesourcefile– Itcanbeextractedusingri– TofindthedocumentaDonforaclasstype ri classname atthecommandprompt
Numbers
Simplenumbers:– binary,startwith0b:0b1100,‐0b10001,0b11111111...– decimal:12,‐17,255...– octal,startwith0:015,‐023,0777...– hexadecimal,startwith0x:0xc,‐0x11,0xff,...– floaDngpointnumbers: “oneandaquarter":1.25
– scienDficnotaDon:“7.25Dmes10tothe45thpower":7.25e45.
Butalsomatricesandcomplexnumbersusingseparatemodules
Strings(1)• Tocreatestringliterals,enclosetheminsingle,ordoublequotes.
• Examples: 'Hello Class of 2007' "Ruby is shiny”
• Thesametypeofquoteusedtostartthestringmustbeusedtoterminateit.
• Youcanhaveyourowndelimitersusing%%q!"I said 'nuts'", I said! # %q‐appliesthesimplequoterules %Q(It's like a " string,\n \\n is a newline) # %Qappliesthedoublequoterules
If you use () {} [] as delimiter you can use these delimiters as a text as long as they are in pairs
Strings(2)
• Escapesequencesforsinglequoted(')strings: only \\ and \’
• Fordoublequoted(‘”’)strings: \a, \b, \e, \f, \n, \r, \s, \t,
• Youcanembedrubycodeintoadoublequotedstringusing#{. . . }:
"Seconds/day: #{24*60*60}” Seconds/day: 86400
Strings(3)
• IntermiGantsingleanddoublequotedstringsareconcatenatedtooneobject: "'Well'" ', he said, ' '"How are you?"’ 'Well', he said, "How Are You?”
• YoucanconstructamulDlinestringusinga“heredocument”:
string = <<END_OF_STRING The Body of the string is the input lines up to one ending with the same text that followed the '<<' END_OF_STRING
VariablesandConstants
• Rubyvariablesandconstantsholdreferencestoobjects.
– Theobjectdecidesthetype,notthevariable– Reassignmentcanchangethetypeofthevariable
• Namingisasfollows:Constantsstartwitha[A-Z],theconvenDonisto
writeallcapswithunderscores
localvariables startwitha[a-z\_] globalvariablesstartwitha`$' instancevariablesstartwitha`@’ classvariables startwith`@@’
Predefinedvariables
• Mostpredefinedvariablescomefromperl
• Therearepredefinedvariablesfor:Input/Output($_, $., …) Pa`ernMatching($=, $1 to $9, …) ExecuDonEnvironment(Ruby specific) ($0, $”, …) ExcepDoninformaDon($!, $@) Standardobjects(true, false, ARGV, …) globalConstants(STDIN, STDOUT, …)
http://www.softlab.ntua.gr/facilities/documentation/unix/ruby-man-1.4/variable.html#equal
Stringvariables
• Stringvariablesareindexedlikelists,starDngat0• Youcanusethemusingtheindexoperator`[i]' a = "Hello World" b = a[4] # b = o
• Substringscanbeusedbypairnumbers:`[start,count]' c = a[0,6] # c = "Hello " d = a[7,4] # d = "orld"
e = a[3,5] # e = "lo Wo”
• Rangescanalsobeusedtospecifyindices.
Ranges
• Constructrangesofnumbersorcharacters
• UsedoubledotnotaDonforinclusiverangecreaDon: 1..5 [1, 2, 3, 4, 5]
• UsetripledotnotaDonforexclusiverangecreaDon: 1...5 [1, 2, 3, 4]
Exampleforstringvariables: a = "Hello World"
c = a[0..5] # c = "Hello " d = a[7..10] # d = "orld"
e = a[3...9] # e = ?
Arrays
• Arraysarearbitrarylistsofobjects• CreateanArrayusing[]: names = [“Fred”,2,"Flintstone”] • Theytooareindexed: a = names[1] # a is now 2
names[0] = “Wilma” # names is changed
• Usingarange: names[1..2] [ 2, "Flintstone" ]
Hashes(1)
• Ahashcontainsobjectsindexedbykeys.• Anyobjectcanbeusedasakeyorvalue,but...• Createahashbyenclosing`key => value’combinaDonsincurlybraces(`{...}'):
a = { "username" => "xenos", "home" => "/home/xenos”,
"uid" => 500
}
Hashes(2)
• Accessanyvalueusingit'skey:u = a["username"] # Returns "xenos" d = a["home"] # Returns "/home/xenos”
• Toinsertormodifyobjects,youassignavaluetoakey‐indexedname.a["username"] = "trixie"
a["home"] = "/home/trixie" a["shell"] = "/usr/bin/tcsh"
Hashes(3)
• Hashmembershipistestedwithseveralmethods:has_key?,has_value?,keys,values
a.has_key? "username” # return True a.has_value? "trixie” # return false a.keys # ["xenos", 500, “/usr/bin/tcsh”, "/home/xenos”]
a.values # ["username", "uid", "shell", "home"]
Expressions
• Singletermsare:– Literals(numbers,strings,arrays,hashes,ranges,symbols,RE's)– Shellcommands,usingbackquotes:`‘...‘`
files=‘ls*‘– Variableorconstantreferences
• Expressionblocksaredenotedbybegin/do . . . end • Theusualoperators:
+, -, *, /, %, **, !, …
• Mostoperatorsareimplementedasmethods(may be overridden)
Assignment
• Usingparallelassignmentyoucanforegotouseoftemporaryvariables: a = 1
b = 2 temp = a a = b b = temp
Usingparallelassignment: a, b = b, a
ComparisonOperators
== Testforequalvalue
=== Comparisonoperatorforthecasestatement<=> Generalcomparisonoperator(returns‐1,0,1)<,<=,>,>=Normalcomparisonoperators
=~ Regularexpressionmatcheql? Checksfortypeandvalueequalityequal?ChecksforObjectIDequality
Flowcontrol
• Codeblocksaredenotedby{...}ordo...endblocks
• CodeblockscanstartwithanargumentlistbetweenverDcalbars:|…|
• #!/usr/bin/rubypresidents=["Ford","Carter","Reagan","Bush1","Clinton”]presidents.each{|prez|putsprez}
• Flowcontrolcanbeexertedusingloopingorcondi9onalstatements.
LoopingStatements(1)• Thestandardconstructsarepresent:
while condition body end
• Usingabegin...endblockthesyntaxcanbereversed:
begin body end while condition
until condition body
end
begin body
end until condition
LoopingStatements(2)
• IteraDngoverthemembersofasequencecontaininganytypeofobject.
for i in [1,2,"three", 4, 5,'eleven', 7 ] print i," "
end • Youcanalsousearange: for i in 1..10 print i," " end
LoopingStatements(3)
• MoststandardobjecttypesalsoprovideiteratormethodsExamplesfornumbers:3.times do print "Hi! " end
0.upto(93) do print "Ha! " end
• Forarrays/files/etceterathereare:obj.each, obj.foreach, . . .
CondiDonalstatements(1)
• ifandunlessstatements:if test [ : | then] body
elsif test [ : | then ] body else body
end
• Youcanalsousethemonexpressionsasmodifiers:expression if test expression unless test
unless test [ : | then ] body
else body
end
CondiDonalStatements(2)
• casestatementcompareseachwhenclausetoatargetandexecutesthefirstmatch
case target when comparison [: | then] body when comparison [: | then] body . . . [else body ] end
h`p://ilikestu~log.com/2008/04/15/how‐to‐write‐case‐switch‐statements‐in‐ruby/
RegularExpressions
• RegularexpressionsareanobjectoftypeRegexp• Theycanbecreatedusing:
/ pattern / [options] %r{ pattern } [options] Regexp.new(' pattern ' [ , options] )
• MoststandardopDonsandpa`ernsareavailable• FormoreinformaDonseethedocumentaDon
• r1 = Regexp.new('^a-z+:\\s+\w+') #=> /^a-z+:\s+\w+/
a = "HELLO” case a
when /^[a-z]*$/; print "Lower case\n”
when /^[A-Z]*$/; print "Upper case\n” else; print "Mixed case\n”
end
Methods(1)
• Amethodcanhavearguments,theyarepassedtotheblockasanarray
• Amethodwillreturntheresultofthelastexecutedexpressionintheblockasthereturnvalue
• Thereturnexpressionwillexitthemethodimmediatelygivingitsargumentasareturnvalue
Methods(2)• AsimplemethoddefiniDonisasfollows:
def sayhi(name) print "Hi", name
End
• AdefiniDonusingpre‐ini9alizedarguments:
def options(a=99, b=a+1) [ a, b ] end
options [99, 100] options 1 [1, 2] options 2, 4 [2, 4]
Methods(3)
• supermethodisaspecialmethodforobjects– ItexecutesthefuncDonofthesamenameintheparentobject– toensurecrea9onorini9aliza9onofparentobjects
• superwithnoarguments– Rubysendsamessagetotheparentofthecurrentobject,– toinvokeamethodofthesamenameasthemethodinvokingsuper.– ItautomaDcallyforwardstheargumentsthatwerepassedtothe
methodfromwhichit'scalled.• super()withanemptyargumentlist
– itsendsnoargumentstothehigher‐upmethod,evenifargumentswerepassedtothecurrentmethod.
• super(a,b,c)withspecificarguments– itsendsexactlythosearguments.
Classes(1)
• ArubyclassisanextensionoftheclassClass• Classnamesstartwitha[A-Z] • Classescreateanewnamespace• Classescanbenested,buttheywillnotbemadeglobal,
soinstanDaDonrequiresthefullyqualifiedclassname• AsimpleexampledefiniDon:
class MyClass CONST = 12345 def f 'hello world' end end
Classes(2)
• Createaninstanceobjectfromaclassasfollows: obj = MyClass.new • TheclassClassdefinesamethodnewwhichisresponsiblefor
thecreaDonofanobjectoftheclass
– Thenewmethodmustcallthesupermethodtoallowtheparentclasstobeallocated,otherwisenoobjectsofthatclasscanbecreated.
• TheclassClassalsodefinesthemethodinitialize,whichwillbeinvokedinanewlycreatedobject,itwillreceivetheargumentspassedtonew.
– TheinitializemethodmustalsocallsuperiftheparentobjectistobeproperlyiniDalized
Classes(3)
• TouseamethodfromanobjectuseadotnotaDon:obj.f
• ToretrieveaconstantfromanobjectusethedoublecolonnotaDon:obj::CONST
• Examples: obj.f # hello world
obj::CONST # 12345
Classes(4)
Classvariables• classvariablesarevariablessharedbetweenallobjects
ofaclass
class Song @@plays = 0 def play @@plays += 1 "This song: Total #@@plays plays." end end
Classes(5)
Classmethods‐objectmethodsvs.classmethods‐aclassmayneedtoprovidemethodsthatworkwithoutbeingDedtoanyparDcularobject.ForexampleMyClass.new.
• Example
class Example def instMeth # instance method end def Example.classMeth # class method end end
Modules(1)
• Modulesareawayofgroupingtogethermethods,classes,andconstants.Modulesgiveyoutwomajorbenefits.– Modulesprovideanamespaceandpreventnameclashes.– Modulesimplementthemixinfacility.
• ARubyModuleisbasicallyaclassthatcannotbeinstan9ated
• MulDplemodulesmaybecreatedinasinglesourcefile• UsethedefiniDonsinamoduleinthesamewayyou
wouldan(instanDated)object• Aredefini9onofamoduleresultsinoverloadingthat
module
Modules(2)
• AmoduledefiniDon: CONST = "outer" module A CONST = 1 def A.method CONST + 1 end end
• QuesDons: CONST "outer" A::CONST 1 A.method 2
Modules(3)
• AmoduledefiniDonwithscopeinheritance:CONST = "outer" module B def B.method CONST + "scope"
end end
• QuesDon: B.method "outerscope”
Modules(4)
• ModulescanbeincludedinthedefiniDonofanothermoduleorclassuse:include <module‐name>
require <modules-name>
• Theincludingmodulewillhaveaccesstoallconstants,variables,methodsetceterafromtheincludedmodule
• Aclassmayalsoincludeamodule– Themodulewillbetreatedasasuperclassfortheclass
– Themodulecanalsocontainanini9alizemethod
Modules(5)
module SillyModule def hello
"Hello." end end
Question s.hello ”Hello”
class SillyClass include SillyModule
End
s = SillyClass.new
IncludingSourcefiles
• IncludeRubysourcefilesintoaprogramusingloadorrequire
Load loadsthereferencedfileeachDmeitiscalledUsefulfor(re)loadingsourcecodegeneratedatrun‐Dmerequire loadsthereferencedfileonlyoncerequireisastatement,itcanbeuseanywherestatements areallowed.Forinstancefromwithinanifstatement.
• Localvariablesinaloadedfilearenotpropagatedtothescopeoftheloadingfile
DocumentaDon
• BOOKS!,theyareinthebackoftheclassroom...
• Usetheweb,therearegoodwebsitesonruby• Checkh`p://www.ruby‐lang.org/forhelp.• h`p://www.ruby‐doc.org/docs/ruby‐doc‐bundle/index.html
• “ProgrammingRuby",canbefoundonlineviaabovelink
PlayAround
• writeafunc9onfacttocomputefactorials.– ThemathemaDcaldefiniDonofnfactorialis: n!=1(whenn==0)=n*(n‐1)!(otherwise)
• writeasimplerubyprogwithcasestatementwheregivenamodelofacaritprintsthebrand
• writeasimplerubyprogwitharrays,printtheelementofthearray,removeelements,prependelements– Hint:Rubyarrayshavemethodsshi�,unshi�,push,andpop)
• writeasimplerubywithcontrolstatementif.WhengivendemocratsitprintsthenamesofdemocratspresidentsinUSsince1976,sameforrepublicans
PlayAround
• writeaclassDecadeandamoduleWeektoprintthenumberofweeksinamonth,ayear,andthenumberofdaysinadecade(includetheWeekmoduleintheClassDecade)
–
• writeaclasswithrunDmeExcep9onhandling.IftheageofagivenpaDentisbellowacertainage,itgenerateanexcepDon.– Hints:useraisetogeneratetheexp,andrescuetocatchit
PlayAround
• writeafunc9onfacttocomputefactorials.– ThemathemaDcaldefiniDonofnfactorialis: n!=1(whenn==0)=n*(n‐1)!(otherwise)
# Program to find the factorial of a number # Save this as fact.rb def fact(n) if n == 0 1 else n * fact(n-1) end
end puts fact(ARGV[0].to_i)
PlayAround
• writeasimplerubyprogwithcasestatementwheregivenamodelofacaritprintsthebrandcar = "Patriot” manufacturer = case car when "Focus": "Ford" when "Navigator" then "Lincoln" when "Camry" then "Toyota" when "Civic" then "Honda" when "Patriot": "Jeep" when "Jetta" ; "VW" when "Ceyene” "Porsche” when "520i" then "BMW” else "Unknown" end puts "The " + car + " is made by " + manufacturer
PlayAround
• writeasimplerubyprogwitharrays,printtheelementofthearrayremoveelements,prependelements
• Hint:Rubyarrayshavemethodsshi�,unshi�,push,andpop)
#!/usr/bin/ruby presidents = ["Ford", "Carter", "Reagan", "Bush1", "Clinton", "Bush2"] presidents.each { |i| print i, "\n"}
#Remove 3 elements from the array #!/usr/bin/ruby
presidents = ["Ford", "Carter", "Reagan", "Bush1", "Clinton", "Bush2"]
presidents.pop presidents.pop presidents.pop presidents.each { |i| print i, "\n"}
PlayAround
• writeasimplerubyprogwitharrays,printtheelementofthearray,removeelements,andprependelements
• Hint:Rubyarrayshavemethodsshi�,unshi�,push,andpop)
#!/usr/bin/ruby presidents = ["Ford", "Carter", "Reagan", "Bush1", "Clinton", "Bush2"] presidents.each { |i| print i, "\n"}
#Prepend 3 elements to the array #!/usr/bin/ruby
presidents = ["Ford", "Carter", "Reagan", "Bush1", "Clinton", "Bush2”] presidents.unshift("Nixon") presidents.unshift("Johnson") presidents.unshift("Kennedy") presidents.each { |i| print i, "\n"}
PlayAround
• writeasimplerubywithcontrolstatementif.WhengivendemocratsitprintsthenamesofdemocratspresidentsinUSsince1976,sameforrepublicans
#!/usr/bin/ruby democrats = ["Carter", "Clinton”]
republicans = ["Ford", "Reagan", "Bush1", "Bush2”] party = ARGV[0]
if party == nil print "Argument must be \"democrats\" or \"republicans\"\n" elsif party == "democrats" democrats.each { |i| print i, " "} print "\n" elsif party == "republicans" republicans.each { |i| print i, " "} print "\n" else print "All presidents since 1976 were either Democrats or Republicans\n" end
PlayAround
• writeaclassDecadeandamoduleWeektoprintthenumberofweeksinamonth,ayear,andthenumberofdaysinadecade(includetheWeekmoduleintheClassDecade)
#!/usr/bin/ruby require "Week” class Decade
include Week no_of_yrs=10 def no_of_months puts Week::FIRST_DAY number=10*12 puts number end
end
!/usr/bin/ruby module Week FIRST_DAY = "Sunday"
def Week.weeks_in_month puts “four weeks in a month"
end
def Week.weeks_in_year
puts “52 weeks in a year"
end end
PlayAround
• writeaclassDecadeandamoduleWeektoprintthenumberofweeksinamonth,ayear,andthenumberofdaysinadecade(includetheWeekmoduleintheClassDecade)
#!/usr/bin/ruby require "Week” class Decade
include Week no_of_yrs=10 def no_of_months puts Week::FIRST_DAY number=10*12 puts number end
end
d1=Decade.new puts Week::FIRST_DAY Week.weeks_in_month Week.weeks_in_year d1.no_of_months
PlayAround• writeaclasswithrunDmeExcep9onhandling.IftheageofagivenpaDentis
bellowacertainage,itgenerateanexcepDon.• Hints:useraisetogeneratetheexp,andrescuetocatchit
class MedicareEligibilityException < RuntimeError def initialize(name, age) @name = name @age = age end def getName return @name end def getAge return @age end end … next page …
PlayAround
def writeToDatabase(name, age) # This is a stub routine
print "Diagnostic: ”,name, ”,age ", age, " is signed up.\n"
end def signHimUp(name, age)
if age >= 65 : writeToDatabase(name, age) else
myException =
MedicareEligibilityException.new(name, age) raise myException , "Must be 65 or older for Medicare", caller
End
end … next page …
PlayAround
# Main routine begin signHimUp("Oliver Oldster", 78)
signHimUp("Billy Boywonder", 18) signHimUp("Cindy Centurinarian", 100)
signHimUp("Bob Baby", 2)
rescue MedicareEligibilityException => elg print elg.getName, " is ", elg.getAge, ",
which is too young.\n" print "You must obtain an exception from
your supervisor. ", elg, "\n” end print "This happens after signHimUp was called.\n"
PlayAround• writeasimpleprogwithtwoclassesMammalandcatthecatClass
extendsMammal.•
# class Mammal def breathe puts "inhale and exhale" end end
class Cat<Mammal def speak puts "Meow" end end
tama = Cat.new tama.breathe tama.speak
PlayAround• writeaprogforreducedfarforthetrain(3ClassesTraveler,Student,
Honest,bothStudentandHonestinheritance
class Traveler def identify puts "I'm a Traveler." end def train_toll(age) if age < 12 puts "Reduced fare."; else puts "Normal fare."; end end end
PlayAround
class Student<Traveler def identify puts "I'm a student." end end
class Honest<Traveler def train_toll(age) super(age) # pass the argument we were given end
end Traveler.new.identify Student1.new.identify Honest.new.train_toll(25)
Assignment
WewillbecreaDnganAlumnidatabasesystem.1.createaclass'alumnus'tostoreasinglepersonor
alumnusin.Createamethodforseparatelyaddingfriends(byreferencetoanexisDngalumnusobject!)
2.testtheclassbycreaDngagroupofalumniwhoarefriends.
3.Notallalumnihavetobedirectfriends,youcanalsohaveacquaintances.Theyarefriendsofyourfriendsthatarenotyourdirectfriend.
So:adistanceof1isyourfriend,adistanceof2isanacquaintanceandmorethan2isunknown.
Assignment
4.createaclassthatprintsinformaDonaboutasinglealumnus4.1createamethodforprinDngallfriendsofthealumnusbyname4.2createamethodforprinDngallacquaintancesofthealumnusby
name4.3createamethodthatprintsALLconnectedalumniatanydistancefor
thegivenalumnus.ForeachconnecDonprintthedistancenumber,thetypeofrelaDonandthealumnithroughwhichtheyareconnected
so:2:acquaintance:eelco‐>jarno‐>karstimpliesthateelcoknowskarstthroughjarno,meaningjarnoisafriendandkarstisanacquaintance.
NotethattherecanbemulDplewaysthateelcoknowskarst,alwayschoosetheshortestroute,andnevershowaconnecDontwice