WTF is Fantom?
 CodeFest, Новосибирск, 2010
Java sucks
Java sucks

	   public static void javaSucks1() {
	   	 Map<String, List<String>> wtf =
	   	 	 new HashMap<String, List<String>>();
	   }
Java sucks

	   public static void javaSucks2() {
	   	 new Thread(new Runnable() {
	   	 	 @Override
	   	 	 public void run() {
	   	 	 	 System.out.println("WTF?");
	   	 	 }
	   	 }).run();
	   }
Java sucks

	   private int value;
	   public int getCount() { return value; }
	   public void setCount(int value) {
	   	 this.value = value;
	   }
	   public void javaSucks3() {
	   	 setCount(getCount() + 1);
	   }
Java sucks
public void javaSucks4() {
  	  try {
	 	 	 out.write(new byte[] { 1,2,3});
	 	 } catch (IOException e) {
	 	 	 System.out.println("Oops!");
	 	 } finally {
	 	 	 try {
	 	 	 	 out.close();
	 	 	 } catch (IOException e) {
	 	 	 }
	 	 }	
}
Java ≠ JVM
JVM rocks
JVM Rocks

• Most popular and powerful VM in the world
• > 15 years on VM market
• True cross-platform
JVM Rocks
• Plenty of frameworks
• Application servers
• Tooling support
     • Debugging
     • Profiling
     • Code coverage
JVM Languages

• Java
• Scala
• Clojure
• Groovy
• Fantom
Fantom
• Object-oriented
• Statically typed
• Open source
• Was born in late 2005
• Authors – Brian Frank and Andy Frank
• Created for start-up SkyFoundry.com
Fantom is more than
just yet another JVM
       language
Fantom
               .fan


      .fcode          .js



JVM   .NET     LLVM   Parrot
Fantom

• Significant developer productivity
  (comparing to Java)
• Safer code
• Multi-paradigm support
• Interaction with platform
Productivity
• Type inference
• Literals
• First-class functions
• Closures
• Mixins
• Small tricks
Type inference

                        mc := MyClass()
Infer local variables   s := "this is a string"
                        duration := 1day




   Infer generic        intList := [1,2,4]

    parameters          strToIntMap := ["a":4, "b":5]
Literals
                   [1, 3, 5, 7]
     Lists         ["a", ["b", "cd"]]


     Maps          ["str": "Str", 1: 3, "list": [null, 5]]


                   Str#
Types(reflection)   sys::Str#
                   Str#capitalize

                   `ftp://user001:pass@ftp.com/mydir/myfile.txt`
     URIs          `http://fantom.org`
                   `/Users/ivaninozemtsev/work/fantom`



   Duration        [1ns, 5ms, 12sec, 3hr, 1day]


    Ranges         [1..5, 2..8, 0..<5]
Functions and closures
                                   //simple signatures
Functions are first class objects   |->| voidSig := |->| {}
                                   |->Int| returnsInt := |->Int| { 42 }



  Methods are just function        |Int a, Int b ->Int| plus := Int#plus.func

        wrappers                   |->| mainFunc := #main.func




                                   op := |Method m, Int a, Int b| { m.callOn(a, [b]) }
