Ruby for Java
Programmers
Mike Bowler
President, Gargoyle Software Inc.
Why learn another
language?
Why Ruby?
Timeline: 1993 to
2000
Created in 1993 by
Yukihiro "Matz"
Matsumoto
Ruby was popular in
Japan but unknown
everywhere else
...
Timeline: 2000-
2004
First English language
book published in 2000
A lot of interest in the
Agile development
community bu...
Timeline: 2004-
today
The Ruby on Rails
framework has pushed
ruby into the spotlight
This is the “killer app”
What influenced it?
Terminology
Early
Late
Static
Dynamic
Strong
Weak
Defining strong/weak
typing
Strong typing
Objects are of a specific type and will not be
converted automatically
Java: “4”...
Early/late
bindingEarly binding (aka static binding)
All method invocations must be defined at compile
time
Java: foo.getU...
Similarities
Like Java, Ruby...
runs on a virtual machine
is garbage collected
is object oriented (although to different
d...
Differences
Everything is an object
Java
string = String.valueOf(1);
Ruby
string = 1.to_s()
Primitive
Object
Differences
Many things that you would expect to be
keywords are actually methods
throw new IllegalArgumentException("oops...
Differences
Some syntax optional unless the result is
ambiguous
These statements are equivalent
puts("foo");
puts "foo"
Id...
Differences
Classes are real
objects
They’re instances of
Class
Class methods can
be overridden
class ZebraCage < Cage
attr_accessor :capacity
@@allCages = Array.new
def initialize maximumZebraCount
@capacity = maximum...
Multiline if
if name.nil?
do_something
end
Multiline if
if name.nil?
do_something
end
Notice the
question mark
With an else
if name.nil?
do_something
else
something_else
end
Single line if
if name.nil?
do_something
end
do_something if name.nil?
Both kinds of
unlessif name.nil?
do_something
end
do_something if name.nil?
unless name.nil?
do_something
end
do_something...
Dangerous methods
name = " foo "
name.strip
name.strip!
Returns a new string.
Doesn’t modify name.
Modifies name
and retur...
Philosophy
Java focuses on building blocks
You can build whatever you want with the
pieces
Ruby focuses on solving problem...
Initializing
arraysList<String> list = new ArrayList<String>();
list.add("foo");
list.add("bar");
Same only ruby
List<String> list = new ArrayList<String>();
list.add("foo");
list.add("bar");
list = Array.new
list << 'fo...
[]
List<String> list = new ArrayList<String>();
list.add("foo");
list.add("bar");
list = Array.new
list << 'foo'
list << '...
%w()
List<String> list = new ArrayList<String>();
list.add("foo");
list.add("bar");
list = Array.new
list << 'foo'
list <<...
In fairness to
java...List<String> list = new ArrayList<String>();
list.add("foo");
list.add("bar");
List<String> list = A...
Same idea with
hashes
Map<String,String> map
= new HashMap<String,String>();
map.put("foo", "one");
map.put("bar", "two");...
Special case for
Hash
hash = {:a => 5, :b => 3}
do_stuff 30, hash
do_stuff 100, :a => 5, :b => 3
Regular
Expressions
Pattern pattern = Pattern.compile("^s*(.+)s*$");
Matcher matcher = pattern.matcher(line);
if( matcher....
Regular
Expressions
Pattern pattern = Pattern.compile("^s*(.+)s*$");
Matcher matcher = pattern.matcher(line);
if( matcher....
Nil and Null
Java’s nullJava’s null Ruby’s nilRuby’s nil
Absence of an object An instance of NilClass
if( a != null ) {......
Implications of
late binding
Method dispatch is quite different
Ruby makes a distinction between “messages”
that are sent ...
Message != Method
What if there isn’t a
method for the
specified message?
method_missing
example from
ActiveRecord
user = Users.find_by_name(name)
user = Users.find(:first,
:conditions => [ "name ...
Creating proxy
objects
Mock object for testing
Proxy object to allow distributed objects across
machines
Wrapper to record...
Implementing a
proxyclass Proxy
def method_missing name, *args, &proc
puts name,args
end
end
Implementing a
proxyclass Proxy
def method_missing name, *args, &proc
puts name,args
end
end
Proxy.new.foo_bar ‘a’
Proxy.n...
Overriding to_s
class Proxy
def method_missing name, *args, &proc
puts name,args
end
def to_s
method_missing :to_s, []
end...
=•===•=~•__id__•_send__•class•clone•dclone
display•dup•enum_for•eql?•equal?•extend freeze
frozen?•hash•id•inspect•instance...
Implementing a proxy
class Proxy
instance_methods.each do |method|
undef_method method unless method =~ /^__/
end
def meth...
Unix was not designed to stop people
from doing stupid things, because that
would also stop them from doing
clever things....
Cultural
differences about
type
Java is very focused on the types of objects
Is the object an instance of a specific class...
Types
public void foo( ArrayList list ) {
list.add("foo");
}
def foo list
list << 'foo'
end
What’s the type?
What’s the ty...
Duck typing
def foo list
list << 'foo'
end
If list is a String
=> ‘foo’
If list is an Array
=> [‘foo’]
If list is an IO
=>...
Duck typing
Duck typing implies that an object is
interchangeable with any other object that
implements the same interface...
How does this
change how we
think of types?
think of types?
think of types?
Overflow conditions
int a = Integer.MAX_VALUE;
System.out.println(" a="+a);
System.out.println("a+1="+(a+1));
a=2147483647...
Overflow conditions
int a = Integer.MAX_VALUE;
System.out.println(" a="+a);
System.out.println("a+1="+(a+1));
a=2147483647...
Overflow in ruby?
number = 1000
1.upto(4) do
puts "#{number.class} #{number}"
number = number * number
end
Fixnum 1000
Fix...
Closures
A closure is a function that is evaluated in an
environment containing one or more bound variables.
When called, ...
Closures
A closure is a block of code that you can
manipulate and query
In Ruby we call them blocks or Procs
A block is a ...
Closures
multiplier = 5
block = lambda {|number| puts number * multiplier }
A block
An instance
of Proc
lambda() is a
meth...
Closures
multiplier = 5
block = lambda {|number| puts number * multiplier }
Parameter
to the block
Closures
multiplier = 5
block = lambda {|number| puts number * multiplier }
Able to access variables
from outside the block
Proc’s
multiplier = 5
block = lambda {|number| puts number * multiplier }
block.call 2
block.arity
prints 10
returns numbe...
Blocks as
parameters
multiplier = 5
1.upto(3) {|number| puts number * multiplier }
=> 5
=> 10
=> 15
Same block
as before
C...
Alternate syntax
multiplier = 5
1.upto(3) {|number| puts number * multiplier }
1.upto(3) do |number|
puts number * multipl...
Why are closures
significant?
Presence of closures in a language completely
changes the design of the libraries
Closure ba...
// Read the lines and split them into columns
List<String[]> lines= new ArrayList<String[]>();
BufferedReader reader = nul...
Closure File
Example
file = File.new(fileName,'w')
begin
file.puts ‘some content’
rescue
file.close
end
Closure File
Example
file = File.new(fileName,'w')
begin
file.puts ‘some content’
rescue
file.close
end Only one line of
b...
Closure File
Example
file = File.new(fileName,'w')
begin
file.puts ‘some content’
rescue
file.close
end
File.open(fileName...
Ruby file IO
sample
# Load the data
lines = Array.new
IO.foreach('people.txt') do |line|
lines << line.split
end
# Sort an...
Closure-like things
in Java
final String name = getName();
new Thread( new Runnable() {
public void run() {
doSomething(na...
Closures for
Java?
There are a couple of proposals being debated for
Java7
Unclear whether any of them will be accepted
In...
Inheriting
behaviour from
multiple places
C++ has multiple inheritance
Java has interfaces
Ruby has mixins
C++ : multiple
inheritance
Java :
inheritance
Ruby : mixins
Mixins
Cannot be instantiated
Can be mixed in
Enumerable
class Foo
include Enumerable
def each &block
block.call 1
block.call 2
block.call 3
end
end
module Enumerable
d...
Enumerable
class Foo
include Enumerable
def each &block
block.call 1
block.call 2
block.call 3
end
end
module Enumerable
d...
Enumerable
Requires that the class implement each()
For max, min and sort the <=> operator is also
needed
Adds many method...
Reopening classes
class Foo
def one
puts 'one'
end
end
Reopening classes
class Foo
def one
puts 'one'
end
end
class Foo
def two
puts 'two'
end
end
Reopening
the same class
Reopening classes
class Foo
def one
puts 'one'
end
end
class Foo
def one
puts '1'
end
end
Replacing, not
adding a method
Reopening core
classesclass String
def one
puts 'one'
end
end
We reopened
a CORE class
and modified it
Metaprogramming
Metaprogramming is the writing of computer
programs that write or manipulate other
programs (or themselves...
What changes can
we make at
runtime?
Anything we can hand code, we can
programmatically do
Because of late binding, EVERYT...
attr_accessor
class Foo
attr_accessor :bar
end
class Foo
def bar
@bar
end
def bar=(newBar)
@bar = newBar
end
end
Getter
Se...
class Foo
def self.attr_accessor name
module_eval <<-DONE
def #{name}()
@#{name}
end
def #{name}=(newValue)
@#{name} = new...
class Foo
def self.attr_accessor name
module_eval <<-DONE
def #{name}()
@#{name}
end
def #{name}=(newValue)
@#{name} = new...
class Foo
def self.attr_accessor name
module_eval <<-DONE
def #{name}()
@#{name}
end
def #{name}=(newValue)
@#{name} = new...
class Foo
def self.attr_accessor name
module_eval <<-DONE
def #{name}()
@#{name}
end
def #{name}=(newValue)
@#{name} = new...
Result
class Foo
def bar
@bar
end
def bar=(newBar)
@bar = newBar
end
end
ActiveRecord
class ListItem < ActiveRecord::Base
belongs_to :amazon_item
acts_as_taggable
acts_as_list :scope => :user
end
Date :: once
def once(*ids) # :nodoc:
for id in ids
module_eval <<-"end;", __FILE__, __LINE__
alias_method :__#{id.to_i}__...
ObjectSpace
ObjectSpace.each_object do |o|
puts o
end
ObjectSpace.each_object(String) do |o|
puts o
end
ObjectSpace
ObjectSpace.each_object do |o|
puts o
end
ObjectSpace.each_object(String) do |o|
puts o
end
All objects
Only S...
Continuations
A snapshot of the call stack that
the application can revert to at
some point in the future
Why
continuations?
To save the state of the application across
reboots of the VM
To save the state of the application acro...
Downsides
Only supported in one implementation of
Ruby
Will be removed from the language in Ruby
2.0
Implementations
Ruby 1.8.x - “reference implementation” in C
Ruby 1.9 - Next version of C interpreter
Rubinius - Ruby in R...
Implementations
Ruby 1.8.x - “reference implementation” in C
Ruby 1.9 - Next version of C interpreter
Rubinius - Ruby in R...
JRuby
Runs on the Java Virtual Machine (JVM)
Full implementation of the Ruby language
Supported by Sun
Runs many benchmark...
Ruby on Rails
Web application framework
Sweet spot - web application talking to a single
relational database
Allows very r...
Who’s using
rails?
Amazon • BBC • Cap Gemini
Chicago Tribune • Barclays • BPN • Cisco
CNET Electronic Arts • IBM • John De...
JRuby on Rails?
Yes! You can run a rails application on JRuby
in a servlet container
Goldspike is the servlet that dispatc...
Recap
Learning a new language will make you better
with all the languages you know
Ruby has a much more concise syntax whi...
Recap
Everything is an object
The language is extremely malleable
New classes/methods can be created on the
fly
Existing c...
Contacting me
Mike Bowler
mbowler@GargoyleSoftware.com
www.GargoyleSoftware.com (company)
www.SphericalImprovement.com (bl...
Upcoming SlideShare
Loading in …5
×

Rubyforjavaprogrammers 1210167973516759-9

243 views

Published on

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
243
On SlideShare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
2
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide
  • Sign language analogy New concepts new culture/idioms Become a better programmer in all languages
  • Coming from a Java background, Ruby offers many new concepts Ruby has become very popular with Java people so there are lots of people to help you get through the initial learning curve It’s a “hot” technology It can be run on existing J2EE infrastructure
  • Influenced by many other languages
  • A lot of confusion around terminology Let’s start with definitions
  • the java example will result in a compile error The perl example will automagically convert the string to an int
  • The java sample will fail at compile time if the Foo class does not contain a getUser() method The smalltalk sample will wait until the getuser message is sent to the object before seeing if there is a method
  • Ruby classes are first class objects, java classes are not Ruby class methods are methods on a real object (can be overridden etc) Java static methods are functions scoped to a Class name Ruby this will be null when executing a static method Everything in Ruby is an object
  • Inheritance is &lt; Enforced naming - Constants start with capital, variable with lower - @ for instance, @@ for class Naming by convention - Methods: all lowercase with underscores - Variables: camel case Others - Scope is private, protected, public. Default scope is public - attr_accessor generates zebras() and zebras=() - default values Object construction - new is a method on the class - is not required to return an instance of this class - initialize is the second stage of object creation Self is the equivalent of this except that it always has a value
  • Methods that return a boolean will end in “?”
  • Methods that return a boolean will end in “?”
  • Methods that return a boolean will end in “?”
  • Methods that return a boolean will end in “?”
  • Methods that return a boolean will end in “?”
  • Bang means the method is dangerous in some way Often this means that it modifies the receiver but not always This is convention only - not mandated by the compiler
  • To create a new list with two strings we do it in three separate steps
  • Special case where the hash is the last parameter to a method :symbol notation
  • Java requires double escaping because it’s a string Requires two explicit temporary objects
  • ActiveRecord::Base uses method_missing to convert the first method into the second
  • method_missing can be used to create a proxy object Problem: Object has quite a few methods already so you can’t proxy those
  • Works really well for new methods Methods already defined in Object don’t get passed to method_missing
  • Works really well for new methods Methods already defined in Object don’t get passed to method_missing
  • We can override the methods in Object and have them call method_missing
  • Problem: Object implements a lot of methods method_missing only gets called when there isn’t a method by that name
  • doesn’t work for to_s as that method was inherited from Kernel This removes all methods (except __send__ and __id__) from the instance
  • In java, we care what the type is In Ruby, we don’t All we care about is the fact that it responds to &lt;&lt;
  • Since objects are so malleable in ruby, it makes less sense to care about the exact class of an object We care about the behaviour (or interface) This allows us to do interesting things like quietly changing the return type of an object
  • Let’s look at an example
  • In Java, integers will quietly overflow and wrap around to negative numbers Problem: Java does not throw an exception during overflow conditions Problem: Overflow is possible at all
  • In Java, integers will quietly overflow and wrap around to negative numbers Problem: Java does not throw an exception during overflow conditions Problem: Overflow is possible at all
  • The * method will return Fixnum’s until the number is too big to fit inside a Fixnum It will then return Bignum Bignums are slower but are able to handle much larger values Wouldn’t be possible without duck typing
  • The method ‘lambda’ returns a Proc instance
  • The method ‘lambda’ returns a Proc instance
  • The method ‘lambda’ returns a Proc instance
  • The method ‘lambda’ returns a Proc instance
  • The block will get passed into the method
  • Idiom: Use curlies for single line blocks and do/end for multiple line blocks Difference in precedance
  • Some size difference due to optional syntax Most due to use of closures
  • Open file for writing begin/rescue == try/finally
  • All the business logic is inside the closure
  • Sort takes a closure foreach takes one File.open takes one
  • The closest thing Java has to closures are anonymous inner classes. The inner class has access to final local variables as well as instance and static variables (final or not) from the enclosing class One of the characteristics of proper closures is that they are syntactically clean. These are not.
  • There have been several rounds of proposals for this It’s not clear if they’ll ever be added to Java
  • C++ allows multiple inheritance Issues when the same method is declared in multiple branches
  • No issues with inheriting an interface twice as no methods are implemented in the interface
  • Mixin is a collection of methods that are grouped together A class can include as many mixins as it wants Mixins can work together with existing methods - ie Enumerable
  • Create class Define method
  • Reopen class Add second method Now Foo has two methods
  • This time we’re replacing a method
  • This is something that Java would never allow
  • Since we use late binding, we can manipulate
  • Create classes Add/modify/remove methods Rename methods
  • C++ would expand this using a pre-processor Ruby adds new methods at run time
  • ActiveRecord uses meta programming to establish relationships between model objects acts_as_* methods modify multiple classes and can make significant change to the behaviour
  • Much more complicated example One of the more interesting methods in the Ruby source Takes a method and ensures that after it’s been called once, the result is cached See my slides from the TSOT talk
  • Allows you to walk through all “live” objects in the heap
  • Allows you to walk through all “live” objects in the heap
  • You may never use these directly but the fact that the language supports them means that frameworks can be built that you can use
  • 1.9 - Faster - Somewhat incompatible Parrot - Common runtime for perl and python and other dynamic languages - Name came from a 2001 april fools joke Definitions DLR = Dynamic Language Runtime (sits on top of CLR) CLR = Common Language Runtime (runtime for .NET)
  • 1.9 - Faster - Somewhat incompatible Parrot - Common runtime for perl and python and other dynamic languages - Name came from a 2001 april fools joke Definitions DLR = Dynamic Language Runtime (sits on top of CLR) CLR = Common Language Runtime (runtime for .NET)
  • Lots of startups and ...
  • Rubyforjavaprogrammers 1210167973516759-9

    1. 1. Ruby for Java Programmers Mike Bowler President, Gargoyle Software Inc.
    2. 2. Why learn another language?
    3. 3. Why Ruby?
    4. 4. Timeline: 1993 to 2000 Created in 1993 by Yukihiro "Matz" Matsumoto Ruby was popular in Japan but unknown everywhere else All documentation was written in Japanese
    5. 5. Timeline: 2000- 2004 First English language book published in 2000 A lot of interest in the Agile development community but mostly unknown elsewhere
    6. 6. Timeline: 2004- today The Ruby on Rails framework has pushed ruby into the spotlight This is the “killer app”
    7. 7. What influenced it?
    8. 8. Terminology Early Late Static Dynamic Strong Weak
    9. 9. Defining strong/weak typing Strong typing Objects are of a specific type and will not be converted automatically Java: “4”/2 results in a compile error Weak typing Objects can be converted under the covers at any time Perl: ‘4’/2 => 2 Ruby is strongly typed
    10. 10. Early/late bindingEarly binding (aka static binding) All method invocations must be defined at compile time Java: foo.getUser() Late binding (aka dynamic binding) The runtime does not check that a given method exists until an attempt to invoke it Smalltalk: foo user. Ruby uses late binding
    11. 11. Similarities Like Java, Ruby... runs on a virtual machine is garbage collected is object oriented (although to different degrees)
    12. 12. Differences Everything is an object Java string = String.valueOf(1); Ruby string = 1.to_s() Primitive Object
    13. 13. Differences Many things that you would expect to be keywords are actually methods throw new IllegalArgumentException("oops"); raise TypeError.new("oops") Keywords Methods
    14. 14. Differences Some syntax optional unless the result is ambiguous These statements are equivalent puts("foo"); puts "foo" Idiomatic (better) style
    15. 15. Differences Classes are real objects They’re instances of Class Class methods can be overridden
    16. 16. class ZebraCage < Cage attr_accessor :capacity @@allCages = Array.new def initialize maximumZebraCount @capacity = maximumZebraCount @@allCages << self end private def clean_cage # do some stuff here end end cage = ZebraCage.new 10 puts cage.capacity
    17. 17. Multiline if if name.nil? do_something end
    18. 18. Multiline if if name.nil? do_something end Notice the question mark
    19. 19. With an else if name.nil? do_something else something_else end
    20. 20. Single line if if name.nil? do_something end do_something if name.nil?
    21. 21. Both kinds of unlessif name.nil? do_something end do_something if name.nil? unless name.nil? do_something end do_something unless name.nil?
    22. 22. Dangerous methods name = " foo " name.strip name.strip! Returns a new string. Doesn’t modify name. Modifies name and returns that. Dangerous!
    23. 23. Philosophy Java focuses on building blocks You can build whatever you want with the pieces Ruby focuses on solving problems Things you do frequently should be concise
    24. 24. Initializing arraysList<String> list = new ArrayList<String>(); list.add("foo"); list.add("bar");
    25. 25. Same only ruby List<String> list = new ArrayList<String>(); list.add("foo"); list.add("bar"); list = Array.new list << 'foo' list << 'bar'
    26. 26. [] List<String> list = new ArrayList<String>(); list.add("foo"); list.add("bar"); list = Array.new list << 'foo' list << 'bar' list = ['foo', 'bar']
    27. 27. %w() List<String> list = new ArrayList<String>(); list.add("foo"); list.add("bar"); list = Array.new list << 'foo' list << 'bar' list = ['foo', 'bar'] list = %w(foo bar)
    28. 28. In fairness to java...List<String> list = new ArrayList<String>(); list.add("foo"); list.add("bar"); List<String> list = Arrays.asList("foo", "bar"); list = Array.new list << 'foo' list << 'bar' list = ['foo', 'bar'] list = %w(foo bar)
    29. 29. Same idea with hashes Map<String,String> map = new HashMap<String,String>(); map.put("foo", "one"); map.put("bar", "two"); map = {'foo' => 'one', 'bar' => 'two'}
    30. 30. Special case for Hash hash = {:a => 5, :b => 3} do_stuff 30, hash do_stuff 100, :a => 5, :b => 3
    31. 31. Regular Expressions Pattern pattern = Pattern.compile("^s*(.+)s*$"); Matcher matcher = pattern.matcher(line); if( matcher.matches() ) { doSomething(); }
    32. 32. Regular Expressions Pattern pattern = Pattern.compile("^s*(.+)s*$"); Matcher matcher = pattern.matcher(line); if( matcher.matches() ) { doSomething(); } do_something if line =~ /^s*(.+)s*$/
    33. 33. Nil and Null Java’s nullJava’s null Ruby’s nilRuby’s nil Absence of an object An instance of NilClass if( a != null ) {...} unless a.nil? {...} null.toString() -> NPE nil.to_s -> “” null.getUser() -> Exception in thread "main" java.lang.NullPointerException nil.get_user -> NoMethodError: undefined method ‘get_user’ for nil:NilClass
    34. 34. Implications of late binding Method dispatch is quite different Ruby makes a distinction between “messages” that are sent to an object and the “methods” that get dispatched
    35. 35. Message != Method
    36. 36. What if there isn’t a method for the specified message?
    37. 37. method_missing example from ActiveRecord user = Users.find_by_name(name) user = Users.find(:first, :conditions => [ "name = ?", name])
    38. 38. Creating proxy objects Mock object for testing Proxy object to allow distributed objects across machines Wrapper to record usage of a given object
    39. 39. Implementing a proxyclass Proxy def method_missing name, *args, &proc puts name,args end end
    40. 40. Implementing a proxyclass Proxy def method_missing name, *args, &proc puts name,args end end Proxy.new.foo_bar ‘a’ Proxy.new.to_s Dispatches to method_missing Doesn’t go to method_missing
    41. 41. Overriding to_s class Proxy def method_missing name, *args, &proc puts name,args end def to_s method_missing :to_s, [] end end
    42. 42. =•===•=~•__id__•_send__•class•clone•dclone display•dup•enum_for•eql?•equal?•extend freeze frozen?•hash•id•inspect•instance_eval instance_of? instance_variable_defined•instance_variable_get instance_variable_get•instance_variable_set instance_variable_set•instance_variables•is_a? kind_of?•method•methods•new•nil?•object_id private_methods•protected_methods•public_methods remove_instance_variable•respond_to?•send singleton_method_added•singleton_method_removed singleton_method_undefined•singleton_methods•taint tainted?•to_a•to_enum•to_s•to_yaml to_yaml_properties•to_yaml_style•type•untaint
    43. 43. Implementing a proxy class Proxy instance_methods.each do |method| undef_method method unless method =~ /^__/ end def method_missing name, *args, &proc puts name,args end end Proxy.new.to_s
    44. 44. Unix was not designed to stop people from doing stupid things, because that would also stop them from doing clever things. —Doug Gwyn
    45. 45. Cultural differences about type Java is very focused on the types of objects Is the object an instance of a specific class? Or does it implement a specific interface? Ruby is focused on the behaviour Does the object respond to a given message?
    46. 46. Types public void foo( ArrayList list ) { list.add("foo"); } def foo list list << 'foo' end What’s the type? What’s the type?
    47. 47. Duck typing def foo list list << 'foo' end If list is a String => ‘foo’ If list is an Array => [‘foo’] If list is an IO => string will be written to stream
    48. 48. Duck typing Duck typing implies that an object is interchangeable with any other object that implements the same interface, regardless of whether the objects have a related inheritance hierarchy. -- Wikipedia "If it walks like a duck and quacks like a duck, it must be a duck." -- Pragmatic Dave Thomas
    49. 49. How does this change how we think of types? think of types? think of types?
    50. 50. Overflow conditions int a = Integer.MAX_VALUE; System.out.println(" a="+a); System.out.println("a+1="+(a+1)); a=2147483647 a+1= ??
    51. 51. Overflow conditions int a = Integer.MAX_VALUE; System.out.println(" a="+a); System.out.println("a+1="+(a+1)); a=2147483647 a+1=-2147483648 oops
    52. 52. Overflow in ruby? number = 1000 1.upto(4) do puts "#{number.class} #{number}" number = number * number end Fixnum 1000 Fixnum 1000000 Bignum 1000000000000 Bignum 1000000000000000000000000
    53. 53. Closures A closure is a function that is evaluated in an environment containing one or more bound variables. When called, the function can access these variables. The explicit use of closures is associated with functional programming and with languages such as ML and Lisp. Constructs such as objects in other languages can also be modeled with closures. -- Wikipedia
    54. 54. Closures A closure is a block of code that you can manipulate and query In Ruby we call them blocks or Procs A block is a pure closure A Proc is a block wrapped as an object We generally use the terms block and Proc interchangeably
    55. 55. Closures multiplier = 5 block = lambda {|number| puts number * multiplier } A block An instance of Proc lambda() is a method to convert blocks into Procs
    56. 56. Closures multiplier = 5 block = lambda {|number| puts number * multiplier } Parameter to the block
    57. 57. Closures multiplier = 5 block = lambda {|number| puts number * multiplier } Able to access variables from outside the block
    58. 58. Proc’s multiplier = 5 block = lambda {|number| puts number * multiplier } block.call 2 block.arity prints 10 returns number of parameters that the block takes. 1 in this case
    59. 59. Blocks as parameters multiplier = 5 1.upto(3) {|number| puts number * multiplier } => 5 => 10 => 15 Same block as before Called once for each time through the loop
    60. 60. Alternate syntax multiplier = 5 1.upto(3) {|number| puts number * multiplier } 1.upto(3) do |number| puts number * multiplier end Equivalent
    61. 61. Why are closures significant? Presence of closures in a language completely changes the design of the libraries Closure based libraries generally result in significantly less code
    62. 62. // Read the lines and split them into columns List<String[]> lines= new ArrayList<String[]>(); BufferedReader reader = null; try { reader = new BufferedReader(new FileReader("people.txt")); String line = reader.readLine(); while( line != null ) { lines.add( line.split("t") ); } } finally { if( reader != null ) { reader.close(); } } // then sort Collections.sort(lines, new Comparator<String[]>() { public int compare(String[] one, String[] two) { return one[1].compareTo(two[1]); } }); // then write them back out BufferedWriter writer = null; try { writer = new BufferedWriter( new FileWriter("people.txt") ); for( String[] strings : lines ) { StringBuilder builder = new StringBuilder(); for( int i=0; i<strings.length; i++ ) { if( i != 0 ) { builder.append("t"); } builder.append(strings[i]); } } } finally { if( writer != null ) { writer.close(); } } # Load the data lines = Array.new IO.foreach('people.txt') do |line| lines << line.split end # Sort and write it back out File.open('people.txt', 'w') do |file| lines.sort {|a,b| a[1] <=> b[1]}.each do |array| puts array.join("t") end end
    63. 63. Closure File Example file = File.new(fileName,'w') begin file.puts ‘some content’ rescue file.close end
    64. 64. Closure File Example file = File.new(fileName,'w') begin file.puts ‘some content’ rescue file.close end Only one line of business logic
    65. 65. Closure File Example file = File.new(fileName,'w') begin file.puts ‘some content’ rescue file.close end File.open(fileName,'w') do |file| file.puts ‘some content’ end
    66. 66. Ruby file IO sample # Load the data lines = Array.new IO.foreach('people.txt') do |line| lines << line.split end # Sort and write it back out File.open('people.txt', 'w') do |file| lines.sort {|a,b| a[1] <=> b[1]}.each do |array| puts array.join("t") end end
    67. 67. Closure-like things in Java final String name = getName(); new Thread( new Runnable() { public void run() { doSomething(name); } }).start(); Only one line of business logic
    68. 68. Closures for Java? There are a couple of proposals being debated for Java7 Unclear whether any of them will be accepted In the past, Sun’s position has been that closures didn’t make sense at this point in Java’s evolution public static void main(String[] args) { int plus2(int x) { return x+2; } int(int) plus2b = plus2; System.out.println(plus2b(2)); }
    69. 69. Inheriting behaviour from multiple places C++ has multiple inheritance Java has interfaces Ruby has mixins
    70. 70. C++ : multiple inheritance
    71. 71. Java : inheritance
    72. 72. Ruby : mixins
    73. 73. Mixins Cannot be instantiated Can be mixed in
    74. 74. Enumerable class Foo include Enumerable def each &block block.call 1 block.call 2 block.call 3 end end module Enumerable def collect array = [] each do |a| array << yield(a) end array end end
    75. 75. Enumerable class Foo include Enumerable def each &block block.call 1 block.call 2 block.call 3 end end module Enumerable def collect array = [] each do |a| array << yield(a) end array end end
    76. 76. Enumerable Requires that the class implement each() For max, min and sort the <=> operator is also needed Adds many methods for modifying, searching, sorting the items all?, any?, collect, detect, each_cons, each_slice, each_with_index, entries, enum_cons, enum_slice, enum_with_index, find, find_all, grep, include?, inject, map, max, member?, min, partition, reject, select, sort, sort_by, to_a, to_set, zip
    77. 77. Reopening classes class Foo def one puts 'one' end end
    78. 78. Reopening classes class Foo def one puts 'one' end end class Foo def two puts 'two' end end Reopening the same class
    79. 79. Reopening classes class Foo def one puts 'one' end end class Foo def one puts '1' end end Replacing, not adding a method
    80. 80. Reopening core classesclass String def one puts 'one' end end We reopened a CORE class and modified it
    81. 81. Metaprogramming Metaprogramming is the writing of computer programs that write or manipulate other programs (or themselves) as their data. In many cases, this allows programmers to get more done in the same amount of time as they would take to write all the code manually. -- Wikipedia
    82. 82. What changes can we make at runtime? Anything we can hand code, we can programmatically do Because of late binding, EVERYTHING happens at runtime
    83. 83. attr_accessor class Foo attr_accessor :bar end class Foo def bar @bar end def bar=(newBar) @bar = newBar end end Getter Setter
    84. 84. class Foo def self.attr_accessor name module_eval <<-DONE def #{name}() @#{name} end def #{name}=(newValue) @#{name} = newValue end DONE end my_attr_accessor :bar end Possible implementation of attr_accessor
    85. 85. class Foo def self.attr_accessor name module_eval <<-DONE def #{name}() @#{name} end def #{name}=(newValue) @#{name} = newValue end DONE end my_attr_accessor :bar end Possible implementation of attr_accessor “Here Doc” Evaluates to String
    86. 86. class Foo def self.attr_accessor name module_eval <<-DONE def #{name}() @#{name} end def #{name}=(newValue) @#{name} = newValue end DONE end my_attr_accessor :bar end Possible implementation of attr_accessor String substitution
    87. 87. class Foo def self.attr_accessor name module_eval <<-DONE def #{name}() @#{name} end def #{name}=(newValue) @#{name} = newValue end DONE end my_attr_accessor :bar end Possible implementation of attr_accessor Executes the string in the context of the class
    88. 88. Result class Foo def bar @bar end def bar=(newBar) @bar = newBar end end
    89. 89. ActiveRecord class ListItem < ActiveRecord::Base belongs_to :amazon_item acts_as_taggable acts_as_list :scope => :user end
    90. 90. Date :: once def once(*ids) # :nodoc: for id in ids module_eval <<-"end;", __FILE__, __LINE__ alias_method :__#{id.to_i}__, :#{id.to_s} private :__#{id.to_i}__ def #{id.to_s}(*args, &block) if defined? @__#{id.to_i}__ @__#{id.to_i}__ elsif ! self.frozen? @__#{id.to_i}__ ||= __#{id.to_i}__(*args, &block) else __#{id.to_i}__(*args, &block) end end end; end end
    91. 91. ObjectSpace ObjectSpace.each_object do |o| puts o end ObjectSpace.each_object(String) do |o| puts o end
    92. 92. ObjectSpace ObjectSpace.each_object do |o| puts o end ObjectSpace.each_object(String) do |o| puts o end All objects Only Strings
    93. 93. Continuations A snapshot of the call stack that the application can revert to at some point in the future
    94. 94. Why continuations? To save the state of the application across reboots of the VM To save the state of the application across requests to a web server Seaside (smalltalk) does this today
    95. 95. Downsides Only supported in one implementation of Ruby Will be removed from the language in Ruby 2.0
    96. 96. Implementations Ruby 1.8.x - “reference implementation” in C Ruby 1.9 - Next version of C interpreter Rubinius - Ruby in Ruby (sort-of) Cardinal - Ruby on Parrot Iron Ruby - Ruby on the DLR (Microsoft) Ruby.NET - Ruby on the CLR JRuby - Ruby on the JVM (Sun)
    97. 97. Implementations Ruby 1.8.x - “reference implementation” in C Ruby 1.9 - Next version of C interpreter Rubinius - Ruby in Ruby (sort-of) Cardinal - Ruby on Parrot Iron Ruby - Ruby on the DLR (Microsoft) Ruby.NET - Ruby on the CLR JRuby - Ruby on the JVM (Sun)
    98. 98. JRuby Runs on the Java Virtual Machine (JVM) Full implementation of the Ruby language Supported by Sun Runs many benchmarks faster than the 1.8 reference implementation (written in C) Able to easily call out to Java code
    99. 99. Ruby on Rails Web application framework Sweet spot - web application talking to a single relational database Allows very rapid development of web apps
    100. 100. Who’s using rails? Amazon • BBC • Cap Gemini Chicago Tribune • Barclays • BPN • Cisco CNET Electronic Arts • IBM • John Deere JP Morgan Chase • LA Times • Limewire Linked In • NASA • NBC • New York Times Oakley • Oracle • Orbitz • Turner Media twitter.com • Siemens • ThoughtWorks Yahoo!
    101. 101. JRuby on Rails? Yes! You can run a rails application on JRuby in a servlet container Goldspike is the servlet that dispatches to rails Tested on WebLogic, WebSphere, GlassFish, Jetty, Tomcat Warbler is the packaging tool that makes the WAR Supported on: WebLogic, WebSphere, GlassFish, Jetty, Tomcat
    102. 102. Recap Learning a new language will make you better with all the languages you know Ruby has a much more concise syntax which means that it takes much less code to solve the same problems Ruby is able to run on the JVM which makes it an option for shops with heavy investments in J2EE infrastructure
    103. 103. Recap Everything is an object The language is extremely malleable New classes/methods can be created on the fly Existing classes can be modified at any time
    104. 104. Contacting me Mike Bowler mbowler@GargoyleSoftware.com www.GargoyleSoftware.com (company) www.SphericalImprovement.com (blog) Interested in learning more about how Ruby and Java can coexist in your company? Just ask me.

    ×