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

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

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

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

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

Infer generic parameters

intList := [1,2,4]strToIntMap := ["a":4, "b":5]

LiteralsLists [1, 3, 5, 7]

["a", ["b", "cd"]]

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

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

URIs`ftp://user001:[email protected]/mydir/myfile.txt``http://fantom.org``/Users/ivaninozemtsev/work/fantom`

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

Ranges [1..5, 2..8, 0..<5]

Functions and closures

Functions are first class objects//simple signatures|->| voidSig := |->| {}|->Int| returnsInt := |->Int| { 42 }

Methods are just function wrappers

|Int a, Int b ->Int| plus := Int#plus.func|->| mainFunc := #main.func

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

Closures are exprs returning funcs

Str prefix := ""print := |Obj o->Str| { prefix + o.toStr }

Mixinsmixin FirstLast{ abstract Str firstName() abstract Str lastName()}

mixin Age{ abstract Int age }

mixin WithImpl : FirstLast{ Str fullName() { "$firstName $lastName" }}

mixin MultiInh : WithImpl, Age{ override Str toStr() { "$fullName ($age years old)" } }

• Replacement of interfaces

• Abstract fields and methods

• Methods can have implementation

Small convenience tricks

Implicit upcasts Derived derived := base

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

Elvis operator //alias for this == null ? that : thisthis ?: 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

• Every type isn’t nullable by default

• Obvious errors are caught by compiler

• Automatic coercion

class Nullable{ Void main() { Int? nullable := null Int nonNullable := 0 nonNullable = nullable //runtime err nonNullable = null //compile err do3(null) //compile err do3(nullable) //runtime err } Int do1(Int? arg) { null } //compile err Int do2(Int? arg) { arg } //runtime err Int? do3(Int arg) { arg } }

Const types

• Const classes contain only const fields

• Const fields must be set in constructor

• Const fields can have only const type or [List, Map, Func].toImmutable

• Static fields must be const

• List and Maps can be const or mutable

class NonConst{ const Int constField Int nonConstField Void mutate() { constField = 4 //compile err nonConstField = 4 //ok }}

class Const{ new make(Int i, Str[] list) { //implicit call of list.toImmutable this.list = list } 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 frameworkusing 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 styleclass Dict{ Str:Obj? map new make(Str:Obj? map) { this.map = map } override Obj? trap(Str name, Obj?[]? args) { if(args.isEmpty) return map[name]//getter return (map[name] = args.first) //setter }}

Void main() { dict := Dict(["foo":5, "bar":"str"]) Str a := dict->foo->toStr //"5" Str b := dict->bar //"str" Obj o := dict->o //null dict->o = 42 }

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.textusing [java]org.eclipse.core.runtimeusing [java]org.eclipse.dltk.coreusing [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:[email protected]

Meet @ chill-out