Ruby and the tools 740tools07rubymetaprogramming
Sponsored Links
This presentation is the property of its rightful owner.
1 / 36

Ruby and the tools 740Tools07RubyMetaprogramming PowerPoint PPT Presentation


  • 82 Views
  • Uploaded on
  • Presentation posted in: General

Ruby and the tools 740Tools07RubyMetaprogramming. CSCE 740 Software Engineering. Topics Blocks Yield Iterators Mix-ins. Spring 2014. Tools -. Last Time Blocks Iterators Closures. New Ruby Yield Iterators Duck-Typing Mix-ins Next Time: System Modelling. REMEMBER!.

Download Presentation

Ruby and the tools 740Tools07RubyMetaprogramming

An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Presentation Transcript


Ruby and the tools740Tools07RubyMetaprogramming

CSCE 740 Software Engineering

  • Topics

    • Blocks

    • Yield

    • Iterators

    • Mix-ins

Spring 2014


Tools -

  • Last Time

    • Blocks

    • Iterators

    • Closures

  • New Ruby

    • Yield

    • Iterators

    • Duck-Typing

    • Mix-ins

  • Next Time: System Modelling


REMEMBER!

  • a.bmeans: call method b on object a

    • a is the receiver to which you sendthe method call, assuming a will respond tothat 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

UCB CS169 Sp 2012 Slides Fox, Patterson and Sen


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 …

SaaS book 2012 Fox Patterson


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

SaaS book 2012 Fox Patterson


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


http://pastebin.com/K6ev3S7g Splat Args

  • # using 'keyword style' arguments

  • defmymethod(required_arg, args={})

  • do_fancy_stuff if args[:fancy]

  • end

  • mymethod "foo",:fancy => true # => args={:fancy => true}

  • mymethod "foo"                # => args={}

  • # using * (splat) arguments

  • defmymethod(required_arg, *args)

  •   # args is an array of extra args, maybe empty

  • end 

  • mymethod "foo","bar",:fancy => true # => args=["bar",{:fancy=>true}]

  • mymethod "foo"                      # => args=[]


3.5 All Programming is Metaprogramming

  • attr_accessor :year

  • creating code at run-time

SaaS book 2012 Fox Patterson


  • #  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

  • deffrom_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


method_missinghttp://pastebin.com/G0ztHTTP

  • class Fixnum

  • defmethod_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


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.


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 { print "Rah, " }

UCB CS169 Sp 2012 Slides Fox, Patterson and Sen


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| ... endhsh.each_pair do |key,val| ... end=> hash traversal

  • 10.times {...} # => iterator of arity zero

  • 10.times do ... end

UCB CS169 Sp 2012 Slides Fox, Patterson and Sen


“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....

http://pastebin.com/Aqgs4mhE

UCB CS169 Sp 2012 Slides Fox, Patterson and Sen


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


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


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.


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")

UCB CS169 Sp 2012 Slides Fox, Patterson and Sen


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

UCB CS169 Sp 2012 Slides Fox, Patterson and Sen


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

UCB CS169 Sp 2012 Slides Fox, Patterson and Sen


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 }

UCB CS169 Sp 2012 Slides Fox, Patterson and Sen


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


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

UCB CS169 Sp 2012 Slides Fox, Patterson and Sen


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

UCB CS169 Sp 2012 Slides Fox, Patterson and Sen


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 }

UCB CS169 Sp 2012 Slides Fox, Patterson and Sen


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

UCB CS169 Sp 2012 Slides Fox, Patterson and Sen


http://pastebin.com/0sTEMcdN

  • <!DOCTYPE html>

  • <html>

  • <head>

  • <title>Report</title>

  • </head>

  • <body>

  • <div id="main">

  • ...user-generated content here...

  • </div>

  • </body>

  • </html>

SaaS book 2012 Fox Patterson


  •  1    defone_page

  • 2      page = ’’  

  • 3      page << make_header()  

  • 4      page << "Hello"  

  • 5      page << make_footer()  

  • 6    end  7    defanother_page

  • 8      page = ’’  

  • 9      page << make_header()

  • 10      page << "World"

  • 11      page << make_footer()

  • 12    end

SaaS book 2012 Fox Patterson


http://pastebin.com/TsvTN5ZT

  • defmake_page(contents)

  •   page = ''

  •   page << make_header()

  •   page << contents

  •   page << make_footer()

  • end

  • #

  • defone_page

  • make_page("Hello")

  • end

  • defanother_page

  • make_page("World")

  • end


http://pastebin.com/zQPh70NJ

  • defmake_page

  •   page = ''

  •   page << make_header()

  •   page << yield

  •   page << make_footer()

  • end

  • defone_page

  • make_page do

  •     "Hello"

  •   end

  • end

  • defanother_page

SaaS book 2012 Fox Patterson


  • We can exploit Ruby’s idiom for single-line blocks to boil this down to: http://pastebin.com/Nqe8MwA5

  • defmake_page

  • make_header << yield << make_footer

  • end

  • defone_page

  • make_page { "Hello" }

  • end

  • defanother_page

  • make_page { "World" }

  • end

SaaSbook http://pastebin.com/Nqe8MwA5


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

UCB CS169 Sp 2012 Slides Fox, Patterson and Sen


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

# 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 in other library

UCB CS169 Sp 2012 Slides Fox, Patterson and Sen


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

UCB CS169 Sp 2012 Slides Fox, Patterson and Sen


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:

    • 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


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.

SaaS book 2012 Fox Patterson


  • Login