MTAT.03.295 Agile Software Development in the Cloud Lecture 4: More on Ruby Luciano García-Bañuelos University of Tartu
Regular Expressions Widely use tool for specifying (and implemen5ng) pa7ern matching processors and even lexical analyzers RegExp are first- class ci5zens in Ruby expr1 = Regexp.new('\(\d+\)') expr2 = /\(\d+\)/ Ruby s syntax is mostly borrowed from Perl s
A toy example =~ nil (cf. false) when no match index of the first occur. on the string, otherwise match nil when no match Instance of MatchData, otherwise def code_matcher(expr, str) if expr =~ str puts "Country code #{expr.match(str)} else puts 'No country code provided end end phone1 = '(372) 58 442-456' phone2 = '58 442-456' expr = /\(\d+\)/ code_matcher(expr, phone1) code_matcher(expr, phone2)
Character classes Example /[Rr]uby/ /Rub(y en)/ /[aeiou]/ /[0-9]/ /[a- za- Z]/ /[^aeiou]/ /[^0-9]/ Descrip2on Matches Ruby or ruby Matches Ruby or Ruben Matches a single lowercase vowel Matches a single digit Matches a single alphabe5c character Matches anything other than a lowercase vowel Matches anything other than a digit
Character classes (continuation) Abrevia2on Descrip2on \d A digit character, as [0-9] \D Any character except a digit, as [^0-9] \s Any whitespace, as [ \t\r\n\f] \S Any character except a whitespace \w Any word character, as [a- za- Z0-9_] \W Any character except a work character, as [^a- za- Z0-9_]. Any character except a whitespace POSIX character classes [:alpha:], [:alnum:], [:blank:], [:cntrl:], [:digit:], [:graph:], [:lower:], [:print:], [:punct:], [:space:], [:upper:], [:xdigit:]
Repetition and anchoring Example /ruby?/ /ruby*/ /ruby+/ /\d{3}/ /\d{3,}/ /\d{3,5}/ Descrip2on Matches rub or ruby Matches rub followed by 0 or more y s Matches rub followed by 1 or more y s Matches exactly three digits Matches 3 o more digits Matches 3, 4 or 5 digits Example /^Ruby/ /Ruby$/ /\ARuby/ /Ruby\Z/ /\bruby\b/ Descrip2on Matches rub or ruby Matches rub followed by 0 or more y s Matches rub followed by 1 or more y s Matches exactly three digits Matches Ruby if and only if found as single word
Matching groups exp1 = /(\d+)\d+(\d+)/ exp2 = /\d+/ m = exp1.match("_ 123 abc 345 x 67 end") puts "#{$1}, #{$2} m.captures exp2.match("_ 123 abc 345 x 67 end") puts "#{$1}, #{$2}" m = "_ 123 abc 345 x 67 end".scan(/(\d+)/) m.each { x puts x }
Matching and replacing str1 = "he said 'hello' to me" str2 = str1.dup puts str1.gsub(/he/,'he') puts str2.gsub(/\bhe\b/,'he')
Blocks class Array def iterate self.each_with_index do n, i self[i] = yield(n) end end end array = [1, 2, 3, 4] array.iterate do n n ** 2 end puts array.inspect
Blocks => Procs class Array def iterate(&code) self.each_with_index do n, i self[i] = code.call(n) end end end array = [1, 2, 3, 4] array.iterate do n n ** 2 end puts array.inspect
Procs can be reused class Array def iterate(code) self.each_with_index do n, i self[i] = code.call(n) end end end array_1 = [1, 2, 3, 4] array_2 = [2, 3, 4, 5] square = Proc.new { n n ** 2} array_1.iterate(square) array_2.iterate(square) puts array_1.inspect puts array_2.inspect
Lambdas class Array def iterate(code) self.each_with_index do n, i self[i] = code.call(n) end end end array = [1, 2, 3, 4] array.iterate( lambda { n n ** 2 }) puts array.inspect
Lambdas strictly check number of parameters def args(code) one, two = 1, 2 code.call(one, two) end args(proc.new{ a, b, c puts "Give me a #{a} and a #{b} and a #{c.class}"}) args(lambda{ a, b, c puts "Give me a #{a} and a #{b} and a #{c.class}"})
Lambdas perform diminutive returns def proc_return Proc.new { return "Proc.new"}.call return "proc_return method finished" end def lambda_return lambda { return "lambda" }.call return "lambda_return method finished" end puts proc_return puts lambda_return
Classes and Mixins module Persistence def load sfilename puts Reading #{sfilename} contents into 'my_data'" end def save sfilename puts "Persisting '#{@my_data}' into '#{sfilename}'" end end class MyClass include Persistence attr :my_data def data=(somedata) @my_data = somedata end end b = MyClass.new b.data = "This_15_my_pwd" b.save("passwords") b.load("passwords")
Finally metaprogramming class Polyglot @@greetings = {estonian: "Tere hommikust", english: "Good morning"} def Polyglot.add_language(language, greeting) @@greetings[language] = greeting if language.is_a? Symbol end def method_missing(name) unless @@greetings[name].nil? puts @@greetings[name] else super end end end a = Polyglot.new a.estonian a.english