1. Fantom
Cross-VM language
четверг, 24 июня 2010 г.
2. Общие сведения
Объектно-ориентированный
Статически типизированный
Opensource (Academic Free license 3.0)
четверг, 24 июня 2010 г.
3. Почему Fantom?
Мультиплатформенность
Отличный язык
Удобство “из коробки” (built-in tools)
Интеграция с платформой
О@#$%ная IDE от Xored :)
четверг, 24 июня 2010 г.
5. Достоинства языка
Повышение производительности
программиста (по сравнению с Java)
Страховка от ошибок
Мультипарадигменность
Низкий порог вхождения (по сравнению
с Scala, Clojure)
четверг, 24 июня 2010 г.
6. Производительность
Литералы
First-class функции
Замыкания
Вывод типов
Миксины
Множество удобных мелочей
четверг, 24 июня 2010 г.
8. Функции и замыкания
//simple signatures
Функции как объекты |->| voidSig := |->| {}
|->Int| returnsInt := |->Int| { 42 }
Методы содержат |Int a, Int b ->Int| plus := Int#plus.func
функции
|->| mainFunc := #main.func
Функции могут связывать opFunc := |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|
Замыкания - выражения, Str prefix := ""
возвращающие функции
print := |Obj o->Str| { prefix + o.toStr }
четверг, 24 июня 2010 г.
9. Вывод типов
Вывод локальных mc := MyClass()
s := "this is string"
переменных duration := 1day
Вывод параметров intList := [1,2,4]
типа для коллекций strIntMap := ["a":4, "b":5]
четверг, 24 июня 2010 г.
10. Миксины
mixin FirstLast
{
abstract Str firstName()
Абстрактные поля и abstract Str lastName()
}
методы
mixin Age{ abstract Int age }
Методы с mixin WithImpl : FirstLast
имплементацией {
Str fullName() { "$firstName $lastName" }
}
Перегрузка mixin MultiInh : WithImpl, Age
методов из Obj {
override Str toStr() { "$fullName ($age
years old)" }
}
четверг, 24 июня 2010 г.
11. Мелкие удобства
Неявные upcast’ы Derived derived := base
Safe invoke person?.phones?.first //null if p ==
null
Elvis operator //alias for this == null ? that : this
this ?: that
Не нужны () для методов
cap := "a".capitalize
без параметров
Опциональный return Int negate(Int arg) { arg.negate }
isnot’ keyword alwaysFalse := "a" isnot Str
четверг, 24 июня 2010 г.
12. Безопасность
Nullable типы
Константные классы и члены
No shared mutable state
четверг, 24 июня 2010 г.
13. Nullable types
class Nullable
{
Every type non- Void main()
{
nullable by default Int? nullable := null
Int nonNullable := 0
nonNullable = nullable //runtime err
Obvious errors are nonNullable = null //compile err
caught by compiler do3(null) //compile err
do3(nullable) //runtime err
}
Automatic coercion
Int do1(Int? arg) { null } //compile err
between nullable and
non-nullable with Int do2(Int? arg) { arg } //runtime err
runtime check Int? do3(Int arg) { arg }
}
четверг, 24 июня 2010 г.
14. Const types
class NonConst
{
Const classes contain only const const Int constField
fields Int nonConstField
Void mutate()
Const fields must be set in {
constField = 4 //compile err
constructor nonConstField = 4 //ok
}
}
Const fields can have only const type
class Const
or [List, Map, Func].toImmutable {
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 const Str[] list
}
mutable
четверг, 24 июня 2010 г.
15. 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
четверг, 24 июня 2010 г.
16. 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)
}
}
четверг, 24 июня 2010 г.
18. Декларативный стиль
a := AddressBook
{
Person
{
first = "Ivan"
last = "Inozemtsev"
phones = [
Phone { num = "+79139494750"; type = PhoneType.cell},
Phone
{
num = "+73833631033"
type = PhoneType.work
}
]
},
}
четверг, 24 июня 2010 г.
19. Динамический стиль
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
}
}
четверг, 24 июня 2010 г.
20. Функциональный
стиль
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) }
четверг, 24 июня 2010 г.
21. Что включено?
Возможность писать build-скрипты на
Фантоме
Компиляция документации API
Встроенные юнит-тесты
Встроенный веб-сервер
Интерактивная консоль (почти REPL)
четверг, 24 июня 2010 г.
22. Билд-скрипты
using build
class Build : build::BuildPod
{
new make()
{
podName = "f4builder"
summary = ""
depends = ["sys 1.0", "compiler 1.0",
"compilerJava 1.0", "javaBytecode 1.0", "f4core 1.0"]
srcDirs = [`fan/`]
outDir = `./`
}
}
четверг, 24 июня 2010 г.
23. Билд-скрипты
class Build : BuildPod
{
@Target { help = "Build native JavaFx files" }
Void javafx()
{
log.info("javafx [$podName]")
log.indent
src := scriptFile.parent + `javafx/`
dist := scriptFile.parent + `res/javafx/`
// start with a clean directory
Delete.make(this, dist).run
CreateDir.make(this, dist).run
// compile and package
cmd := ["javafxpackager", "-src",
src.osPath, "-appClass", "fan.fwt.Canvas", "-d", dist.osPath]
r := Process.make(cmd).run.join
...
четверг, 24 июня 2010 г.
24. документация API
**
** Compare two strings without regard to case and return -1, 0, or 1
** if this string is less than, equal to, or greater than the specified
** string. Only ASCII character case is taken into account.
** See `localeCompare` for localized case insensitive comparisions.
**
** Examples:
** "a".compareIgnoreCase("b") => -1
** "hi".compareIgnoreCase("HI") => 0
** "b".compareIgnoreCase("a") => 1
**
Int compareIgnoreCase(Str s)
четверг, 24 июня 2010 г.
25. документация API
compareIgnoreCase
Int compareIgnoreCase(Str s)
Compare two strings without regard to case and return -1, 0, or 1 if this
string is less than, equal to, or greater than the specified string. Only ASCII
character case is taken into account. See localeCompare for localized case
insensitive comparisions.
Examples:
"a".compareIgnoreCase("b") => -1
"hi".compareIgnoreCase("HI") => 0
"b".compareIgnoreCase("a") => 1
четверг, 24 июня 2010 г.
26. Тесты
class ParseExprTest : Test
{
////////////////////////////////////////////////////////////////
// Literals
////////////////////////////////////////////////////////////////
Void testNullLiteral()
{
verifyExpr(ExprId.nullLiteral, "null", |Literal l|
{
verifyEq(l.val, null)
verifyEq(l.resolvedType.qname, "sys::Obj")
})
}
четверг, 24 июня 2010 г.
27. Веб-сервер
class WebHello : AbstractMain
{
@Opt { help = "http port" }
Int port := 8080
override Int run()
{
wisp := WispService
{
it.port = this.port
it.root = RouteMod
{
routes = [
"hello": HelloMod()
]
}
}
return runServices([wisp])
}
}
const class HelloMod : WebMod
{
override Void onGet()
{
res.headers["Content-Type"] = "text/plain; charset=utf-8"
res.out.print("hello world #4")
}
}
четверг, 24 июня 2010 г.
28. Как поиграться?
komaz-mac:margincon ivaninozemtsev$ fansh
Fantom Shell v1.0.53 ('?' for help)
fansh> a := [1,2,3,4,5]
[1, 2, 3, 4, 5]
fansh> a.map { it * 2 }.map { it.toStr }.sortr
[8, 6, 4, 2, 10]
fansh> [1,2,3,4,5].reduce(0) |Int r, Int i -> Int| { r + i }
15
fansh> mul := |Int op1, Int op2 -> Int| { op1 * op2 }
|sys::Int,sys::Int->sys::Int|
fansh> plusSlot := Int#plus
sys::Int.plus
fansh> plus := |Int op1, Int op2 -> Int| { plusSlot.callOn(op1, [op2]) }
|sys::Int,sys::Int->sys::Int|
fansh> plus(4, 5)
9
четверг, 24 июня 2010 г.
29. Как поиграться?
komaz-mac:margincon ivaninozemtsev$ echo "#! /usr/bin/env fan
class Hello
{
Void main() { echo("Hello, world") }
}
" > hw.fan
komaz-mac:margincon ivaninozemtsev$ chmod +x hw.fan
komaz-mac:margincon ivaninozemtsev$ ./hw.fan
Hello, world
komaz-mac:margincon ivaninozemtsev$
четверг, 24 июня 2010 г.
30. Взаимодействие с платформой
(на примере Java)
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
}
}
четверг, 24 июня 2010 г.
31. F4 IDE
Написана на Семантическая
Фантоме подсветка
Компиляция/ Навигация по коду
запуск/отладка
Построение
Ссылки между иерархий
проектами наследования
Продвинутое Показ API-doc’ов
автодополнение
четверг, 24 июня 2010 г.