Functions can bind arguments       mul := opFunc.bind([Int#mult]) //|Int, Int->Int|
                                   plus2 := opFunc.bind([Int#plus, 2]) //|Int -> Int|




 Closures are exprs returning      Str prefix := ""

            funcs                  print := |Obj o->Str| { prefix + o.toStr }
Mixins
                          mixin FirstLast
                          {
                            abstract Str firstName()
•   Replacement of          abstract Str lastName()
    interfaces            }

                          mixin Age{ abstract Int age }

•   Abstract fields and    mixin WithImpl : FirstLast
    methods               {
                            Str fullName() { "$firstName $lastName" }

•   Methods can have
                          }


    implementation        mixin MultiInh : WithImpl, Age
                          {
                            override Str toStr() { "$fullName ($age
                          years old)" }
                          }
Small convenience
           tricks
     Implicit upcasts         Derived derived := base



       Safe invoke            person?.phones?.first //null if p == null



     Elvis operator           //alias for this == null ? that : this
                              this ?: that


No () for methods w/o args    cap := "a".capitalize



No ‘return’ for single expr   Int negate(Int arg) { arg.negate }



     ‘isnot’ keyword          alwaysFalse := "a" isnot Str
Safety

• Nullable types
• Const fields and classes
• No shared mutable state
Nullable types
                                class Nullable
                                {
                                  Void main()
                                  {

•   Every type isn’t nullable       Int? nullable := null
                                    Int nonNullable := 0
    by default                      nonNullable = nullable //runtime err
                                    nonNullable = null //compile err

•   Obvious errors are              do3(null) //compile err
                                    do3(nullable) //runtime err
    caught by compiler            }



•
                                    Int do1(Int? arg) { null } //compile err
    Automatic coercion
                                    Int do2(Int? arg) { arg } //runtime err

                                    Int? do3(Int arg) { arg }
                                }
Const types
                                              class NonConst
                                              {
                                                const Int constField

•   Const classes contain only const fields
                                                Int nonConstField

                                                  Void mutate()
                                                  {
•   Const fields must be set in constructor          constField = 4 //compile err
                                                    nonConstField = 4 //ok
                                                  }

•   Const fields can have only const type or   }

    [List, Map, Func].toImmutable             class Const
                                              {
                                                new make(Int i, Str[] list)
•   Static fields must be const                  {
                                                  //implicit call of list.toImmutable
                                                  this.list = list

•   List and Maps can be const or mutable       }
                                                const Str[] list
                                              }
Actor framework
• Actors are the only way for multithreading
• Actor are const classes extending Actor
  class
• Actors interchange with const or
  serializable messages
• Actors can have private mutable data
Actor framework
using concurrent

const class Logger : Actor
{
  new make(ActorPool pool := ActorPool()) :
    super(pool) {}

    override Obj? receive(Obj? msg) { echo(msg); return null }
}
class Actors
{
  Void main()
  {
    logger := Logger()
    logger.send("Hello")
    future := logger.sendLater(1sec, "Later")
    logger.send("Now")
    future2 := logger.sendWhenDone(future, "After later");
    future3 := logger.sendWhenDone(future2, "After after")
    future3.cancel

        Actor.sleep(2sec)
    }
}
Multiparadigm
Declarative style

Window
{
  title = "FWT Demo"
  size = Size(800, 600)
  Label { text = "Hello, codefest!" },
}.open
Declarative style
a := AddressBook
{
  Person
  {
     first = "Ivan"
     last = "Inozemtsev"
     phones = [
       Phone { num = "+79139494750"; type = PhoneType.cell},
       Phone
       {
         num = "+73833631033"
         type = PhoneType.work
       }
     ]
  },
}
Dynamic style
Void iAmDynamic(Obj duck)
{
  duck->quack
  duck->swim("away")
}
Dynamic style
class Dict
                                                  Void main()
{
                                                  {
  Str:Obj? map
                                                    dict := Dict(["foo":5, "bar":"str"])
  new make(Str:Obj? map) { this.map = map }
                                                    Str a := dict->foo->toStr //"5"
                                                    Str b := dict->bar //"str"
    override Obj? trap(Str name, Obj?[]? args)      Obj o := dict->o //null
    {                                               dict->o = 42
      if(args.isEmpty) return map[name]//getter   }
      return (map[name] = args.first) //setter
    }
}
Functional style
  persons.findAll |Person p->Bool|
  {
    p.first == "Ivan"
  }.map |Person p -> Phone[]|
  {
    p.phones
  }.flatten
  .exclude |Phone ph->Bool|
  {
    ph.type == PhoneType.work
  }.map |Phone ph->Str|
  {
    ph.num
  }.each { echo(it) }
Interaction with platform
using   [java]org.eclipse.dltk.internal.ui.text
using   [java]org.eclipse.core.runtime
using   [java]org.eclipse.dltk.core
using   [java]org.eclipse.ui.progress

class ReconcileListener :
  IScriptReconcilingListener
{
   private AstView view

    public new make(AstView view) { this.view = view }
    override Void aboutToBeReconciled() {}
    override Void reconciled(ISourceModule? module,
        Bool forced,
        IProgressMonitor? progressMonitor) {
      if (module != null) UpdateJob(view, module).schedule
    }
}
OK, what else?

• Build scripts on Fantom
• API Doc generation
• Built-in unit-testing framework
• Built-in web server
• Interactive shell (REPL)
Who’s using it?
We are!
X5
•   Collects, analyzes
    and groups error
    reports

•   Highly concurrent
    application

•   Pure Fantom
    solution

•   Uses CouchDB
F4
•   World-class IDE for
    Fantom written on
    Fantom

•   Completion

•   Navigation

•   Highlighting

•   Search

•   Debugging
Terminals

•   Full-featured xterm
    compatible terminal

•   Intense integration with
    Java

•   Embedded into Eclipse
FPF - Fantom
      presentation framework
•   Scene graph-based UI
    Framework

•   Same look&feel on
    Desktop and browsers

•   HTML5 Canvas on Web

•   OpenGL Canvas on
    Desktop
And not only
Kloudo.com

•   Pure Fantom on server
    side

•   Runs on built-in Fantom
    web server

•   Developed in 4 man-
    months
Ready to be involved?
• http://fantom.org
• http://xored.com/f4
• mailto:fan-dev@xored.com
    Meet @ chill-out

CodeFest 2010. Иноземцев И. — Fantom. Cross-VM Language

  • 1.
    WTF is Fantom? CodeFest, Новосибирск, 2010
  • 2.
  • 3.
    Java sucks public static void javaSucks1() { Map<String, List<String>> wtf = new HashMap<String, List<String>>(); }
  • 4.
    Java sucks public static void javaSucks2() { new Thread(new Runnable() { @Override public void run() { System.out.println("WTF?"); } }).run(); }
  • 5.
    Java sucks private int value; public int getCount() { return value; } public void setCount(int value) { this.value = value; } public void javaSucks3() { setCount(getCount() + 1); }
  • 6.
    Java sucks public voidjavaSucks4() { try { out.write(new byte[] { 1,2,3}); } catch (IOException e) { System.out.println("Oops!"); } finally { try { out.close(); } catch (IOException e) { } } }
  • 7.
  • 8.
  • 9.
    JVM Rocks • Mostpopular and powerful VM in the world • > 15 years on VM market • True cross-platform
  • 10.
    JVM Rocks • Plentyof frameworks • Application servers • Tooling support • Debugging • Profiling • Code coverage
  • 11.
    JVM Languages • Java •Scala • Clojure • Groovy • Fantom
  • 12.
    Fantom • Object-oriented • Staticallytyped • Open source • Was born in late 2005 • Authors – Brian Frank and Andy Frank • Created for start-up SkyFoundry.com
  • 13.
    Fantom is morethan just yet another JVM language
  • 14.
    Fantom .fan .fcode .js JVM .NET LLVM Parrot
  • 15.
    Fantom • Significant developerproductivity (comparing to Java) • Safer code • Multi-paradigm support • Interaction with platform
  • 16.
    Productivity • Type inference •Literals • First-class functions • Closures • Mixins • Small tricks
  • 17.
    Type inference mc := MyClass() Infer local variables s := "this is a string" duration := 1day Infer generic intList := [1,2,4] parameters strToIntMap := ["a":4, "b":5]
  • 18.
    Literals [1, 3, 5, 7] Lists ["a", ["b", "cd"]] Maps ["str": "Str", 1: 3, "list": [null, 5]] Str# Types(reflection) sys::Str# Str#capitalize `ftp://user001:pass@ftp.com/mydir/myfile.txt` URIs `http://fantom.org` `/Users/ivaninozemtsev/work/fantom` Duration [1ns, 5ms, 12sec, 3hr, 1day] Ranges [1..5, 2..8, 0..<5]
  • 19.
    Functions and closures //simple signatures Functions are first class objects |->| voidSig := |->| {} |->Int| returnsInt := |->Int| { 42 } Methods are just function |Int a, Int b ->Int| plus := Int#plus.func wrappers |->| mainFunc := #main.func op := |Method m, Int a, Int b| { m.callOn(a, [b]) } Functions can bind arguments mul := opFunc.bind([Int#mult]) //|Int, Int->Int| plus2 := opFunc.bind([Int#plus, 2]) //|Int -> Int| Closures are exprs returning Str prefix := "" funcs print := |Obj o->Str| { prefix + o.toStr }
  • 20.
    Mixins mixin FirstLast { abstract Str firstName() • Replacement of abstract Str lastName() interfaces } mixin Age{ abstract Int age } • Abstract fields and mixin WithImpl : FirstLast methods { Str fullName() { "$firstName $lastName" } • Methods can have } implementation mixin MultiInh : WithImpl, Age { override Str toStr() { "$fullName ($age years old)" } }
  • 21.
    Small convenience tricks Implicit upcasts Derived derived := base Safe invoke person?.phones?.first //null if p == null Elvis operator //alias for this == null ? that : this this ?: that No () for methods w/o args cap := "a".capitalize No ‘return’ for single expr Int negate(Int arg) { arg.negate } ‘isnot’ keyword alwaysFalse := "a" isnot Str
  • 22.
    Safety • Nullable types •Const fields and classes • No shared mutable state
  • 23.
    Nullable types class Nullable { Void main() { • Every type isn’t nullable Int? nullable := null Int nonNullable := 0 by default nonNullable = nullable //runtime err nonNullable = null //compile err • Obvious errors are do3(null) //compile err do3(nullable) //runtime err caught by compiler } • Int do1(Int? arg) { null } //compile err Automatic coercion Int do2(Int? arg) { arg } //runtime err Int? do3(Int arg) { arg } }
  • 24.
    Const types class NonConst { const Int constField • Const classes contain only const fields Int nonConstField Void mutate() { • Const fields must be set in constructor constField = 4 //compile err nonConstField = 4 //ok } • Const fields can have only const type or } [List, Map, Func].toImmutable class Const { new make(Int i, Str[] list) • Static fields must be const { //implicit call of list.toImmutable this.list = list • List and Maps can be const or mutable } const Str[] list }
  • 25.
    Actor framework • Actorsare the only way for multithreading • Actor are const classes extending Actor class • Actors interchange with const or serializable messages • Actors can have private mutable data
  • 26.
    Actor framework using concurrent constclass Logger : Actor { new make(ActorPool pool := ActorPool()) : super(pool) {} override Obj? receive(Obj? msg) { echo(msg); return null } } class Actors { Void main() { logger := Logger() logger.send("Hello") future := logger.sendLater(1sec, "Later") logger.send("Now") future2 := logger.sendWhenDone(future, "After later"); future3 := logger.sendWhenDone(future2, "After after") future3.cancel Actor.sleep(2sec) } }
  • 27.
  • 28.
    Declarative style Window { title = "FWT Demo" size = Size(800, 600) Label { text = "Hello, codefest!" }, }.open
  • 29.
    Declarative style a :=AddressBook { Person { first = "Ivan" last = "Inozemtsev" phones = [ Phone { num = "+79139494750"; type = PhoneType.cell}, Phone { num = "+73833631033" type = PhoneType.work } ] }, }
  • 30.
    Dynamic style Void iAmDynamic(Objduck) { duck->quack duck->swim("away") }
  • 31.
    Dynamic style class Dict Void main() { { Str:Obj? map dict := Dict(["foo":5, "bar":"str"]) new make(Str:Obj? map) { this.map = map } Str a := dict->foo->toStr //"5" Str b := dict->bar //"str" override Obj? trap(Str name, Obj?[]? args) Obj o := dict->o //null { dict->o = 42 if(args.isEmpty) return map[name]//getter } return (map[name] = args.first) //setter } }
  • 32.
    Functional style persons.findAll |Person p->Bool| { p.first == "Ivan" }.map |Person p -> Phone[]| { p.phones }.flatten .exclude |Phone ph->Bool| { ph.type == PhoneType.work }.map |Phone ph->Str| { ph.num }.each { echo(it) }
  • 33.
    Interaction with platform using [java]org.eclipse.dltk.internal.ui.text using [java]org.eclipse.core.runtime using [java]org.eclipse.dltk.core using [java]org.eclipse.ui.progress class ReconcileListener : IScriptReconcilingListener { private AstView view public new make(AstView view) { this.view = view } override Void aboutToBeReconciled() {} override Void reconciled(ISourceModule? module, Bool forced, IProgressMonitor? progressMonitor) { if (module != null) UpdateJob(view, module).schedule } }
  • 34.
    OK, what else? •Build scripts on Fantom • API Doc generation • Built-in unit-testing framework • Built-in web server • Interactive shell (REPL)
  • 35.
  • 36.
  • 37.
    X5 • Collects, analyzes and groups error reports • Highly concurrent application • Pure Fantom solution • Uses CouchDB
  • 38.
    F4 • World-class IDE for Fantom written on Fantom • Completion • Navigation • Highlighting • Search • Debugging
  • 39.
    Terminals • Full-featured xterm compatible terminal • Intense integration with Java • Embedded into Eclipse
  • 40.
    FPF - Fantom presentation framework • Scene graph-based UI Framework • Same look&feel on Desktop and browsers • HTML5 Canvas on Web • OpenGL Canvas on Desktop
  • 41.
  • 42.
    Kloudo.com • Pure Fantom on server side • Runs on built-in Fantom web server • Developed in 4 man- months
  • 43.
    Ready to beinvolved? • http://fantom.org • http://xored.com/f4 • mailto:fan-dev@xored.com Meet @ chill-out