Static or Dynamic Typing? Why not both?
Upcoming SlideShare
Loading in...5
×
 

Static or Dynamic Typing? Why not both?

on

  • 4,759 views

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

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

Statistics

Views

Total Views
4,759
Views on SlideShare
3,335
Embed Views
1,424

Actions

Likes
4
Downloads
24
Comments
0

16 Embeds 1,424

http://orugga.webcoding.com.ar 787
http://www.readshares.com 272
http://orugga 105
http://lanyrd.com 96
http://www.linkedin.com 85
http://www.orugga.com 31
http://orugga.com 23
http://www.readshares.in 7
http://4117394205971577459_239e7fa99943ea94edeaac2d75f2d9e07ba7d457.blogspot.com 6
https://www.linkedin.com 3
http://4117394205971577459_239e7fa99943ea94edeaac2d75f2d9e07ba7d457.blogspot.in 2
http://vrindavijayan.blogspot.in 2
https://twimg0-a.akamaihd.net 2
https://twitter.com 1
http://www.onlydoo.com 1
http://www.hanrss.com 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Apple Keynote

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • \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? Static or Dynamic Typing? Why not both? Presentation Transcript

  • 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 actual classes (beyond jrubyc) • Method signatures • Overloaded methods • Type erasure in generics • Subclassing • Annotations • Executable JAR files • Legacy applications
  • 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... • ...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
  • 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/
  • PerformanceJRuby performance is great and gettingbetter...(and it doesn’t matter if the application is waiting for theuser 10 times faster)
  • 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
  • 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 types • Implicits • The Dynamic trait• Scala libraries
  • 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)
  • 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
  • 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”)
  • 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
  • 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
  • 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
  • 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)
  • Scala Libraries• Akka• Parser combinators• Play / Lift / Scalatra / ...
  • Akka• Based on the Actor model (Erlang)• Message passing• Transparent distribution• Messaging system integration • AMQP • Apache Camel • HTTP • ...• Software Transactional Memory
  • 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!
  • 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’ => 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
  • 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  }}
  • 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”}
  • 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
  • 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 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
  • 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 possible• Static typing as far as possible
  • 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
  • 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    def initialize (firstname, lastname)      @firstname = firstname      @lastname = lastname   end    def fullname      "#{firstname} #{lastname}"    end    def get_label      javax.swing.JLabel.new(fullname)    end  end...
  • 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
  • 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("[]")
  • 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")
  • 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)
  • 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")
  • 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
  • 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
  • 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
  • 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.*)
  • 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.abstra.cc Special thanks to @MadridJUG