Static or Dynamic Typing?     Why Not Both?       Mixing JRuby and Scala           Mario Camou            @thedoc
Agenda• Why?• Why Scala?• Calling Scala from JRuby• Calling JRuby from Scala• Q&A
Why?
Why Not?• The JVM allows us to mix-and-match• Use the right tool for each part of  the job
Why?Ruby (and dynamic languages in general) aregreat•   Rapid development•   Flexibility•   Duck-typing•   Metaprogramming
Why?...but there are some pitfalls•   Integration•   Correctness•   Performance•   Productivity
IntegrationJRuby gives you access to any Java librariesand frameworks...
Integration...but not all of them are JRuby-friendly   (even though JRuby keeps getting better!)   •  Class names and actu...
IntegrationUse statically-typed proxies to bridge the gap      http://fffff.at/free-universal-construction-kit/
Correctness •   Static analysis •   Refactoring •   Self-documentation •   Type errors •   Unit tests can help...     •   ...
Correctness• Use a statically-typed language for critical or  library code• Use a dynamically-typed language for high-  le...
PerformanceJRuby performance is great and gettingbetter...(and it doesn’t matter if the application is waiting for theuser...
Performance• For some tasks, static typing can be faster     •    Heavy computation     •    Method lookup     •    method...
PerformanceImplement performance-critical tasks in acompiled statically-typed language
Productivity• Refactoring (again!)• Code navigation• IDE help (method parameters, autocomplete, ...)
Agenda• Why?• Why Scala?• Calling Scala from JRuby• Calling JRuby from Scala• Q&A
Why Scala?• Simplified syntax• Functional programming• Dynamic-language features  •   Mix-ins (traits)  •   Structural type...
Simplified Syntax•   Case classescase class Person (firstName:String, lastName:String)•   Type inferenceval m = new HashMap[...
Functional ProgrammingMixed OO - Functional model•   Closures / partial functions    •   foreach, map, fold, filter, ...   ...
Traits• Interfaces with method definitions• Can be used for mix-ins• Calling the previous method in the chain  with no alia...
Structural Types• Declare what you need, not the type• Statically-typed duck typingclass Foo { def x = "Foo.x" }class Bar ...
Implicits• Automatically convert one object to another type• Solve some of the same problems as open classesclass MyRichSt...
ImplicitsIn Scala:                                       In Ruby:implicit def newLT(i: Int) = new {              class Fix...
The Dynamic Trait  • Similar to method_missing  • Experimental in 2.9, available in 2.10object Test extends Dynamic {  def...
Scala Libraries• Akka• Parser combinators• Play / Lift / Scalatra / ...
Akka• Based on the Actor model (Erlang)• Message passing• Transparent distribution• Messaging system integration •   AMQP ...
Akka• Mikka: Actors in JRuby by Theo Hultberg  (@iconara)• Thin wrapper around Akka Java API to  make it more Ruby-like• h...
Agenda• Why?• Why Scala?• Calling Scala from JRuby• Calling JRuby from Scala• Q&A
Calling Scala from JRuby• Just like Java!• JRuby sugar  •   1.6.0+  •   1.6.6+
Just like Java!In Scala:                                 In JRuby:package app.helpers                       require ‘java’...
Just like Java!     Functions / blocks / closuresIn Scala:                             In JRuby:package app.helpers       ...
JRuby Sugar - 1.6.0+  Singleton (Scala object) support  Call Singleton methods just like static/class methodsIn Scala:    ...
JRuby Sugar - 1.6.6+ Operator aliases $plus -> + $minus -> - $div -> / $plus$eq -> += apply (a.k.a. ()) -> [] update (a.k....
Agenda• Why?• Why Scala?• Calling Scala from JRuby• Calling JRuby from Scala• Q&A
Calling JRuby from Scala• JRuby Embed API (RedBridge / JSR-223)• Scuby
JRuby Embed APIval container = new ScriptingContainerval receiver = container.runScriptlet("""# Radioactive decaydef amoun...
Scuby• Goals• Assumptions and defaults• Usage and examples• Future steps
Scuby Goals• Thin DSL layer between Scala and JRuby• Simplify calling JRuby• Calling JRuby should be as transparent as pos...
Assumptions & Defaults•   Single JRuby engine    •   For our needs, we don’t need more    •   You don’t have to pass in th...
Usage• require & eval• Creating objects• Calling methods• Convenience methods• Additional facilities
Example Ruby File# File test.rb (from the Scuby tests)module Core  class Person    attr_accessor :firstname, :lastname    ...
Example Ruby File...  module Backend   def self.get_people      # Get data from the backend and return an Array of Person ...
require & evalimport cc.abstra.scuby.JRuby._// Require a Ruby file from the classpathrequire("test")// Eval a Ruby stateme...
Creating Objectsimport cc.abstra.scuby._// Create a Ruby objectval array3 = new RubyObject(Array)// Create a proxy object ...
Calling Methods    // Call a method on a Ruby object (in this case, the Ruby class),    // passing in parameters, and get ...
Arrays and Hashes// Access to a Ruby Hash or Array (i.e., anything that implements [])// and creating a Ruby Symbol using ...
Convenience Methods• toString, equals, hashCode   •   Forwarded to their Ruby equivalents (#to_s, #==,       #hash)• respo...
Wrapping in Traitstrait   Person {  def   firstname: String  def   firstname_=(f: String): Unit  def   lastname: String  d...
UsageTo use Scuby: • Use the Source! (Pull requests welcome)   •   https://github.com/abstracc/scuby   •   Build using Mav...
Future Steps• Scala side  •   Ruby collections  •   Java-friendly API  •   Optimization• Ruby side  •   Create a Scuby gem...
Agenda• Why?• Why Scala?• Calling Scala from JRuby• Calling JRuby from Scala• Q&A
Thank you         Mario Camou          @thedochttp://github.com/abstracc/scuby   http://github.com/mcamou       http://www...
Upcoming SlideShare
Loading in …5
×

Static or Dynamic Typing? Why not both?

6,607 views
5,944 views

Published on

Integrating Scala and JRuby - full video of presentation at JRubyConfEU 2012 is at https://vimeo.com/47928462 .

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

No Downloads
Views
Total views
6,607
On SlideShare
0
From Embeds
0
Number of Embeds
1,489
Actions
Shares
0
Downloads
27
Comments
0
Likes
5
Embeds 0
No embeds

No notes for slide
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Static or Dynamic Typing? Why not both?

    1. Static or Dynamic Typing? Why Not Both? Mixing JRuby and Scala Mario Camou @thedoc
    2. Agenda• Why?• Why Scala?• Calling Scala from JRuby• Calling JRuby from Scala• Q&A
    3. Why?
    4. Why Not?• The JVM allows us to mix-and-match• Use the right tool for each part of the job
    5. Why?Ruby (and dynamic languages in general) aregreat• Rapid development• Flexibility• Duck-typing• Metaprogramming
    6. Why?...but there are some pitfalls• Integration• Correctness• Performance• Productivity
    7. IntegrationJRuby gives you access to any Java librariesand frameworks...
    8. Integration...but not all of them are JRuby-friendly (even though JRuby keeps getting better!) • Class names and actual classes (beyond jrubyc) • Method signatures • Overloaded methods • Type erasure in generics • Subclassing • Annotations • Executable JAR files • Legacy applications
    9. IntegrationUse statically-typed proxies to bridge the gap http://fffff.at/free-universal-construction-kit/
    10. Correctness • Static analysis • Refactoring • Self-documentation • Type errors • Unit tests can help... • ...but they have to be complete... • ...and they don’t cover all possible scenarios... • ...and tracking down type errors can be Hellhttp://evanfarrer.blogspot.com.es/2012/06/unit-testing-isnt-enough-you-need.html
    11. Correctness• Use a statically-typed language for critical or library code• Use a dynamically-typed language for high- level dynamic code and DSLs http://olabini.com/blog/2008/06/fractal-programming/
    12. PerformanceJRuby performance is great and gettingbetter...(and it doesn’t matter if the application is waiting for theuser 10 times faster)
    13. Performance• For some tasks, static typing can be faster • Heavy computation • Method lookup • method_missing • Some benchmarks: http://shootout.alioth.debian.org/u32/performance.php
    14. PerformanceImplement performance-critical tasks in acompiled statically-typed language
    15. Productivity• Refactoring (again!)• Code navigation• IDE help (method parameters, autocomplete, ...)
    16. Agenda• Why?• Why Scala?• Calling Scala from JRuby• Calling JRuby from Scala• Q&A
    17. Why Scala?• Simplified syntax• Functional programming• Dynamic-language features • Mix-ins (traits) • Structural types • Implicits • The Dynamic trait• Scala libraries
    18. Simplified Syntax• Case classescase class Person (firstName:String, lastName:String)• Type inferenceval m = new HashMap[Int, String]• No getters / settersUnless you really need them• More flexible method names (think DSLs)Use (almost) any characterTranslated to legal names in bytecode (i.e., + is $plus, += is $plus$eq)
    19. Functional ProgrammingMixed OO - Functional model• Closures / partial functions • foreach, map, fold, filter, ... • Define your own control structures• Immutable eager and lazy values• Pattern matching• For comprehensions
    20. Traits• Interfaces with method definitions• Can be used for mix-ins• Calling the previous method in the chain with no aliasing• Dependency injection (“cake pattern”)
    21. Structural Types• Declare what you need, not the type• Statically-typed duck typingclass Foo { def x = "Foo.x" }class Bar { def x = "Bar.x" }def doIt (arg: { def x:String }) = arg.xscala> doIt(new Foo)res0: String = Foo.xscala> doIt(new Bar)res1: String = Bar.x
    22. Implicits• Automatically convert one object to another type• Solve some of the same problems as open classesclass MyRichString(str: String) {  def acronym = str.toCharArray.foldLeft("") { (t, c) =>    t + (if (c.isUpperCase) c.toString else "")  }} implicit def str2MRString(str: String) = new MyRichString(str)scala> "The HitchHikers Guide To The Galaxy".acronymres0: java.lang.String = THHGTTG
    23. ImplicitsIn Scala: In Ruby:implicit def newLT(i: Int) = new { class Fixnum  def <(str: String) = i < str.length   alias_method :__old_lt, <.to_sym}   def <(target)     if target.kind_of? String       __old_lt__ target.sizescala> 1 < "foo"     elseres0: Boolean = false       __old_lt__ target     endscala> 5 < "foo"   endres1: Boolean = true endhttp://www.codecommit.com/blog/ruby/implicit-conversions-more-powerful-than-dynamic-typing
    24. The Dynamic Trait • Similar to method_missing • Experimental in 2.9, available in 2.10object Test extends Dynamic {  def applyDynamic (method:String) (args: Any*) {    println ("%s (%s)".format(method, args.mkString(",")))  }}scala> Test.foo("bar",baz, 1)foo (bar,baz, 1)
    25. Scala Libraries• Akka• Parser combinators• Play / Lift / Scalatra / ...
    26. Akka• Based on the Actor model (Erlang)• Message passing• Transparent distribution• Messaging system integration • AMQP • Apache Camel • HTTP • ...• Software Transactional Memory
    27. Akka• Mikka: Actors in JRuby by Theo Hultberg (@iconara)• Thin wrapper around Akka Java API to make it more Ruby-like• https://github.com/iconara/mikka• ...for more info ask Theo!
    28. Agenda• Why?• Why Scala?• Calling Scala from JRuby• Calling JRuby from Scala• Q&A
    29. Calling Scala from JRuby• Just like Java!• JRuby sugar • 1.6.0+ • 1.6.6+
    30. Just like Java!In Scala: In JRuby:package app.helpers require ‘java’ => trueimport scala.reflect.BeanProperty f = Java::app.helpers.Foo.new => #<Java::AppHelpers::Foo:0x325bc91>class Foo { f.q = "Life, the Universe and Everything"  private var question: String = "" => "Life, the Universe and Everything"  @BeanProperty var a: String = "" f.a = "42" => "42"  def questionAndAnswer = "Unknowable" f.q => "Life, the Universe and Everything"  def setQ(s:String) = { question = s } f.a  def getQ = question => "42"} f.question_and_answer => "Unknowable" https://github.com/jruby/jruby/wiki/CallingJavaFromJRuby
    31. Just like Java! Functions / blocks / closuresIn Scala: In JRuby:package app.helpers f = Java::app.helpers.Foo.new => #<Java::AppHelpers::Foo:0x325bc91>class Foo { f(1, 2, 3) { |x, y| x + y }  def test(x:Int, y:Int, z:Int, => true           f:(Int, Int) => Int) = {    f(x,y) == z  }}
    32. JRuby Sugar - 1.6.0+ Singleton (Scala object) support Call Singleton methods just like static/class methodsIn Scala: In JRuby:package app.helpers require ‘java’ # => trueobject Foo { Java::app.helpers.Foo.test  def test = "Static method" # => “Static method”}
    33. JRuby Sugar - 1.6.6+ Operator aliases $plus -> + $minus -> - $div -> / $plus$eq -> += apply (a.k.a. ()) -> [] update (a.k.a. ()=) -> []= ... There are some caveats... seehttps://github.com/jruby/jruby/wiki/Integrating-with-Scala
    34. Agenda• Why?• Why Scala?• Calling Scala from JRuby• Calling JRuby from Scala• Q&A
    35. Calling JRuby from Scala• JRuby Embed API (RedBridge / JSR-223)• Scuby
    36. JRuby Embed APIval container = new ScriptingContainerval receiver = container.runScriptlet("""# Radioactive decaydef amount_after_years(q0, t) q0 * Math.exp(1.0 / $half_life * Math.log(1.0/2.0) * t)enddef years_to_amount(q0, q) $half_life * (Math.log(q) - Math.log(q0)) / Math.log(1.0/2.0)end""")container.put("$half_life", 24100) // Plutoniumval args = Array[Object](10.0:java.lang.Double, 1000:java.lang.Integer)val result = container.callMethod("amount_after_years", args, Double.class) https://github.com/jruby/jruby/wiki/RedBridgeExamples
    37. Scuby• Goals• Assumptions and defaults• Usage and examples• Future steps
    38. Scuby Goals• Thin DSL layer between Scala and JRuby• Simplify calling JRuby• Calling JRuby should be as transparent as possible• Static typing as far as possible
    39. Assumptions & Defaults• Single JRuby engine • For our needs, we don’t need more • You don’t have to pass in the engine to every call• Singleton interpreter scope (default) • Otherwise you can get things like nil != nil • Can be changed before first JRuby call• Transient local variable behavior (default) • Local variables don’t survive multiple evaluations • If you need them to persist, store in a Scala val (and pass as parameter)... • ...or change before first JRuby call
    40. Usage• require & eval• Creating objects• Calling methods• Convenience methods• Additional facilities
    41. Example Ruby File# File test.rb (from the Scuby tests)module Core  class Person    attr_accessor :firstname, :lastname    def initialize (firstname, lastname)      @firstname = firstname      @lastname = lastname   end    def fullname      "#{firstname} #{lastname}"    end    def get_label      javax.swing.JLabel.new(fullname)    end  end...
    42. Example Ruby File...  module Backend   def self.get_people      # Get data from the backend and return an Array of Person    end    def self.get_data      { :people => get_people, :other_data => get_other_data }    end    def self.get_person(name)      # Get a persons data from the DB and return a Person object    end    def self.get_other_data      # Get some other data that is needed for the app    end  endend
    43. require & evalimport cc.abstra.scuby.JRuby._// Require a Ruby file from the classpathrequire("test")// Eval a Ruby statement discarding the return valueeval("import Core")// Eval a Ruby statement that returns a Ruby objectval array = eval[RubyObj]("[]")// Or with type inferenceval array2:RubyObj = eval("[]")
    44. Creating Objectsimport cc.abstra.scuby._// Create a Ruby objectval array3 = new RubyObject(Array)// Create a proxy object for the Ruby BackEnd classval backend = RubyClass(Backend)// Create an instance of the Person classval person = new RubyObject(Person, "Zaphod", "Beeblebrox")val person2 = RubyClass(Person) ! (new, "Ford", "Prefect")
    45. Calling Methods    // Call a method on a Ruby object (in this case, the Ruby class),    // passing in parameters, and get back another Ruby object    val zaphod = backend ! (get_person, "Zaphod")    // Call a Ruby method with no parameters    val data = backend ! get_data    // Ruby method chaining    val length = backend ! get_people ! length    // Get a reference to a Ruby method that can later be called    val getPerson = backend --> get_person    // Call the method. Returns an AnyRef.    // With the above, these 2 lines are equivalent:    getPerson("Zaphod")    backend(get_person, "Zaphod")    // Call a Ruby method which returns a Java object, // in a type-safe way    val label = person.send[JLabel](get_label)
    46. Arrays and Hashes// Access to a Ruby Hash or Array (i.e., anything that implements [])// and creating a Ruby Symbol using %val people = data(%(people))val zaphod2 = people(0)// Multidimensional Hashes or Arrays (i.e., data["parm1"]["parm2"])val ford = data(%(people), 1)// Modify/add an element to a Hash or Array (or anything that// implements []=)people(2) = RubyClass(Person) ! (new, "Arthur", "Dent")
    47. Convenience Methods• toString, equals, hashCode • Forwarded to their Ruby equivalents (#to_s, #==, #hash)• respondTo_? array3 respondTo_? length // true array3 respondTo_? foo // false• isA_? array3 isA_? Array // true array3 isA_? Hash // false
    48. Wrapping in Traitstrait Person {  def firstname: String  def firstname_=(f: String): Unit  def lastname: String  def lastname_=(l: String): Unit  def fullname: String  def getLabel: JLabel}val zaphod = backend(get_person, "Zaphod").as[Person]zaphod.firstname = "The Zeeb"println(zaphod.fullname)val label = zaphod.getLabel
    49. UsageTo use Scuby: • Use the Source! (Pull requests welcome) • https://github.com/abstracc/scuby • Build using Maven • Download the compiled artifacts • https://oss.sonatype.org/content/repositories/releases/cc/abstra/ pasilla/scuby/0.1.8/ • You also need scala-library-2.9.2.jar and jruby-complete-1.6.7.jar • Add all the .jar’s to your CLASSPATH • Use Maven (or SBT, Gradle, ...) • groupId: cc.abstra.pasilla • artifactId: scuby • Current version: 0.1.8
    50. Future Steps• Scala side • Ruby collections • Java-friendly API • Optimization• Ruby side • Create a Scuby gem • FunctionN -> block conversion • Wrapping Scala collections • Object#to_scala • scala top-level function (so we can, i.e., import scala.*)
    51. Agenda• Why?• Why Scala?• Calling Scala from JRuby• Calling JRuby from Scala• Q&A
    52. Thank you Mario Camou @thedochttp://github.com/abstracc/scuby http://github.com/mcamou http://www.abstra.cc Special thanks to @MadridJUG

    ×