Upgrade to Pro — share decks privately, control downloads, hide ads and more …

jRuby: The best of both worlds

jRuby: The best of both worlds

A brief introduction to ruby and jRuby, and how to access the java from ruby and visa versa.

autonomous

March 27, 2012
Tweet

More Decks by autonomous

Other Decks in Technology

Transcript

  1. Yukihiro “Matz” Matsumoto “I wanted a scripting language that was

    more powerful than Perl, and more object-oriented than Python...” Tuesday 27 March 12
  2. “[We] need to focus on humans, on how humans care

    about doing programming... We are the masters. They are the slaves.” Tuesday 27 March 12
  3. “I hope to see Ruby help every programmer in the

    world be productive, and to enjoy programming, and to be happy. This is the primary purpose of Ruby language” Tuesday 27 March 12
  4. # booleans truth = true lies = false # Strings

    dude = 'Matz' credo = "#{dude} is nice, so we are nice!" # Numbers 42 ** 13 53.8 / 9 19 % 3 Tuesday 27 March 12
  5. # Arrays backpack = [6, 'apple', [true, some_object]] # Hashes

    hash = { true => 'He loves me!', dude => 'Must obey!', backpack => false } # symbols cities = [:paris, :new_york, :johannesburg] Tuesday 27 March 12
  6. coders = [ { 'language' => 'ruby', 'location' => 'johannesburg'

    }, { 'language' => 'java', 'location' => 'port elizabeth' }, # ... { 'language' => 'ruby', 'location' => 'pretoria' } ] # vs. coders = [ { :language => 'ruby', :location => 'johannesburg' }, { :language => 'java', :location => 'port elizabeth' }, # ... { :language => 'ruby', :location => 'pretoria' } ] Tuesday 27 March 12
  7. public Class Person { private String firstName, lastName; public Person(String

    firstName, String lastName){ setFirstName(firstName); setLastName(lastName); } public String getFirstName(){ return firstName; } public String getLastName(){ return lastName; } public String setFirstName(String firstName){ this.firstName = firstName; } public String setLastName(String lastName){ this.lastName = lastName; } } Tuesday 27 March 12
  8. class Person attr_accessor :first_name, :last_name def initialize(first_name, last_name) @first_name =

    first_name @last_name = last_name end end person = Person.new( 'Nick', 'Cave') person.first_name = 'Slick' person.last_name = 'Nave' puts "#{person.first_name} #{person.last_name}" Tuesday 27 March 12
  9. true.class() # => TrueClass false.to_s() # => "false" 5.9.floor() #

    => 5 3.times{ puts('Hello JUG!') } # => Hello JUG! # => Hello JUG! # => Hello JUG! Tuesday 27 March 12
  10. module Earth end class Person attr_reader :first_name, :last_name def initialize(first_name,

    last_name) @first_name, @last_name = first_name, last_name end end Tuesday 27 March 12
  11. module Earth end class Person attr_reader :first_name, :last_name def initialize(first_name,

    last_name) @first_name, @last_name = first_name, last_name end end chap = Earth::Person.new('Chandler', 'Bing') chap.first_name # => Chandler Tuesday 27 March 12
  12. module RepublicPersonnel def storm_trooper Earth::Person.new('Storm', 'Trooper') end end class CloningVat

    extend RepublicPersonnel end #<Earth::Person @last_name="Trooper", @first_name="Storm"> CloningVat.storm_trooper Tuesday 27 March 12
  13. module TehForce def sense '... a disturbance in the force'

    end end module Earth class Person include TehForce end end Tuesday 27 March 12
  14. module TehForce def sense '... a disturbance in the force'

    end end module Earth class Person include TehForce end end farm_boy = Earth::Person.new('Luke', 'Skywalker') # => '... a disturbance in the force' farm_boy.sense Tuesday 27 March 12
  15. def other_days( this_happens, and_that_happens) puts 'The sun rises' puts this_happens

    puts and_that_happens puts 'The sun sets' end some_days 'I do some work' other_days 'I skip', 'I read a book' def some_days( something_happens ) puts 'The sun rises' puts something_happens puts 'The sun sets' end Tuesday 27 March 12
  16. def some_days( something_happens ) puts 'The sun rises' puts something_happens

    puts 'The sun sets' end def some_days puts 'The sun rises' yield puts 'The sun sets' end some_days { puts 'I go to work' } some_days do puts 'I skip' puts 'I read a book' end Tuesday 27 March 12
  17. File.open('i <3 ruby.txt', 'w') do |file| file.puts "... i really

    do!" end file = File.open('i <3 ruby.txt', 'w') file.puts "... i really do!" file.close Tuesday 27 March 12
  18. Rubyists TATFT! describe Calculator do before(:each) do @calc = Calculator.new

    end context 'Addition' do it 'returns 10 when adding 5 and 5' @calc.add(5,5).should == 10 end it 'returns 0 when adding 5 and -5' do @calc.add(5,-5).should == 0 end end # ... end Tuesday 27 March 12
  19. class Person def initialize @height, @weight, @hair_color = 6.2, '70kg',

    'brown' end %w(height weight hair).each do |property| define_method("#{property}") do i_var = self.instance_eval("@#{property}") i_var.to_s.upcase end end def method_missing(*args, &block) puts "I dont have #{args[0].to_s.gsub(/_/, ' ')}" end end p = Person.new p.my_height # => 6.2 p.my_weight # => 70KG p.my_hair_color # => BROWN p.your_car_keys # => I dont have your car keys Tuesday 27 March 12
  20. Interactive Ruby $ jirb jruby-1.6.7 :001 > require 'java' =>

    true jruby-1.6.7 :001 > #... Tuesday 27 March 12
  21. class Ackermann def self.ack(m, n) return n + 1 if

    m.zero? return ack(m - 1, 1) if n.zero? ack( m - 1, ack(m, n - 1) ) end end Tuesday 27 March 12
  22. include Rubeus::Swing JFrame.new('Ackerizer') do |frame| frame.layout = java.awt.FlowLayout.new @m, @n

    = JTextField.new('3'),JTextField.new('10') JButton.new('->') do start = Time.now @result.text = Ackermann.ack( @m.text.to_i, @n.text.to_i ).to_s puts "#{Time.now - start}" end @result = JTextField.new 10 frame.pack frame.show end Tuesday 27 March 12
  23. class Ackermann def self.ack(m, n) return n + 1 if

    m.zero? return ack(m - 1, 1) if n.zero? ack( m - 1, ack(m, n - 1) ) end end Tuesday 27 March 12
  24. class Ackermann def self.ack(m, n) return n + 1 if

    m.zero? return ack(m - 1, 1) if n.zero? ack( m - 1, ack(m, n - 1) ) end end public class Ackermann { public static int ack(int m, int n) { if (m == 0) return n + 1; if (n == 0) return ack(m - 1, 1); return ack(m - 1, ack(m, n - 1)); } } Tuesday 27 March 12
  25. include Rubeus::Swing JFrame.new('Ackerizer') do |frame| frame.layout = java.awt.FlowLayout.new @m, @n

    = JTextField.new('3'),JTextField.new('10') JButton.new('->') do start = Time.now @result.text = Java::Ackermann.ack( @m.text.to_i, @n.text.to_i ).to_s puts "#{Time.now - start}" end @result = JTextField.new 10 frame.pack frame.show end Tuesday 27 March 12
  26. Method overloading public class OverloadTypeChecker { public static String inspect(long

    value) { return "long"; } public static String inspect(String value) { return "string"; } public static String inspect(Object value) { return "object"; } } Tuesday 27 March 12
  27. require 'java' java_import 'OverloadTypeChecker' do 'OTC' end # jRuby happily

    handles the simple case OTC.inspect(5) # long OTC.inspect('Helloooo!') # string OTC.inspect([]) # object Tuesday 27 March 12
  28. public class BitLength { public int neededFor(int i) { return

    32; } public int neededFor(long l) { return 64; } } Tuesday 27 March 12
  29. # jRuby can be forced to use a specific overload

    require 'java' java_import 'BitLength' bits = BitLength.new bits.needed_for(1_000_000) # 64 Tuesday 27 March 12
  30. # jRuby can be forced to use a specific overload

    require 'java' java_import 'BitLength' bits = BitLength.new bits.needed_for(1_000_000) # 64 # java_send bits.java_send :neededFor, [Java::int], 1_000_000 # 32 Tuesday 27 March 12
  31. # jRuby can be forced to use a specific overload

    require 'java' java_import 'BitLength' bits = BitLength.new bits.needed_for(1_000_000) # 64 # java_alias class BitLength java_alias :needed_for_int, :neededFor, [Java::int] end bits.needed_for_int 1_000_000 # 32 # java_send bits.java_send :neededFor, [Java::int], 1_000_000 # 32 Tuesday 27 March 12
  32. # jRuby can be forced to use a specific overload

    require 'java' java_import 'BitLength' bits = BitLength.new bits.needed_for(1_000_000) # 64 # java_method needed = bits.java_method :neededFor, [Java::int] needed.call 1_000_000 # 32 # java_alias class BitLength java_alias :needed_for_int, :neededFor, [Java::int] end bits.needed_for_int 1_000_000 # 32 # java_send bits.java_send :neededFor, [Java::int], 1_000_000 # 32 Tuesday 27 March 12
  33. public class TypeChecker{ public static String check(Object o){ return o.getClass().getName();

    } } require 'java' ruby_array = [1, 2, 'Mushrooms', :sample] java_array = ruby_array.to_java # org.jruby.RubyArray Java::TypeChecker.check( ruby_array ) # [Ljava.lang.Object; Java::TypeChecker.check( java_array ) # org.jruby.RubyArray Java::TypeChecker.check( java_array.to_a ) Tuesday 27 March 12
  34. Awesome, but why? • Cross platform GUI dev • Performance

    • Ruby interface to legacy code • Use a ruby test framework (Seriously, they’re amazing!) • Utilize java libraries • Sneak ruby into a java shop • Threading Tuesday 27 March 12
  35. import org.jruby.embed.InvokeFailedException; import org.jruby.embed.ScriptingContainer; public class RubyFromJava { public static

    void main(String[] args) { ScriptingContainer container = new ScriptingContainer(); container.runScriptlet("puts 'Java touched my Ruby'"); } } $ java -cp jruby-complete.jar:. RubyFromJava Java touched my Ruby Tuesday 27 March 12