0% found this document useful (0 votes)
90 views29 pages

All Programming Is Metaprogramming: (Engineering Software As A Service 3.5)

Uploaded by

Harshul Soni
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
90 views29 pages

All Programming Is Metaprogramming: (Engineering Software As A Service 3.5)

Uploaded by

Harshul Soni
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 29

All Programming is

Metaprogramming

(Engineering Software as a
Service §3.5)

Based on materials from Armando Fox and David Patterson


© 2013 Armando Fox & David Patterson, all rights reserved
Metaprogramming &
Reflection
• Reflection lets us ask an object
questions about itself and have it
modify itself
• Metaprogramming lets us define
new code at runtime

• How can these make our code


DRYer, more concise, or easier to
read?
– (or are they just fancy words to make
An International Bank
Account
acct.deposit(100) # deposit $100
acct.deposit(euros_to_dollars(20))
acct.deposit(CurrencyConverter.new(
:euros, 20))
An International Bank
Account!
acct.deposit(100) # deposit $100
acct.deposit(20.euros) # about $25
•No problem with open classes....
class Numeric
def euros ; self * 1.292 ; end
end http://pastebin.com/f6WuV2rC

• But what about


acct.deposit(1.euro)
http://pastebin.com/WZGBhXci
The Power of method_missing
• But suppose we also want to
support
acct.deposit(1000.yen)
acct.deposit(3000.rupees)
• Surely there is a DRY wayhttp://pastebin.com/agjb5qBF
to do
this?

http://pastebin.com/HJTvUid5
Reflection &
Metaprogramming
• You can ask Ruby objects
questions about themselves at
runtime (introspection)
• You can use this information to
generate new code (methods,
objects, classes) at runtime
(reflection)
• …so can have code that writes
code (metaprogramming)
• You can “reopen” any class at any
END
7
Suppose we want to handle
5.euros.in(:rupees)
What change to Numeric would be most
appropriate?
☐ Change Numeric.method_missing to
detect calls to 'in' with appropriate
args
☐ Change Numeric#method_missing to
detect calls to 'in' with appropriate
args
☐ Define the method Numeric#in

☐ Define the method Numeric.in

8
END
9
Blocks, Iterators,
Functional Idioms

(Engineering Software as a
Service §3.6)

© 2013 Armando Fox & David Patterson, all rights reserved


Functionally Flavored
• How can techniques from
functional programming help us
rethink basic programming
concepts like iteration?

• And why is it worth doing that?


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, " }


If You Are Iterating with an
Index, You Are 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
“Expression Orientation”
x = ['apple','cherry','apple','banana']
x.sort # => ['apple','apple','banana','cherry']

x.uniq.reverse # => ['cherry','banana','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 }
http://pastebin.com/Aqgs4mhE
• A real life example....
END
15
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)

16
END
17
Mix-ins and Duck Typing

(Engineering Software as a
Service §3.7)

© 2013 Armando Fox & David Patterson, all rights reserved


So What If You’re Not My
Type

• Ruby emphasizes
“What methods do you respond
to?”
over
“What class do you belong to?”

• How does this encourage


productivity through reuse?
What is “Duck Typing”?
• If it responds to the
same methods as a
duck...it might as well
be a duck
• Similar to Java
Interfaces but easier to
use
[5, 4, 3].sort
• Example:
["dog", "cat", "rat"].sort
my_list.sort
[:a, :b, :c].sort
IO.readlines("my_file").sort
Modules
• Collection of methods that aren’t a
class
– you can’t instantiate it
– Some modules are namespaces, similar
to Python: Math::sin(Math::PI / 2.0)
• Important use of modules: mix its
methods into a class:
class A ; include MyModule ; end
– A.foo will search A, then MyModule, then
method_missing in A & MyModule, then A's
super
A Mix-in is a Contract
• Example: Enumerable assumes target
object responds to each
– ...provides all?, any?, collect, find, include?,
inject, map, partition, ....
• Enumerable also provides sort, which
requires elements of collection (things
returned by each) to respond to <=>
• Comparable assumes that target object
responds to <=>(other_thing)
– provides < <= >= > == between? for free
Class of objects doesn’t matter: only
methods to which they respond
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 }
END
24
a = SavingsAccount.new(100)
b = SavingsAccount.new(50)
c = SavingsAccount.new(75)
What is 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
Doesn’t
sort work, but would work if we
defined <=> on SavingsAccount
☐ Doesn’t work: SavingsAccount isn’t
a basic Ruby type so can’t compare
them
25
END
26
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
When Module? When Class?
• Modules reuse behaviors
– high-level behaviors that could
conceptually apply to many classes
– Example: Enumerable, Comparable
– Mechanism: mix-in (include Enumerable)
• Classes reuse implementation
– subclass reuses/overrides superclass
methods
– Mechanism: inheritance (class A < B)
• Remarkably often, we will prefer
composition over inheritance
END
29

You might also like