Scala e JRuby 
União de dois mundos 
Maurício Eduardo Chicupo Szabo 
http://about.me/mauricio.szabo
Why? 
Scala World 
SQL é bom! 
Paralelismo, actors… 
Linguagens devem ser 
estáticas! 
Ruby World 
ORMs são bons! 
Fibers, workers, 
redis... 
Linguagens dinâmicas 
são melhores!
Why? 
Because We CAN!
How? 
● Ruby roda na JVM - JRuby. 
● Sintaxes semelhantes
Sintaxes 
numbers = (1..20).map { |e| e * 2 } 
h = numbers.each_with_index 
.inject({}) do |hash, (number, index)| 
hash.merge(index => number) 
end 
val numbers = 1 to 20 map { e => e * 2 } 
val m = numbers.zipWithIndex 
.foldLeft(Map[Int, Int]()) { case(map, (number, index)) 
=> 
map + (index -> number) 
}
But HOW? 
● org.jruby.Ruby ← Environment 
● Ruby#evalScriptlet 
● IRubyObject 
● IRubyObject#callMethod 
Ruby("puts 'Hello, world!'")
Scala Way 
● AbstractRubyWrapper 
● trait Ruby[A <: AbstractRubyWrapper] 
● __toRubyWrapper 
val r = Ruby("'some string'") 
r: RubyImpl = "some string" 
r.upcase 
res0: RubyImpl = "SOME STRING"
Scala Way 
● init 
● normalize ← params enviados para JRuby 
val bd = Ruby(‘"BigDecimal").init("2.05") 
bd: ruby.RubyImpl = #<BigDecimal: 
58b0dd88,'0.205E1',3(4)> 
(bd + 20).to_f 
res0: ruby.RubyImpl = 22.05
Scala Conversions 
● Estático → Dinâmico → Estático → Dinâmico 
● null → nil (NilClass) → ……..? 
(bd + Ruby("20")).to_f 
res0: ruby.RubyImpl = 22.05
Estático / Dinâmico 
● Conversões de dinâmico para estático 
● rubyResult.as(String) 
● rubyResult.any 
val m = Ruby("{:ten => 10, :twenty => 20}").as(Map) 
m: Map[Any,Any] = Map('twenty -> 20, 'ten -> 10) 
val d = Ruby("10").as(Int) 
d: Int = 10
Scala Conversions 
● Objects → Boolean 
if(Ruby("nil")) 10 else 20 
res0: Int = 20 
if(Ruby("10")) 10 else 20 
res1: Int = 10 
if(Ruby("0")) 10 else 20 
res2: Int = 10
Scala Conversions 
● Funções → Proc → Funções 
val h = Ruby("Hash").init { (_: Any, e: String) => 
e.toUpperCase 
} h: ruby.RubyImpl = {} 
h("Some String") 
res0: ruby.RubyImpl = "SOME STRING" 
h(10) 
java.lang.ClassCastException: java.lang.Long cannot 
be cast to java.lang.String
Nulo... 
● Ruby nil é uma classe, Scala null é… bem… 
● val a: String = null 
● rubyObject.as[String] // => Option[String] 
val s = Ruby("'Hello, world!'").as[String] 
s: Option[String] = Some(Hello, world!) 
val s = Ruby("nil").as[String] 
s: Option[String] = None
Casts de Generics 
● Cast de Listas 
● Cast de Mapas 
val list = Ruby("[1, 2, 3]").as[List, Int] 
list: Option[List[Int]] = Some(Vector(1, 2, 3)) 
val map = Ruby("{:ten => 10}").asMap[Symbol, Int] 
map: Option[Map[Symbol,Int]] = Some(Map('ten -> 10)) 
val vector = Ruby("[1, 2, 3]").as[Vector, Int] 
vector: Option[Vector[Int]] = Some(Vector(1, 2, 3))
Subclassing 
● SimpleSubclass 
● Override 
● (alguns problemas com classe… ainda) 
class Skate extends SimpleSubclass("Vehicles"){ 
def max_speed = 45 
}
ActiveRecord 
● activerecord.Model 
object Person extends active_record.Model { 
scope('foo, this.where('name -> "Foo")) 
scope('age, a => this.where('age -> a)) 
this has_many 'children 
} 
Person.where('name -> "Foo").where('age ->) 
Person.foo.age(17).limit(20)
Sinatra 
● Not there yet... 
class SinatraApp extends SubclassOf(SinatraApp) 
object SinatraApp extends 
Subclass[SinatraApp]("Sinatra::Base") { 
this.reset_! 
this.get("/", { () => 
"Hello, world!" 
}) 
}
But... 
WHY????
Mais informações 
https://github.com/mauricioszabo/Ruby2Scala 
http://jruby.org/apidocs/

