2. Mirah & Dubious
A bold and beautiful way to write Java,
plus a new framework for App Engine
Charles Nutter
John Woodell
Aug 30, 2010
2
Tuesday, August 31, 2010
3. Mirah
A pragmatic blend of Ruby and Java
Tuesday, August 31, 2010
4. Me
• Charles Oliver Nutter
• Engine Yard, Inc
• headius@headius.com
• @headius
• JRuby core developer
• Mirah creator
Tuesday, August 31, 2010
5. Ruby
• Beautiful language
• Clean syntax
• Easy-to-use closures
• Nice core libraries
• “Slow” language
• Very dynamic == hard to optimize
Tuesday, August 31, 2010
6. Java
• High-performance language
• Mostly static typing
• Full system optimizations
• Primitive math operations
• Ugly language
• (C++)-- of 1995
Tuesday, August 31, 2010
7. Mirah
• “Apparent features” of Ruby
• Syntax
• Closures and iterators
• Dynamic-feeling behaviors
• Performance, typing like Java
• As fast as Java for almost everything
Tuesday, August 31, 2010
8. What If This...
public class Foo {
private int a;
public Foo(int a) {
this.a = a;
}
public void show() {
System.out.println(a);
}
}
Tuesday, August 31, 2010
9. ...Could Be This
class Foo
def initialize(a)
@a = a
end
def show
puts @a
end
end
Tuesday, August 31, 2010
10. Mirah
class Foo
def initialize(a:int)
@a = a
end
def show
puts @a
end
end
Tuesday, August 31, 2010
11. “Java’s Ruby”
• A nicer way to write Java
• Ruby syntax with modifications
• Feels like Ruby
• Compiles to Java/JVM
• No runtime library
Tuesday, August 31, 2010
13. Features From X
• (Coming Soon)
• Extension methods (C#ish, but nicer)
• Implicit type conversions (Scala)
• Pattern matching?
• Case classes?
Tuesday, August 31, 2010
14. Ruby
puts “Hello, world!”
Tuesday, August 31, 2010
15. Mirah
puts “Hello, world!”
Tuesday, August 31, 2010
16. Mirah
// Generated from DashE
public class DashE extends java.lang.Object {
public static void main(java.lang.String[] argv) {
java.io.PrintStream temp$1 = java.lang.System.out;
temp$1.println("Hello, world!");
}
}
Tuesday, August 31, 2010
17. Ruby
def fib(a)
if a < 2
a
else
fib(a - 1) + fib(a - 2)
end
end
Tuesday, August 31, 2010
18. Mirah
def fib(a:int)
if a < 2
a
else
fib(a - 1) + fib(a - 2)
end
end
Tuesday, August 31, 2010
19. Mirah
// Generated from DashE
public class DashE extends java.lang.Object {
public static void main(java.lang.String[] argv) {
}
public static int fib(int a) {
return (a < 2) ? (a) : ((DashE.fib((a - 1)) +
DashE.fib((a - 2))));
}
}
Tuesday, August 31, 2010
20. Ruby
def foo(a = 1, b = 2)
puts a + b
end
Tuesday, August 31, 2010
21. Mirah
def foo(a:int = 1, b:int = 2)
puts a + b
end
Tuesday, August 31, 2010
22. Mirah
public static java.io.PrintStream foo(int a, int b) {
java.io.PrintStream temp$1 =
java.lang.System.out;
temp$1.println((a + b));
return temp$1;
}
public static java.io.PrintStream foo() {
return foo(1);
}
public static java.io.PrintStream foo(int a) {
return foo(a, 2);
}
Tuesday, August 31, 2010
23. Ruby
a = [5,4,3,2,1]
a.each do |x|
puts x
end
Tuesday, August 31, 2010
24. Mirah
a = [5,4,3,2,1]
a.each do |x|
puts x
end
Tuesday, August 31, 2010
25. Mirah
// Generated from DashE
public class DashE extends java.lang.Object {
public static void main(java.lang.String[] argv) {
java.util.List a =
java.util.Collections.unmodifiableList(
java.util.Arrays.asList(1, 2, 3, 4, 5));
java.util.Iterator __xform_tmp_1 = a.iterator();
label1:
while (__xform_tmp_1.hasNext()) {
java.lang.Object x = __xform_tmp_1.next();
label2:
{
java.io.PrintStream temp$3 = java.lang.System.out;
temp$3.println(x);
}
}
}
}
Tuesday, August 31, 2010
26. Ruby
t = Thread.new do
puts “in thread”
end
Tuesday, August 31, 2010
27. Mirah
t = Thread.new do
puts “in thread”
end
Tuesday, August 31, 2010
28. // Generated from DashE
Mirah
public class DashE extends java.lang.Object {
public static void main(java.lang.String[] argv) {
DashE.__xform_tmp_1 $binding = new DashE.__xform_tmp_1();
$binding.x = "in thread";
java.lang.Thread t = new java.lang.Thread(new DashE.__xform_tmp_2($binding));
}
public static class __xform_tmp_1 extends java.lang.Object {
java.lang.String x;
}
public static class __xform_tmp_2 extends java.lang.Object implements
java.lang.Runnable {
private DashE.__xform_tmp_1 binding;
public __xform_tmp_2(DashE.__xform_tmp_1 binding) {
this.binding = binding;
}
public void run() {
DashE.__xform_tmp_1 $binding = this.binding;
java.io.PrintStream temp$1 = java.lang.System.out;
temp$1.println($binding.x);
}
}
}
Tuesday, August 31, 2010
29. // Generated from DashE
Mirah
public class DashE extends java.lang.Object {
public static void main(java.lang.String[] argv) {
DashE.__xform_tmp_1 $binding = new DashE.__xform_tmp_1();
$binding.x = "in thread";
java.lang.Thread t = new java.lang.Thread(new DashE.__xform_tmp_2($binding));
}
public static class __xform_tmp_1 extends java.lang.Object {
java.lang.String x;
}
public static class __xform_tmp_2 extends java.lang.Object implements
java.lang.Runnable {
private DashE.__xform_tmp_1 binding;
public __xform_tmp_2(DashE.__xform_tmp_1 binding) {
this.binding = binding;
}
public void run() {
DashE.__xform_tmp_1 $binding = this.binding;
java.io.PrintStream temp$1 = java.lang.System.out;
temp$1.println($binding.x);
}
}
}
Tuesday, August 31, 2010
30. // Generated from DashE
Mirah
public class DashE extends java.lang.Object {
public static void main(java.lang.String[] argv) {
DashE.__xform_tmp_1 $binding = new DashE.__xform_tmp_1();
$binding.x = "in thread";
java.lang.Thread t = new java.lang.Thread(new DashE.__xform_tmp_2($binding));
}
public static class __xform_tmp_1 extends java.lang.Object {
java.lang.String x;
}
public static class __xform_tmp_2 extends java.lang.Object implements
java.lang.Runnable {
private DashE.__xform_tmp_1 binding;
public __xform_tmp_2(DashE.__xform_tmp_1 binding) {
this.binding = binding;
}
public void run() {
DashE.__xform_tmp_1 $binding = this.binding;
java.io.PrintStream temp$1 = java.lang.System.out;
temp$1.println($binding.x);
}
}
}
Tuesday, August 31, 2010
31. Open Class (proposal)
interface StringFunc
def apply(str:String)
end
extend class String # java.lang.String
def each(func:StringFunc)
# String#split call from Java
lines = split
# like “for (String str: strArray)”
lines.each do |str|
func.apply(str)
end
end
end
Tuesday, August 31, 2010
32. Open Class (Java side)
public interface StringFunc {
public void apply(String str);
}
public class StringExtension {
public void each(String str, StringFunc func) {
for (String s: str.split()) {
func.apply(str);
}
}
}
Tuesday, August 31, 2010
33. Open Class (usage)
str = “hellongoodbyenworld”
str.each {|s| ... }
Tuesday, August 31, 2010
34. Open Class (Java usage)
String str = “hellongoodbyenworld”;
StringExtension.each(str, new StringFunc() {
public void apply(String s) {
...
}
});
Tuesday, August 31, 2010
35. Open Class (Java usage)
String str = “hellongoodbyenworld”;
StringExtension.each(str, new StringFunc() {
public void apply(String s) {
...
YUCK!
}
});
Tuesday, August 31, 2010
36. Type Conversion
str = “hellongoodbyenworld”
# no “map” method on String...
str.map {|s| # ERROR
Tuesday, August 31, 2010
37. Type Conversion
(by hand)
str = “hellongoodbyenworld”
# without type conversion
Arrays.asList(str.split).map { ...
Tuesday, August 31, 2010
38. Type Conversion
(by hand)
str = “hellongoodbyenworld”
# without type conversion
Arrays.asList(str.split).map { ...
Tuesday, August 31, 2010
39. Type Conversion
(proposal)
conversion(String => List) do |str|
Arrays.asList(str.split)
end
conversion(List => String) do |list|
list.join(‘n’)
end
Tuesday, August 31, 2010
40. Type Conversion
(usage)
str = “hellongoodbyenworld”
# with type conversion!
str.map { ... # OK!!
Tuesday, August 31, 2010
41. It’s Not Ruby
• Using Java’s libraries and type system
• No “eval”
• No runtime-mutable classes
• Ruby libraries will not work
Tuesday, August 31, 2010
42. But It Feels Like Ruby!
• Clean, lightweight syntax
• Iteration, closures
• Far less “ceremony” than Java
• Performance equivalent to Java
Tuesday, August 31, 2010
45. Dubious
Dubious Mirah Web
Tuesday, August 31, 2010
46. Me
• John Woodell
• Web developer at Google
• Dubious creator
• App Engine JRuby maintainer
• @JohnWoodell
Tuesday, August 31, 2010
47. Thank you for using
"AppEngine/Java”
"AppEngine/Java"
47
Tuesday, August 31, 2010
48. Spin-up time can make scaling “painful”
• The most critical issue to be resolved is spin-up time,
App Engine scales by adding new application instances.
• Even if initialization could happen without affecting users
some apps will need to scale instantly.
48
Tuesday, August 31, 2010
49. Spin-up?
Yes, this is a problem...
49
Tuesday, August 31, 2010
50. ...but now you can use
Mirah and Dubious
"Mirah/Dubious"
50
Tuesday, August 31, 2010
51. Dubious is Web framework for Mirah
Dubious Mirah Web
*du bi ous[ djbis | dj- ] [ ]
[1] (( )) …
((of, about, as to ...)).
[2]
>
51
Tuesday, August 31, 2010
52. Write Rails-style code,
it runs on Google App Engine
GoogleAppEngine
Rails
52
Tuesday, August 31, 2010
53. Benefits of Mirah on App Engine
• Ruby syntax & apparent features + Java type system
• Use Java or Ruby when Mirah lacks features you require
• The generated Java source can be inspected at any time
• Macros and plugins can be written in Ruby or Mirah
• New instances always spin-up in about a second
53
Tuesday, August 31, 2010
54. Working with Dubious
• Dubious framework uses familiar Rails conventions
• Generate JSONs or work with ERb templates
• MirahModel syntax is similar to DataMapper
• Developers can create apps entirely in Rails,
then refactor URLs that need to scale quickly
• Some important features are currently missing,
but “you” could have fun contributing them
54
Tuesday, August 31, 2010
55. Here’s code from Dubious
(this is not Rails)
Rails
Dubious
55
Tuesday, August 31, 2010