Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
CSCE 740 Software Engineering Ruby and the tools 740Tools07RubyMetaprogramming Topics Spring 2014 Blocks Yield Iterators Mix-ins Tools Last Time Blocks Iterators Closures New Ruby Yield Iterators Duck-Typing Mix-ins Next Time: System Modelling –2– CSCE 740 Spring 2014 REMEMBER! a.b means: call method b on object a a is the receiver to which you send the method call, assuming a will respond to that method does not mean: b is an instance variable of a does not mean: a is some kind of data structure that has b as a member 5.class.superclass Understanding this distinction will save you from much grief and confusion –3– UCB CS169 Sp 2012 Slides Fox, Patterson and Sen CSCE 740 Spring 2014 3.2 Everything is an Object - revisited “Ruby’s object model descends from Smalltalk, whose design was inspired by ideas in Simula.” Ruby: is dynamically typed is lexically scoped does not support multiple inheritance supports reflection (asking about objects) “Even a class in Ruby is itself an object—it’s an instance of Class, which is a class whose instances are classes (a metaclass).” def class xxx … –4– SaaS book 2012 Fox Patterson CSCE 740 Spring 2014 Poetry Mode revisited To improve readability by removing clutter: omit parentheses, braces as long as parsing remains unambiguous spreading long lines over multiple lines using “ ; ” instead of newline as separator surround “;” with spaces – making meaner clearer attr_accessor :year –5– SaaS book 2012 Fox Patterson CSCE 740 Spring 2014 long lines multiple lines http://pastebin.com/dFJjugTf # downcase and split are defined in String class words = IO.read("file"). split(/\W+/). select { |s| s =~ /^[aeiou]/i }. map { |s| s.downcase }. uniq. sort –6– CSCE 740 Spring 2014 http://pastebin.com/K6ev3S7g Splat Args # using 'keyword style' arguments def mymethod(required_arg, args={}) do_fancy_stuff if args[:fancy] end mymethod "foo",:fancy => true # => args={:fancy => true} mymethod "foo" # => args={} # using * (splat) arguments def mymethod(required_arg, *args) # args is an array of extra args, maybe empty end mymethod "foo","bar",:fancy => true # => args=["bar",{:fancy=>true}] "foo" # => args=[] –mymethod 7– CSCE 740 Spring 2014 3.5 All Programming is Metaprogramming attr_accessor :year creating code at run-time –8– SaaS book 2012 Fox Patterson CSCE 740 Spring 2014 # Note: Time.now returns current time as seconds since epoch class Fixnum def seconds ; self ; end def minutes ; self * 60 ; end def hours ; self * 60 * 60 ; end def ago ; Time.now - self ; end def from_now ; Time.now + self ; end end Time.now # => Mon Nov 07 10:18:10 -0800 2011 5.minutes.ago # => Mon Nov 07 10:13:15 -0800 2011 5.minutes - 4.minutes # => 60 3.hours.from_now # => Mon Nov 07 13:18:15 -0800 2011 –9– CSCE 740 Spring 2014 method_missing http://pastebin.com/G0ztHTTP class Fixnum def method_missing(method_id, *args) name = method_id.to_s if name =~ /^(second|minute|hour)$/ self.send(name + 's') else super # pass the buck to superclass end end end – 10 – CSCE 740 Spring 2014 3.6 Blocks: Iterators, Functional Idioms, and Closures Fox, Armando; Patterson, David (2014-01-31). Engineering Software as a Service: An Agile Approach Using Cloud Computing (Kindle Location 2514). Strawberry Canyon LLC. Kindle Edition. – 11 – CSCE 740 Spring 2014 Loops—but don’t think of them that way ["apple", "banana", "cherry"].each do |string| puts string end for i in (1..10) do puts i end 1.upto 10 do |num| puts num end 3.times { – 12 – print "Rah, " } UCB CS169 Sp 2012 Slides Fox, Patterson and Sen CSCE 740 Spring 2014 If you’re iterating with an index, you’re probably doing it wrong Iterators let objects manage their own traversal (1..10).each do |x| ... end (1..10).each { |x| ... } 1.upto(10) do |x| ... end => range traversal my_array.each do |elt| ... end => array traversal hsh.each_key do |key| ... end hsh.each_pair do |key,val| ... end => hash traversal 10.times {...} # => iterator of arity zero 10.times do ... end – 13 – UCB CS169 Sp 2012 Slides Fox, Patterson and Sen CSCE 740 Spring 2014 “Expression orientation” x = ['apple','cherry','apple','banana'] x.sort # => ['apple','apple','banana','cherry'] x.uniq.reverse # => ['banana','cherry','apple'] x.reverse! # => modifies x x.map do |fruit| fruit.reverse end.sort # => ['ananab','elppa','elppa','yrrehc'] x.collect { |f| f.include?("e") } x.any? { |f| f.length > 5 } A real life example.... – 14 – http://pastebin.com/Aqgs4mhE UCB CS169 Sp 2012 Slides Fox, Patterson and Sen CSCE 740 Spring 2014 Which string will not appear in the result of: ['banana','anana','naan'].map do |food| food.reverse end.select { |f| f.match /^a/ } ☐ naan ☐ ananab ☐ anana ☐ The above code won’t run due to syntax error(s) UCB CS169 Sp 2012 Slides Fox, Patterson and Sen 15 Collection Operators Method - #Args - Returns a new collection containing. . . c.map 1 - elements obtained by applying block to each element of c c.select 1 Subset of c for which block evaluates to true c.reject 1 Subset of c obtained by removing elements for which block evaluates to true c.uniq all elements of c with duplicates removed c.reverse elements of c in reverse order c.compact all non-nil elements of c c.flatten elements of c and any of its sub-arrays, recursively flattened to contain only non-array elements – 16 – CSCE 740 Spring 2014 More Collection Operators c.sort -If sort is called without a block, the elements are sorted according to how they respond to <=>. c.partition c.sort_by c.max c.min Fox, Armando; Patterson, David (2014-01-31). Engineering Software as a Service: An Agile Approach Using Cloud Computing (Kindle Locations 2594-2595). Strawberry Canyon LLC. Kindle Edition. – 17 – CSCE 740 Spring 2014 What is “duck typing”? If it responds to the same methods as a duck...it might as well be a duck More than just overloading; similar to Java Interfaces Example: my_list.sort [5, 4, 3].sort ["dog", "cat", "rat"].sort [:a, :b, :c].sort IO.readlines("my_file") – 18 – UCB CS169 Sp 2012 Slides Fox, Patterson and Sen CSCE 740 Spring 2014 Modules A module is a collection of class & instance methods that are not actually a class you can’t instantiate it Some modules are namespaces, similar to Python: Math::sin(Math::PI / 2.0) The more interesting ones let you mix the methods into a class: class A < B ; include MyModule ; end A.foo will search A, then MyModule, then B sort is actually defined in module Enumerable, which is mixed into Array by default – 19 – UCB CS169 Sp 2012 Slides Fox, Patterson and Sen CSCE 740 Spring 2014 A Mix-in Is A Contract Example: Enumerable assumes objects of target class respond to each ...provides all?, any?, collect, find, include?, inject, map, partition, .... Example: Comparable assumes that objects of target class respond to <=> provides < <= => > == between? for free Enumerable also provides sort, which requires elements of target class (things returned by each) to respond to <=> Class of objects doesn’t matter: only methods to which they respond – 20 – UCB CS169 Sp 2012 Slides Fox, Patterson and Sen CSCE 740 Spring 2014 Example: sorting a file Sorting a file File.open returns an IO object IO objects respond to each by returning each line as a String So we can say File.open('filename.txt').sort relies on IO#each and String#<=> Which lines of file begin with vowel? File.open('file'). select { |s| s =~ /^[aeiou]/i } – 21 – UCB CS169 Sp 2012 Slides Fox, Patterson and Sen CSCE 740 Spring 2014 a = SavingsAccount.new(100) b = SavingsAccount.new(50) c = SavingsAccount.new(75) What’s result of [a,b,c].sort ☐ Works, because account balances (numbers) get compared ☐ Doesn’t work, but would work if we passed a comparison method to sort ☐ Doesn’t work, but would work if we defined <=> on SavingsAccount ☐ Doesn’t work: SavingsAccount isn’t a basic Ruby type so can’t compare them UCB CS169 Sp 2012 Slides Fox, Patterson and Sen 22 Making accounts comparable Just define <=> and then use the Comparable module to get the other methods Now, an Account quacks like a numeric http://pastebin.com/itkpaqMh – 23 – UCB CS169 Sp 2012 Slides Fox, Patterson and Sen CSCE 740 Spring 2014 When Module? When Class? Modules reuse behaviors high-level behaviors that could conceptually apply to many classes Example: Enumerable, Comparable Mechanism: mixin (include Enumerable) Classes reuse implementation subclass reuses/overrides superclass methods Mechanism: inheritance (class A < B) Remarkably often, we will prefer composition over inheritance – 24 – UCB CS169 Sp 2012 Slides Fox, Patterson and Sen CSCE 740 Spring 2014 Blocks (anonymous λ) (map '(lambda (x) (+ x 2)) mylist ) mylist.map { |x| x+2 } (filter '(lambda (x) (even? x)) mylist) mylist.select do |x| ; x.even? ; end (map '(lambda (x) (+ x 2)) (filter '(lambda (x) (even? x)) mylist)) mylist.select {|x| x.even?}.map {|x| x+2 } – 25 – UCB CS169 Sp 2012 Slides Fox, Patterson and Sen CSCE 740 Spring 2014 Turning iterators inside-out Java: You hand me each element of that collection in turn. I’ll do some stuff. Then I’ll ask you if there’s any more left. Ruby: Here is some code to apply to every element of the collection. You manage the iteration or data structure traversal. Let’s do an example... http://pastebin.com/T3JhV7Bk – 26 – UCB CS169 Sp 2012 Slides Fox, Patterson and Sen CSCE 740 Spring 2014 http://pastebin.com/0sTEMcdN <!DOCTYPE html> <html> <head> <title>Report</title> </head> <body> <div id="main"> ...user-generated content here... </div> </body> </html> – 27 – SaaS book 2012 Fox Patterson CSCE 740 Spring 2014 1 def one_page 2 page = ’’ 3 page << make_header() 4 page << "Hello" 5 page << make_footer() 6 end 7 def another_page 8 page = ’’ 9 page << make_header() 10 page << "World" 11 page << make_footer() 12 end – 28 – SaaS book 2012 Fox Patterson CSCE 740 Spring 2014 http://pastebin.com/TsvTN5ZT def make_page(contents) page = '' page << make_header() page << contents page << make_footer() end # def one_page make_page("Hello") end def another_page make_page("World") – end 29 – CSCE 740 Spring 2014 http://pastebin.com/zQPh70NJ def make_page page = '' page << make_header() page << yield page << make_footer() end def one_page make_page do "Hello" end end def another_page – 30 – … SaaS book 2012 Fox Patterson CSCE 740 Spring 2014 We can exploit Ruby’s idiom for single-line blocks to boil this down to: http://pastebin.com/Nqe8MwA5 def make_page make_header << yield << make_footer end def one_page make_page { "Hello" } end def another_page make_page { "World" } end – 31 – SaaSbook http://pastebin.com/Nqe8MwA5 CSCE 740 Spring 2014 http://pastebin.com/T3JhV7Bk class RandomSequence def initialize(limit,num) @limit,@num = limit,num end def each @num.times { yield (rand * @limit).floor } end end – 32 – UCB CS169 Sp 2012 Slides Fox, Patterson and Sen CSCE 740 Spring 2014 Iterators are just one nifty use of yield # in some other library def before_stuff ...before code... end def after_stuff ...after code... end # in your code def do_everything before_stuff() my_custom_stuff() after_stuff() end Without yield(): expose 2 calls in other library – 33 – # in some other library def around_stuff ...before code... yield ...after code... end # in your code def do_everything around_stuff do my_custom_stuff() end end With yield(): expose 1 call otherCSCE library UCB CS169 Sp 2012 Slides Fox, Patterson and in Sen 740 Spring 2014 Blocks are Closures A closure is the set of all variable bindings you can “see” at a given point in time In Scheme, it’s called an environment Blocks are closures: they carry their environment around with them Result: blocks can help reuse by separating what to do from where & when to do it We’ll see various examples in Rails http://pastebin.com/zQPh70NJ – 34 – UCB CS169 Sp 2012 Slides Fox, Patterson and Sen CSCE 740 Spring 2014 Summary of Yield In the body of a method that takes a block as a parameter, yield transfers control to the block and optionally passes it an argument. A block is a closure, its scope is the one that was in effect when the block was defined, Yielding is the general mechanism behind iterators: – 35 – an iterator is simply a method that traverses some data structure and uses yield to pass one element at a time to the iterator’s receiver. SaaS book 2012 Fox Patterson CSCE 740 Spring 2014 3.9 Fallacies and Pitfalls Pitfall: Writing Java in Ruby Pitfall: Thinking of symbols and strings as interchangeable. Pitfall: Naming a local variable when you meant a local method. Pitfall: Confusing require with include. Fox, Armando; Patterson, David (2014-01-31). Engineering Software as a Service: An Agile Approach Using Cloud Computing (Kindle Locations 2811-2812). Strawberry Canyon LLC. Kindle Edition. – 36 – SaaS book 2012 Fox Patterson CSCE 740 Spring 2014