Scala e JRuby

  • 1.
    Scala e JRuby União de dois mundos Maurício Eduardo Chicupo Szabo http://about.me/mauricio.szabo
  • 2.
    Why? Scala World SQL é bom! Paralelismo, actors… Linguagens devem ser estáticas! Ruby World ORMs são bons! Fibers, workers, redis... Linguagens dinâmicas são melhores!
  • 3.
  • 4.
    How? ● Rubyroda na JVM - JRuby. ● Sintaxes semelhantes
  • 5.
    Sintaxes numbers =(1..20).map { |e| e * 2 } h = numbers.each_with_index .inject({}) do |hash, (number, index)| hash.merge(index => number) end val numbers = 1 to 20 map { e => e * 2 } val m = numbers.zipWithIndex .foldLeft(Map[Int, Int]()) { case(map, (number, index)) => map + (index -> number) }
  • 6.
    But HOW? ●org.jruby.Ruby ← Environment ● Ruby#evalScriptlet ● IRubyObject ● IRubyObject#callMethod Ruby("puts 'Hello, world!'")
  • 7.
    Scala Way ●AbstractRubyWrapper ● trait Ruby[A <: AbstractRubyWrapper] ● __toRubyWrapper val r = Ruby("'some string'") r: RubyImpl = "some string" r.upcase res0: RubyImpl = "SOME STRING"
  • 8.
    Scala Way ●init ● normalize ← params enviados para JRuby val bd = Ruby(‘"BigDecimal").init("2.05") bd: ruby.RubyImpl = #<BigDecimal: 58b0dd88,'0.205E1',3(4)> (bd + 20).to_f res0: ruby.RubyImpl = 22.05
  • 9.
    Scala Conversions ●Estático → Dinâmico → Estático → Dinâmico ● null → nil (NilClass) → ……..? (bd + Ruby("20")).to_f res0: ruby.RubyImpl = 22.05
  • 10.
    Estático / Dinâmico ● Conversões de dinâmico para estático ● rubyResult.as(String) ● rubyResult.any val m = Ruby("{:ten => 10, :twenty => 20}").as(Map) m: Map[Any,Any] = Map('twenty -> 20, 'ten -> 10) val d = Ruby("10").as(Int) d: Int = 10
  • 11.
    Scala Conversions ●Objects → Boolean if(Ruby("nil")) 10 else 20 res0: Int = 20 if(Ruby("10")) 10 else 20 res1: Int = 10 if(Ruby("0")) 10 else 20 res2: Int = 10
  • 12.
    Scala Conversions ●Funções → Proc → Funções val h = Ruby("Hash").init { (_: Any, e: String) => e.toUpperCase } h: ruby.RubyImpl = {} h("Some String") res0: ruby.RubyImpl = "SOME STRING" h(10) java.lang.ClassCastException: java.lang.Long cannot be cast to java.lang.String
  • 13.
    Nulo... ● Rubynil é uma classe, Scala null é… bem… ● val a: String = null ● rubyObject.as[String] // => Option[String] val s = Ruby("'Hello, world!'").as[String] s: Option[String] = Some(Hello, world!) val s = Ruby("nil").as[String] s: Option[String] = None
  • 14.
    Casts de Generics ● Cast de Listas ● Cast de Mapas val list = Ruby("[1, 2, 3]").as[List, Int] list: Option[List[Int]] = Some(Vector(1, 2, 3)) val map = Ruby("{:ten => 10}").asMap[Symbol, Int] map: Option[Map[Symbol,Int]] = Some(Map('ten -> 10)) val vector = Ruby("[1, 2, 3]").as[Vector, Int] vector: Option[Vector[Int]] = Some(Vector(1, 2, 3))
  • 15.
    Subclassing ● SimpleSubclass ● Override ● (alguns problemas com classe… ainda) class Skate extends SimpleSubclass("Vehicles"){ def max_speed = 45 }
  • 16.
    ActiveRecord ● activerecord.Model object Person extends active_record.Model { scope('foo, this.where('name -> "Foo")) scope('age, a => this.where('age -> a)) this has_many 'children } Person.where('name -> "Foo").where('age ->) Person.foo.age(17).limit(20)
  • 17.
    Sinatra ● Notthere yet... class SinatraApp extends SubclassOf(SinatraApp) object SinatraApp extends Subclass[SinatraApp]("Sinatra::Base") { this.reset_! this.get("/", { () => "Hello, world!" }) }
  • 18.
  • 19.