Fantom on the JVM By Fred Simon, JFrog Dror Bereznitsky, AlphaCSP Stephen Colebourne, Joda
A BOF about the Fantom language
Agenda Introduction to Fantom Why Fantom ? The future of Fantom
Speaker’s Qualifications Fred Simon is a  Founder and Chief Architect at JFrog Ltd. Dror Bereznitsky is the Director of Technologies at AlphaCSP Ltd. Stephen Colebourne is the Joda project lead
Why Fantom ? A  practical  programming language Hybrid OO and functional language Static typing with dynamic abilities Elegant APIs Modularity baked into the language Modern approach to concurrency RESTFul design JSON style serialization
Hello World class  HelloWorld {  static  Void main() {  echo( “Hello world !" )  }  }
Pods Pods are used to organize types Like Java packages or C# namespaces Qualified type names - <pod>::<type> sys::DateTime web::Weblet
Pod Declaration – pod.fan @podDepends = [Depend( &quot; sys 1.0 &quot; ), Depend( &quot; someOtherPod 1.0 &quot; )]  @podSrcDirs = [ `fan/` ,  `test/` ]  pod  myPod { // symbols  Str mySymbol :=  &quot; value &quot; }
Pods Unit of deployment and versioning Similar to a Java JAR file or a .NET assembly Pod names must be globally unique Standard ZIP file Bundles Fantom code, meta-data, and file resources
Type System Two kind of types Classes Mixins Everything is an object Value types –  Bool, Int, Float
Classes Single class inheritance May inherit multiple Mixins The root of all classes is the  sys::Obj class  Foo : Bar { }
Mixins Similar Scala traits Java/C# interfaces + method implementation No state mixin  Foo {  Int bar() {  return   42  }  }
Enums Enums are normal classes Enums have a fixed range of instances enum   Color { red, blue, green }
Null Safety Types may be nullable or non-nullable By default types are non-nullable Use  ?  to specify a nullable type Int? x :=  null Int x  :=  null   // Error
Generics No user defined generics Limited to List, Map, and Func Str[]  // list of Str  [ Str:User]  // map of Users keyed by Str  |Int a->Str|   // takes Int, returns Str
Why Fantom? Built in modularity  Everything is an Object Value-types for performance Statically typed mixins Null safety No user defined generics
Slots Fields and Methods on Types Uniquely named No overloading Protection Scope public (default) private protected internal - only accessible inside pod
Slots - Methods Not virtual by default Must explicitly specify  virtual  and  override class  Animal {  virtual  Void talk() { echo( &quot;generic&quot; ) }  } class  Cat : Animal {  override  Void talk() { echo( &quot;meow&quot; ) }  }
Slots – Methods Continued Default parameters Void foo(Int a, Int b :=  5 ) Once methods Computed first time, then cached  once  Str fullName() {  return   &quot;$firstName $lastName&quot;  }
Slots - Fields Use the  :=  operator to provide an initial value Str message :=  &quot;hello world&quot; Implicitly use a getter/setter Use  *  to access field storage directly *message :=  &quot;hello world&quot;
Slots – Field Accessors Accessors Int x :=  10  {  get {  return  *x }  set { *x = val } }  Can narrow field setter scope Int x {  private  set }  readonly  Int x  // the same
Slots – Field Immutability const  - indicate that the field is immutable Cannot be assigned outside of the construction process Value of all const fields must be immutable Any object instance of a const class The result of  Obj.toImmutable  (1.0.47)
Constructors Multiple constructors allowed Use the  new  keyword Convention is  makeXXX() Implicit  make()  constructor if not defined new  make(Str name :=  &quot;anonymous&quot; ){ this .name = name }  new  makeFoo(Int x) {  this .x = x }
Calling Constructors Called just like static factory methods foo := Foo.make  foo := Foo.make( &quot;bar&quot; )  foo := Foo.makeFoo( 5 )
Construction Calls Special construction syntax:  Type(args) Bind to  Type.fromStr  if exists and takes a single Str argument Otherwise bind to  Type.make foo := Foo.make  // non-preferred  foo := Foo()  // preferred
Why Fantom ? No overloading Simple reflection Method resolution with default parameters Implicit getter and setters Immutability Human readable serialization
Literals Int 45  -89_039  0xCAFE_BABE Float 3.0f  3f  0.2e+6f Decimal 4d  4.0  0.2e+6D Str “ foo”  “x is $x, in hex $x.toHex” Duration 4ns  100ms  -0.5hr Uri `index.html`  ` http://fandev.org ` Types, Slots Str#  sys::Str#  Int#plus  #echo
Literals Continued Range 0..5  x...y List [1, 2, 3]  Int[10, 20, 30]  Int[,] Map [1:”one”, 2:”two”]  Int:Str[1:”one”]  Int:Str[:]
Str Literals Multiline x :=  &quot;line 1  line 2  line3&quot; Triple quotes echo( &quot;&quot;&quot;Do you know &quot;What lies beneath the shadow of    the statue&quot;?&quot;&quot;&quot; ) Interpolation &quot;x is  $x , in hex  $x.toHex , and x+8 is  ${x+8} &quot;
Functions First class objects - sys::Func Methods Closures Bind Signature –  |A a, B b ... H h -> R| |Int a| |Str a, Str b -> Int|
Functions Calling func.callList([ 7 ,  8 ]) func.call( 7 ,  8 ) func( 7 ,  8 )
Methods Wrapper around a Func Method.func func := Str#replace.func  func( &quot;hi!&quot; ,  &quot;hi&quot; ,  &quot;hello&quot; )  &quot;hi!&quot; .replace( &quot;hi&quot; ,  &quot;hello&quot; )
Func.bind Binds one or more fixed arguments to create a new function f := |Int a, Int b-> Str| {  return   &quot;$a $b&quot;  }  g := f.bind([ 0 ])  f( 0 ,  1 )  // 0 1  g( 1 )  // 0 1
Closures Functions that can reference enclosing scope counter :=  0  // counter = 1 f := |->Int| {  return  ++counter } f() f()  // counter = 2
Closures Last arg to a method, can be defined “outside” // not preferred  foo( 5 , |->Int| { x })  // preferred  foo( 5 ) |->Int| { x }
Closures Used extensively in the API [ 1 ,  2 ,  3 ].each |Int i| {echo(i)} [ 3 ,  8 ,  4 ].sort |Int a, Int b->Int| { a <=> b }
It Blocks Syntax sugar to bind  this  to another variable named  it foo := Foo() { age =  15  }  foo := Foo();  foo.age =  15   Can set const fields
Dynamic Invoke Dynamic invoke operator:  -> No compile time type checking Actually invokes  Obj.trap() By default trap() uses reflection to lookup and call method a->x  a.trap( “x” , [,]) a->x = b  a.trap( “x” , [b]) a->x(b, c)  a.trap( “x” , [b, c])
Why Fantom ? Functions are 1 st  class citizens Statically typed, duck typing possible Declarative style with blocks Built-in immutable calls
Facets Annotate types/slots with meta-data Similar to Java annotations or C# attributes @symbolName=value  @serializable  @icon= `/icons/account.png` @version=Version( &quot;1.2&quot; )
Facets Access at runtime using  Pod.facet Type.facet Slot.facet obj.type.facet(@simple) ==  true
Symbols pod fanDemo { Str defaultName := &quot;anonymous“ } class  Person {  const  Str firstName  const  Str lastName  new  make(Str firstName := @defaultName, Str  lastName :=  &quot;&quot; ) { ... }  }
DSL Embed other languages into your Fantom source Built in DSLs Str  <|no \ or $ escapes need, and multi-line works too|> Regex  <|foo|foo/(\d*)|> DSL Plugins
Concurrency No mutable shared state Threads may never share mutable state under any circumstances Immutability Message passing REST UriSpaces - a  whiteboard  mechanism for multiple threads to share state
Immutability Immutable  object = once constructed it never changes state Any object instance of a const class The result of Obj.toImmutable()
Immutability - Const Classes Use const keyword const   class  Foo {}  Can only contain const fields or fields with no storage Use const keyword  -  const  Int id :=  5 Can only be set in the constructor Must inherit from a const class or  sys::Obj
Message Passing - Actors pool := ActorPool()  a := Actor(pool) |Obj msg| { echo( &quot;$Time.now: $msg&quot; )  }  a.send( &quot;start&quot; ) a.sendLater( 1sec ,  &quot;1sec&quot; )
Serialization Syntax is a subset of the Fantom grammar myPod::Person {  name =  &quot;Homer Simpson&quot;   age =  39   children =  [ &quot;Bart&quot; ,  &quot;Lisa&quot; ,  &quot;Maggie&quot; ]  }
Serialization Tree based No attempt to keep track of object references Tree nodes Literal Simple  - serialized via string representation Complex  - aggregate of literal, simple, and/or complex
Serialization - Simple Types that are serializable to/from a string toStr()  must return suitable string representation Must have static  fromStr()  method
Serialization - Simple @simple  class  Point {  static  Point fromStr(Str s) {  t := s.split( &quot;,&quot; );  return  make(t[ 0 ].toInt, t[ 1 ].toInt)  }  override  Str toStr() {  return   &quot;$x,$y&quot;  }  Int x :=  0  Int y :=  0  }
Serialization - Complex @serializable facet By default will serialize all non-static fields Use @transient to skip fields @serializable   class   Rectangle   {   Int x; Int y   Int w; Int h   @transient   Int area }
Serialization - @collections Nicer syntax for nesting children Person {  name =  &quot;Homer Simpson&quot;  Person { name =  &quot;Bart&quot;  }  Person { name =  &quot;Lisa&quot;  }  Person { name =  &quot;Maggie&quot;  }  }
Java FFI using  [java] java.util::Date  as  JavaDate  class  Test {  Void main() {  date := JavaDate()  // constructors year := date.getYear +  1900   // methods  // dynamic invokes  millis := date->getTime echo( &quot;$date, $year, $millis&quot; )  }  }
UriSpaces Standard ‘RESTful’ URI naming system Resources are represented as Fantom objects Resources are identified with Uris Resources are managed using a small set of &quot;verbs&quot; Resources are transferred between threads safely
UriSpaces UriSpace.root.create( `/hello` ,  &quot;hi&quot; ) UriSpace.root[ `/hello` ]  // &quot;hi“ UriSpace.root.put( `/hello` ,  &quot;hola&quot; ) UriSpace.root[ `/hello` ]  // &quot;hola“ UriSpace.root.delete( `/hello` ) UriSpace.root[ `/hello` ]  // raises UnresolvedErr UriSpace.root.get( `/hello` ,  false )  // null
Type Database Maintains database of all installed pods and types Provide a mechanism to index facet name/value pairs to types Automatically rebuilt as needed
Type Database – Facet Indexing @podIndexFacets = [@parserForExt]  pod acme {  Str[] parserForExt := Str[,]  }  @parserForExt=[ &quot;xml&quot; ]  class  XmlParser {}  parsers := Type.findByFacet(@parserForExt,  &quot;xml&quot; )
Build using  build class  Build : BuildPod {  override  Void setup() {  podName =  “myPodName&quot;  version = Version( &quot;1.0&quot; )  }  }
Build – Custom Code using  build class  Build : BuildScript {  @target= &quot;Compile everything&quot;  Void compile() { log.info( &quot;Compile away!&quot; ) }  @target= &quot;Clean it all up&quot;  Void clean() { log.info( &quot;Clean away!&quot; ) }  }
Fandoc Plaint-text documentation language Inline code:   'FandocParser' Emphasis:   *foo bar* Hyperlink:   [Fantom Home Page]` http://fandev.org/` Based on Markdown
Deployment Fantom shipped as fcode in pods At runtime, fcode is emitted to Java bytecode or MSIL Sys API is implemented natively in Java/C#
Why Fantom ? Concurrency – state isolation Type database No more scanning for annotations Easy integration with Java Out of the box build system Provided test framework No more modifiers trick with dynamic calls
DEMO What’sthis demo about
Thanks for your attention! http://www.fantom.org http://wiki.jfrog.org/confluence/display/FANP/Home

Fantom on the JVM Devoxx09 BOF

  • 1.
    Fantom on theJVM By Fred Simon, JFrog Dror Bereznitsky, AlphaCSP Stephen Colebourne, Joda
  • 2.
    A BOF aboutthe Fantom language
  • 3.
    Agenda Introduction toFantom Why Fantom ? The future of Fantom
  • 4.
    Speaker’s Qualifications FredSimon is a Founder and Chief Architect at JFrog Ltd. Dror Bereznitsky is the Director of Technologies at AlphaCSP Ltd. Stephen Colebourne is the Joda project lead
  • 5.
    Why Fantom ?A practical programming language Hybrid OO and functional language Static typing with dynamic abilities Elegant APIs Modularity baked into the language Modern approach to concurrency RESTFul design JSON style serialization
  • 6.
    Hello World class HelloWorld { static Void main() { echo( “Hello world !&quot; ) } }
  • 7.
    Pods Pods areused to organize types Like Java packages or C# namespaces Qualified type names - <pod>::<type> sys::DateTime web::Weblet
  • 8.
    Pod Declaration –pod.fan @podDepends = [Depend( &quot; sys 1.0 &quot; ), Depend( &quot; someOtherPod 1.0 &quot; )] @podSrcDirs = [ `fan/` , `test/` ] pod myPod { // symbols Str mySymbol := &quot; value &quot; }
  • 9.
    Pods Unit ofdeployment and versioning Similar to a Java JAR file or a .NET assembly Pod names must be globally unique Standard ZIP file Bundles Fantom code, meta-data, and file resources
  • 10.
    Type System Twokind of types Classes Mixins Everything is an object Value types – Bool, Int, Float
  • 11.
    Classes Single classinheritance May inherit multiple Mixins The root of all classes is the sys::Obj class Foo : Bar { }
  • 12.
    Mixins Similar Scalatraits Java/C# interfaces + method implementation No state mixin Foo { Int bar() { return 42 } }
  • 13.
    Enums Enums arenormal classes Enums have a fixed range of instances enum Color { red, blue, green }
  • 14.
    Null Safety Typesmay be nullable or non-nullable By default types are non-nullable Use ? to specify a nullable type Int? x := null Int x := null // Error
  • 15.
    Generics No userdefined generics Limited to List, Map, and Func Str[] // list of Str [ Str:User] // map of Users keyed by Str |Int a->Str| // takes Int, returns Str
  • 16.
    Why Fantom? Builtin modularity Everything is an Object Value-types for performance Statically typed mixins Null safety No user defined generics
  • 17.
    Slots Fields andMethods on Types Uniquely named No overloading Protection Scope public (default) private protected internal - only accessible inside pod
  • 18.
    Slots - MethodsNot virtual by default Must explicitly specify virtual and override class Animal { virtual Void talk() { echo( &quot;generic&quot; ) } } class Cat : Animal { override Void talk() { echo( &quot;meow&quot; ) } }
  • 19.
    Slots – MethodsContinued Default parameters Void foo(Int a, Int b := 5 ) Once methods Computed first time, then cached once Str fullName() { return &quot;$firstName $lastName&quot; }
  • 20.
    Slots - FieldsUse the := operator to provide an initial value Str message := &quot;hello world&quot; Implicitly use a getter/setter Use * to access field storage directly *message := &quot;hello world&quot;
  • 21.
    Slots – FieldAccessors Accessors Int x := 10 { get { return *x } set { *x = val } } Can narrow field setter scope Int x { private set } readonly Int x // the same
  • 22.
    Slots – FieldImmutability const - indicate that the field is immutable Cannot be assigned outside of the construction process Value of all const fields must be immutable Any object instance of a const class The result of Obj.toImmutable (1.0.47)
  • 23.
    Constructors Multiple constructorsallowed Use the new keyword Convention is makeXXX() Implicit make() constructor if not defined new make(Str name := &quot;anonymous&quot; ){ this .name = name } new makeFoo(Int x) { this .x = x }
  • 24.
    Calling Constructors Calledjust like static factory methods foo := Foo.make foo := Foo.make( &quot;bar&quot; ) foo := Foo.makeFoo( 5 )
  • 25.
    Construction Calls Specialconstruction syntax: Type(args) Bind to Type.fromStr if exists and takes a single Str argument Otherwise bind to Type.make foo := Foo.make // non-preferred foo := Foo() // preferred
  • 26.
    Why Fantom ?No overloading Simple reflection Method resolution with default parameters Implicit getter and setters Immutability Human readable serialization
  • 27.
    Literals Int 45 -89_039 0xCAFE_BABE Float 3.0f 3f 0.2e+6f Decimal 4d 4.0 0.2e+6D Str “ foo” “x is $x, in hex $x.toHex” Duration 4ns 100ms -0.5hr Uri `index.html` ` http://fandev.org ` Types, Slots Str# sys::Str# Int#plus #echo
  • 28.
    Literals Continued Range0..5 x...y List [1, 2, 3] Int[10, 20, 30] Int[,] Map [1:”one”, 2:”two”] Int:Str[1:”one”] Int:Str[:]
  • 29.
    Str Literals Multilinex := &quot;line 1 line 2 line3&quot; Triple quotes echo( &quot;&quot;&quot;Do you know &quot;What lies beneath the shadow of the statue&quot;?&quot;&quot;&quot; ) Interpolation &quot;x is $x , in hex $x.toHex , and x+8 is ${x+8} &quot;
  • 30.
    Functions First classobjects - sys::Func Methods Closures Bind Signature – |A a, B b ... H h -> R| |Int a| |Str a, Str b -> Int|
  • 31.
    Functions Calling func.callList([7 , 8 ]) func.call( 7 , 8 ) func( 7 , 8 )
  • 32.
    Methods Wrapper arounda Func Method.func func := Str#replace.func func( &quot;hi!&quot; , &quot;hi&quot; , &quot;hello&quot; ) &quot;hi!&quot; .replace( &quot;hi&quot; , &quot;hello&quot; )
  • 33.
    Func.bind Binds oneor more fixed arguments to create a new function f := |Int a, Int b-> Str| { return &quot;$a $b&quot; } g := f.bind([ 0 ]) f( 0 , 1 ) // 0 1 g( 1 ) // 0 1
  • 34.
    Closures Functions thatcan reference enclosing scope counter := 0 // counter = 1 f := |->Int| { return ++counter } f() f() // counter = 2
  • 35.
    Closures Last argto a method, can be defined “outside” // not preferred foo( 5 , |->Int| { x }) // preferred foo( 5 ) |->Int| { x }
  • 36.
    Closures Used extensivelyin the API [ 1 , 2 , 3 ].each |Int i| {echo(i)} [ 3 , 8 , 4 ].sort |Int a, Int b->Int| { a <=> b }
  • 37.
    It Blocks Syntaxsugar to bind this to another variable named it foo := Foo() { age = 15 } foo := Foo(); foo.age = 15 Can set const fields
  • 38.
    Dynamic Invoke Dynamicinvoke operator: -> No compile time type checking Actually invokes Obj.trap() By default trap() uses reflection to lookup and call method a->x a.trap( “x” , [,]) a->x = b a.trap( “x” , [b]) a->x(b, c) a.trap( “x” , [b, c])
  • 39.
    Why Fantom ?Functions are 1 st class citizens Statically typed, duck typing possible Declarative style with blocks Built-in immutable calls
  • 40.
    Facets Annotate types/slotswith meta-data Similar to Java annotations or C# attributes @symbolName=value @serializable @icon= `/icons/account.png` @version=Version( &quot;1.2&quot; )
  • 41.
    Facets Access atruntime using Pod.facet Type.facet Slot.facet obj.type.facet(@simple) == true
  • 42.
    Symbols pod fanDemo{ Str defaultName := &quot;anonymous“ } class Person { const Str firstName const Str lastName new make(Str firstName := @defaultName, Str lastName := &quot;&quot; ) { ... } }
  • 43.
    DSL Embed otherlanguages into your Fantom source Built in DSLs Str <|no \ or $ escapes need, and multi-line works too|> Regex <|foo|foo/(\d*)|> DSL Plugins
  • 44.
    Concurrency No mutableshared state Threads may never share mutable state under any circumstances Immutability Message passing REST UriSpaces - a whiteboard mechanism for multiple threads to share state
  • 45.
    Immutability Immutable object = once constructed it never changes state Any object instance of a const class The result of Obj.toImmutable()
  • 46.
    Immutability - ConstClasses Use const keyword const class Foo {} Can only contain const fields or fields with no storage Use const keyword - const Int id := 5 Can only be set in the constructor Must inherit from a const class or sys::Obj
  • 47.
    Message Passing -Actors pool := ActorPool() a := Actor(pool) |Obj msg| { echo( &quot;$Time.now: $msg&quot; ) } a.send( &quot;start&quot; ) a.sendLater( 1sec , &quot;1sec&quot; )
  • 48.
    Serialization Syntax isa subset of the Fantom grammar myPod::Person { name = &quot;Homer Simpson&quot; age = 39 children = [ &quot;Bart&quot; , &quot;Lisa&quot; , &quot;Maggie&quot; ] }
  • 49.
    Serialization Tree basedNo attempt to keep track of object references Tree nodes Literal Simple - serialized via string representation Complex - aggregate of literal, simple, and/or complex
  • 50.
    Serialization - SimpleTypes that are serializable to/from a string toStr() must return suitable string representation Must have static fromStr() method
  • 51.
    Serialization - Simple@simple class Point { static Point fromStr(Str s) { t := s.split( &quot;,&quot; ); return make(t[ 0 ].toInt, t[ 1 ].toInt) } override Str toStr() { return &quot;$x,$y&quot; } Int x := 0 Int y := 0 }
  • 52.
    Serialization - Complex@serializable facet By default will serialize all non-static fields Use @transient to skip fields @serializable class Rectangle { Int x; Int y Int w; Int h @transient Int area }
  • 53.
    Serialization - @collectionsNicer syntax for nesting children Person { name = &quot;Homer Simpson&quot; Person { name = &quot;Bart&quot; } Person { name = &quot;Lisa&quot; } Person { name = &quot;Maggie&quot; } }
  • 54.
    Java FFI using [java] java.util::Date as JavaDate class Test { Void main() { date := JavaDate() // constructors year := date.getYear + 1900 // methods // dynamic invokes millis := date->getTime echo( &quot;$date, $year, $millis&quot; ) } }
  • 55.
    UriSpaces Standard ‘RESTful’URI naming system Resources are represented as Fantom objects Resources are identified with Uris Resources are managed using a small set of &quot;verbs&quot; Resources are transferred between threads safely
  • 56.
    UriSpaces UriSpace.root.create( `/hello`, &quot;hi&quot; ) UriSpace.root[ `/hello` ] // &quot;hi“ UriSpace.root.put( `/hello` , &quot;hola&quot; ) UriSpace.root[ `/hello` ] // &quot;hola“ UriSpace.root.delete( `/hello` ) UriSpace.root[ `/hello` ] // raises UnresolvedErr UriSpace.root.get( `/hello` , false ) // null
  • 57.
    Type Database Maintainsdatabase of all installed pods and types Provide a mechanism to index facet name/value pairs to types Automatically rebuilt as needed
  • 58.
    Type Database –Facet Indexing @podIndexFacets = [@parserForExt] pod acme { Str[] parserForExt := Str[,] } @parserForExt=[ &quot;xml&quot; ] class XmlParser {} parsers := Type.findByFacet(@parserForExt, &quot;xml&quot; )
  • 59.
    Build using build class Build : BuildPod { override Void setup() { podName = “myPodName&quot; version = Version( &quot;1.0&quot; ) } }
  • 60.
    Build – CustomCode using build class Build : BuildScript { @target= &quot;Compile everything&quot; Void compile() { log.info( &quot;Compile away!&quot; ) } @target= &quot;Clean it all up&quot; Void clean() { log.info( &quot;Clean away!&quot; ) } }
  • 61.
    Fandoc Plaint-text documentationlanguage Inline code: 'FandocParser' Emphasis: *foo bar* Hyperlink: [Fantom Home Page]` http://fandev.org/` Based on Markdown
  • 62.
    Deployment Fantom shippedas fcode in pods At runtime, fcode is emitted to Java bytecode or MSIL Sys API is implemented natively in Java/C#
  • 63.
    Why Fantom ?Concurrency – state isolation Type database No more scanning for annotations Easy integration with Java Out of the box build system Provided test framework No more modifiers trick with dynamic calls
  • 64.
  • 65.
    Thanks for yourattention! http://www.fantom.org http://wiki.jfrog.org/confluence/display/FANP/Home