SlideShare a Scribd company logo
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) are
great
•   Rapid development
•   Flexibility
•   Duck-typing
•   Metaprogramming
Why?


...but there are some pitfalls
•   Integration
•   Correctness
•   Performance
•   Productivity
Integration



JRuby gives you access to any Java libraries
and 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
Integration

Use 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 Hell
http://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/
Performance


JRuby performance is great and getting
better...
(and it doesn’t matter if the application is waiting for the
user 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
Performance



Implement performance-critical tasks in a
compiled 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 classes
case class Person (firstName:String, lastName:String)

•   Type inference
val m = new HashMap[Int, String]

•   No getters / setters
Unless you really need them

•   More flexible method names (think DSLs)
Use (almost) any character
Translated to legal names in bytecode (i.e., + is $plus, += is $plus$eq)
Functional Programming

Mixed 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 typing
class Foo { def x = "Foo.x" }

class Bar { def x = "Bar.x" }

def doIt (arg: { def x:String }) = arg.x


scala> doIt(new Foo)
res0: String = Foo.x

scala> doIt(new Bar)
res1: String = Bar.x
Implicits

• Automatically convert one object to another type
• Solve some of the same problems as open classes
class 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 HitchHiker's Guide To The Galaxy".acronym
res0: java.lang.String = THHGTTG
Implicits
In 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.size
scala> 1 < "foo"                                    else
res0: Boolean = false                                 __old_lt__ target
                                                    end
scala> 5 < "foo"                                  end
res1: Boolean = true                            end




http://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.10
object 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’
                                          => true
import 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 / closures
In 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 methods


In Scala:                            In JRuby:

package app.helpers                  require ‘java’
                                     # => true
object 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... see
https://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 API

val container = new ScriptingContainer
val receiver = container.runScriptlet("""
# Radioactive decay
def amount_after_years(q0, t)
  q0 * Math.exp(1.0 / $half_life * Math.log(1.0/2.0) * t)
end
def 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) // Plutonium
val 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 person's 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
  end
end
require & eval

import cc.abstra.scuby.JRuby._

// Require a Ruby file from the classpath
require("test")

// Eval a Ruby statement discarding the return value
eval("import Core")

// Eval a Ruby statement that returns a Ruby object
val array = eval[RubyObj]("[]")

// Or with type inference
val array2:RubyObj = eval("[]")
Creating Objects

import cc.abstra.scuby._

// Create a Ruby object
val array3 = new RubyObject('Array)

// Create a proxy object for the Ruby BackEnd class
val backend = RubyClass('Backend)

// Create an instance of the Person class
val 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 Traits
trait   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
Usage
To 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
          @thedoc

http://github.com/abstracc/scuby
   http://github.com/mcamou
       http://www.abstra.cc

  Special thanks to @MadridJUG

More Related Content

What's hot (18)

PDF
JRuby and Invokedynamic - Japan JUG 2015
Charles Nutter
 
ODP
Scala ntnu
Alf Kristian Støyle
 
PDF
Scala at HUJI PL Seminar 2008
Yardena Meymann
 
PDF
Java 7 New Features
Jussi Pohjolainen
 
PDF
What's a macro?: Learning by Examples / Scalaのマクロに実用例から触れてみよう!
scalaconfjp
 
PPT
Scala Talk at FOSDEM 2009
Martin Odersky
 
PPT
java training faridabad
Woxa Technologies
 
PPTX
Scala Intro
Alexey (Mr_Mig) Migutsky
 
PDF
Down the Rabbit Hole: An Adventure in JVM Wonderland
Charles Nutter
 
PDF
Java SE 8 best practices
Stephen Colebourne
 
PDF
Java 5 and 6 New Features
Jussi Pohjolainen
 
PPTX
A brief tour of modern Java
Sina Madani
 
PDF
An Introduction to Scala for Java Developers
Miles Sabin
 
PDF
Scala : language of the future
AnsviaLab
 
PPTX
Scala Matsuri 2016: Japanese Text Mining with Scala and Spark
Eduardo Gonzalez
 
PPT
Scala introduction
Yardena Meymann
 
PDF
camel-scala.pdf
Hiroshi Ono
 
PPTX
A Brief Intro to Scala
Tim Underwood
 
JRuby and Invokedynamic - Japan JUG 2015
Charles Nutter
 
Scala at HUJI PL Seminar 2008
Yardena Meymann
 
Java 7 New Features
Jussi Pohjolainen
 
What's a macro?: Learning by Examples / Scalaのマクロに実用例から触れてみよう!
scalaconfjp
 
Scala Talk at FOSDEM 2009
Martin Odersky
 
java training faridabad
Woxa Technologies
 
Down the Rabbit Hole: An Adventure in JVM Wonderland
Charles Nutter
 
Java SE 8 best practices
Stephen Colebourne
 
Java 5 and 6 New Features
Jussi Pohjolainen
 
A brief tour of modern Java
Sina Madani
 
An Introduction to Scala for Java Developers
Miles Sabin
 
Scala : language of the future
AnsviaLab
 
Scala Matsuri 2016: Japanese Text Mining with Scala and Spark
Eduardo Gonzalez
 
Scala introduction
Yardena Meymann
 
camel-scala.pdf
Hiroshi Ono
 
A Brief Intro to Scala
Tim Underwood
 

Similar to Static or Dynamic Typing? Why not both? (20)

PDF
Using Java from Ruby with JRuby IRB
Hiro Asari
 
KEY
Практики применения JRuby
.toster
 
PDF
Quick Intro To JRuby
Frederic Jean
 
PDF
Clojure - A new Lisp
elliando dias
 
PDF
JRuby and You
Hiro Asari
 
PDF
Crystal presentation in NY
Crystal Language
 
PDF
Ruby 101 && Coding Dojo
Guilherme
 
PDF
BCS SPA 2010 - An Introduction to Scala for Java Developers
Miles Sabin
 
PDF
Ugo Cei Presentation
RubyOnRails_dude
 
PDF
JRuby @ Boulder Ruby
Nick Sieger
 
KEY
JRuby: What's Different (RORO Melbourne October 2011)
Charles Nutter
 
PDF
Clojure for Rubyists
Jean-François Héon
 
KEY
Euruko 2012 - JRuby
Charles Nutter
 
PPTX
All about scala
Yardena Meymann
 
PDF
Scala days mizushima
Skills Matter Talks
 
PDF
Thnad's Revenge
Erin Dees
 
PDF
Intro to J Ruby
Frederic Jean
 
PDF
Ruby & Machine Vision - Talk at Sheffield Hallam University Feb 2009
Jan Wedekind
 
PDF
A Tour Through the Groovy Ecosystem
Leonard Axelsson
 
Using Java from Ruby with JRuby IRB
Hiro Asari
 
Практики применения JRuby
.toster
 
Quick Intro To JRuby
Frederic Jean
 
Clojure - A new Lisp
elliando dias
 
JRuby and You
Hiro Asari
 
Crystal presentation in NY
Crystal Language
 
Ruby 101 && Coding Dojo
Guilherme
 
BCS SPA 2010 - An Introduction to Scala for Java Developers
Miles Sabin
 
Ugo Cei Presentation
RubyOnRails_dude
 
JRuby @ Boulder Ruby
Nick Sieger
 
JRuby: What's Different (RORO Melbourne October 2011)
Charles Nutter
 
Clojure for Rubyists
Jean-François Héon
 
Euruko 2012 - JRuby
Charles Nutter
 
All about scala
Yardena Meymann
 
Scala days mizushima
Skills Matter Talks
 
Thnad's Revenge
Erin Dees
 
Intro to J Ruby
Frederic Jean
 
Ruby & Machine Vision - Talk at Sheffield Hallam University Feb 2009
Jan Wedekind
 
A Tour Through the Groovy Ecosystem
Leonard Axelsson
 
Ad

Recently uploaded (20)

PDF
Biography of Daniel Podor.pdf
Daniel Podor
 
PDF
Bitcoin for Millennials podcast with Bram, Power Laws of Bitcoin
Stephen Perrenod
 
PDF
[Newgen] NewgenONE Marvin Brochure 1.pdf
darshakparmar
 
PDF
What Makes Contify’s News API Stand Out: Key Features at a Glance
Contify
 
PDF
LOOPS in C Programming Language - Technology
RishabhDwivedi43
 
PDF
Go Concurrency Real-World Patterns, Pitfalls, and Playground Battles.pdf
Emily Achieng
 
PDF
Exolore The Essential AI Tools in 2025.pdf
Srinivasan M
 
PDF
The Rise of AI and IoT in Mobile App Tech.pdf
IMG Global Infotech
 
PDF
CIFDAQ Market Wrap for the week of 4th July 2025
CIFDAQ
 
PPTX
AI Penetration Testing Essentials: A Cybersecurity Guide for 2025
defencerabbit Team
 
PPTX
Future Tech Innovations 2025 – A TechLists Insight
TechLists
 
PDF
July Patch Tuesday
Ivanti
 
PDF
Newgen 2022-Forrester Newgen TEI_13 05 2022-The-Total-Economic-Impact-Newgen-...
darshakparmar
 
PPTX
AUTOMATION AND ROBOTICS IN PHARMA INDUSTRY.pptx
sameeraaabegumm
 
PDF
How Startups Are Growing Faster with App Developers in Australia.pdf
India App Developer
 
PDF
CIFDAQ Market Insights for July 7th 2025
CIFDAQ
 
PDF
Transforming Utility Networks: Large-scale Data Migrations with FME
Safe Software
 
PPTX
From Sci-Fi to Reality: Exploring AI Evolution
Svetlana Meissner
 
PDF
Advancing WebDriver BiDi support in WebKit
Igalia
 
PDF
“NPU IP Hardware Shaped Through Software and Use-case Analysis,” a Presentati...
Edge AI and Vision Alliance
 
Biography of Daniel Podor.pdf
Daniel Podor
 
Bitcoin for Millennials podcast with Bram, Power Laws of Bitcoin
Stephen Perrenod
 
[Newgen] NewgenONE Marvin Brochure 1.pdf
darshakparmar
 
What Makes Contify’s News API Stand Out: Key Features at a Glance
Contify
 
LOOPS in C Programming Language - Technology
RishabhDwivedi43
 
Go Concurrency Real-World Patterns, Pitfalls, and Playground Battles.pdf
Emily Achieng
 
Exolore The Essential AI Tools in 2025.pdf
Srinivasan M
 
The Rise of AI and IoT in Mobile App Tech.pdf
IMG Global Infotech
 
CIFDAQ Market Wrap for the week of 4th July 2025
CIFDAQ
 
AI Penetration Testing Essentials: A Cybersecurity Guide for 2025
defencerabbit Team
 
Future Tech Innovations 2025 – A TechLists Insight
TechLists
 
July Patch Tuesday
Ivanti
 
Newgen 2022-Forrester Newgen TEI_13 05 2022-The-Total-Economic-Impact-Newgen-...
darshakparmar
 
AUTOMATION AND ROBOTICS IN PHARMA INDUSTRY.pptx
sameeraaabegumm
 
How Startups Are Growing Faster with App Developers in Australia.pdf
India App Developer
 
CIFDAQ Market Insights for July 7th 2025
CIFDAQ
 
Transforming Utility Networks: Large-scale Data Migrations with FME
Safe Software
 
From Sci-Fi to Reality: Exploring AI Evolution
Svetlana Meissner
 
Advancing WebDriver BiDi support in WebKit
Igalia
 
“NPU IP Hardware Shaped Through Software and Use-case Analysis,” a Presentati...
Edge AI and Vision Alliance
 
Ad

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
  • 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) are great • Rapid development • Flexibility • Duck-typing • Metaprogramming
  • 6. Why? ...but there are some pitfalls • Integration • Correctness • Performance • Productivity
  • 7. Integration JRuby gives you access to any Java libraries and 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. Integration Use 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 Hell http://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. Performance JRuby performance is great and getting better... (and it doesn’t matter if the application is waiting for the user 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. Performance Implement performance-critical tasks in a compiled 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 classes case class Person (firstName:String, lastName:String) • Type inference val m = new HashMap[Int, String] • No getters / setters Unless you really need them • More flexible method names (think DSLs) Use (almost) any character Translated to legal names in bytecode (i.e., + is $plus, += is $plus$eq)
  • 19. Functional Programming Mixed 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 typing class Foo { def x = "Foo.x" } class Bar { def x = "Bar.x" } def doIt (arg: { def x:String }) = arg.x scala> doIt(new Foo) res0: String = Foo.x scala> doIt(new Bar) res1: String = Bar.x
  • 22. Implicits • Automatically convert one object to another type • Solve some of the same problems as open classes class 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 HitchHiker's Guide To The Galaxy".acronym res0: java.lang.String = THHGTTG
  • 23. Implicits In 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.size scala> 1 < "foo"     else res0: Boolean = false       __old_lt__ target     end scala> 5 < "foo"   end res1: Boolean = true end http://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.10 object 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’ => true import 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 / closures In 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 methods In Scala: In JRuby: package app.helpers require ‘java’ # => true object 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... see https://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 API val container = new ScriptingContainer val receiver = container.runScriptlet(""" # Radioactive decay def amount_after_years(q0, t) q0 * Math.exp(1.0 / $half_life * Math.log(1.0/2.0) * t) end def 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) // Plutonium val 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 person's 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   end end
  • 43. require & eval import cc.abstra.scuby.JRuby._ // Require a Ruby file from the classpath require("test") // Eval a Ruby statement discarding the return value eval("import Core") // Eval a Ruby statement that returns a Ruby object val array = eval[RubyObj]("[]") // Or with type inference val array2:RubyObj = eval("[]")
  • 44. Creating Objects import cc.abstra.scuby._ // Create a Ruby object val array3 = new RubyObject('Array) // Create a proxy object for the Ruby BackEnd class val backend = RubyClass('Backend) // Create an instance of the Person class val 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 Traits trait 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. Usage To 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 @thedoc http://github.com/abstracc/scuby http://github.com/mcamou http://www.abstra.cc Special thanks to @MadridJUG

Editor's Notes