FunScript 2013 (with speakers notes)

ZachBray 3,312 views 33 slides Jan 31, 2013
Slide 1
Slide 1 of 33
Slide 1
1
Slide 2
2
Slide 3
3
Slide 4
4
Slide 5
5
Slide 6
6
Slide 7
7
Slide 8
8
Slide 9
9
Slide 10
10
Slide 11
11
Slide 12
12
Slide 13
13
Slide 14
14
Slide 15
15
Slide 16
16
Slide 17
17
Slide 18
18
Slide 19
19
Slide 20
20
Slide 21
21
Slide 22
22
Slide 23
23
Slide 24
24
Slide 25
25
Slide 26
26
Slide 27
27
Slide 28
28
Slide 29
29
Slide 30
30
Slide 31
31
Slide 32
32
Slide 33
33

About This Presentation

FunScript/F# is the only statically-typed compile-to-js language poised to take full advantage of the JavaScript ecosystem. F#'s type providers make consuming JavaScript possible without any code generation or foreign function interface definition. FunScript has taken the first steps to making t...


Slide Content

FunScript
Zach Bray 2013

Me
•Energy trading systems
•C#/F#/C++
•Functional
zbray.com
@zbray
* Lots of F#
* Calculation Engine
* Not a JS expert

What is FunScript?
// F# Code -> JavaScript Code
Compiler.Compile: Expr -> string
* F# Code -> JS Code
* Quotation Expr -> String
* Quotations in F# provide a way of getting the AST from a piece of code.

What does it support?
•Most F# code
•A little mscorlib
•400+ bootstrapped tests
* Bootstrapped: FSharp.PowerPack + JInt

Primitives
•Strings
•Numbers (beware!)
•Booleans
* Ints/Bytes/etc. all converted to number.
* Loops that look infinite can turn out to be finite...

Flow
var _temp1;
if (x)
{
_temp1 = "foo";
}
else
{
_temp1 = "bar";
};
var y = _temp1;
return y;
let y =
if x then "foo"
else "bar"
y
let xs = [1; 2; 3]
match xs with
| x::xs -> x
| _ -> failwith "never"
var xs = List_CreateCons(1.000000,
List_CreateCons(2.000000,
List_CreateCons(3.000000,
List_Empty())));
if ((xs.Tag == "Cons"))
{
var _xs = List_Tail(xs);
var x = List_Head(xs);
return x;
}
else
{
throw ("never");
}
* Inline if... then... else... blocks
* Pattern matching
* While + For loops
* Caveat: Quotation Problem: “for x in xs” when xs is an array

Functions
(fun x -> x % 2 = 0)(2)
return (function (x)
{
return ((x % 2.000000).CompareTo(0.000000) == 0.000000);
})(2.000000);
let isOdd x = x % 2 <> 0
isOdd 2
var isOdd = (function (x)
{
return ((x % 2.000000).CompareTo(0.000000) != 0.000000);
});
return isOdd(2.000000);
* Let bound functions
* Anonymous lambda functions
* Note/Caveat: CompareTo rather than operators: Allows structural equality. Has negative
impact on performance. Cite: Mandelbrot test by Carsten Koenig 100x worse than JS vs.
1000x for Fay.

Records
var i_Person__ctor;
i_Person__ctor = (function (Name, Age)
{
this.Name = Name;
this.Age = Age;
});
var bob = (new i_Person__ctor("Bob", 25.000000));
type Person =
{ Name: string; Age: int }
let bob =
{ Name = "Bob"; Age = 25 }
...but also discriminated unions, classes and modules
var now = (new i_Person__ctor("Bob", 25.000000));
var _temp1;
var Age = 26.000000;
_temp1 = (new i_Person__ctor(now.Name, Age));
var soon = _temp1;
let now = { Name = "Bob"; Age = 25 }
let soon = { now with Age = 26 }
* Most of the types you can define
* Records, DUs, Classes, Modules
* Records very similar to JSON.
* Record expressions are shallow copies with some changes
* Records & DUs have structural equality.
* Caveat: Class inheritance doesn’t work (yet)
* Caveat: DU structural equality is broken on the main branch.

Operators
var xs = Seq_ToList(Range_oneStep( 10.000000, 20.000000));
let xs = [10 .. 20]
var xs = Seq_ToList(Range_customStep( 10.000000, 2.000000, 20.000000));
let xs = [10 .. 2 .. 20]
let incr x = x + 1
let x = 10
x |> incr
var incr = (function (x)
{
return (x + 1.000000);
});
var x = 10.000000;
return incr(x)
var incr = (function (x)
{
return (x + 1.000000);
});
var divBy2 = (function (x)
{
return (x / 2.000000);
});
return (function (x)
{
return incr(divBy2(x));
})(10.000000);
let incr x = x + 1.
let divBy2 x = x / 2.
(incr << divBy2) 10.
* Logic & Arithmetic too (obviously)
* But also... identity, ignore, defaultArg, reference assignment etc.
* Can also define your own.
* See the tests for a complete list.

Computation
expressions
async { return () }
|> Async.StartImmediate
return (function (arg00)
{
return Async_StartImmediate(arg00, {Tag: "None"});
})((function (builder_)
{
return builder_.Delay((function (unitVar)
{
var _temp3;
return builder_.Return(_temp3);
}));
})(Async_get_async()));
* Async workflow built in...
* Can define your own too, e.g., the maybe monad if you wanted it
* LiveScript has the concept of back calls

Data structures
•Array
•List
•Seq
•Map
•Set
•Option

Bored yet?
Boring bit over (hopefully).
We’re half way to the pub.

Why bother?

Enormous number of devices. More than .Net or Mono.

Not just for the browser.
* Desktop Apps.
* Tablet/Phone Apps.
* Servers.

Don’t we have this
already?
•FSWebTools
•WebSharper
•Pit
•JSIL
F# has a long history of compiling to JavaScript
Tomas released FSWebTools back in 2006 or 07.
Co!eeScript appeared in 2009.
But FunScript is focusing on something slightly di!erent...

Extensibility
We cannot port the whole framework.
... but we can give you the tools to chip o! the bits you need.

Movie data example
Tomas built this web app with FunScript.
No .NET the whole thing runs in JS.

* Who is familar with type providers?
* Like code gen, but without the manual step and can be lazy (which is great for stu! like
freebase)...

Mapping the Apiary.io
type provider
•Makes calls to the framework
•Not quotation friendly
•We replace (or re-route) the calls to
quotation friendly methods and types
ExpressionReplacer.createUnsafe <@ ApiaryDocument.Create @> <@ JsonProvider.JsRuntime.CreateDocument @>
ExpressionReplacer.createUnsafe <@ fun (d:ApiaryDocument) -> d.JsonValue @> <@ JsonProvider.JsRuntime.Identity @>
ExpressionReplacer.createUnsafe <@ fun (d:ApiaryDocument) -> d.Context @> <@ getContext @>
Compiler.Compile(<@ page () @>, components=FunScript.Data.Components.DataProviders)
* We cannot use the provider out of the box...
* But because the compiler is EXTENSIBLE we can tell it how to convert those calls.
* It [the compiler] will find all call sites and change them.
* Then we can use the provider in our JavaScript output
* Any questions on that?

* OK so...
* That’s one feature that existing implementations don’t have.
* What else?

What about these?
See: http://altjs.org/
Elm
* Many languages target JavaScript now.
* It has become a kind of IL.
* Some are quite good. I recommend LiveScript if you don’t mind something dynamic.

Dynamically typed

Good at interop

But if its too close to
JavaScript...
* Can reuse existing libraries
* Can consume JS data
* But...
* Inconsistent operations (annoying on forms)
* Dodgy for ... in ... loops, although fixed in most compile to JS languages
* Dodgy function scope. Yuck!
* Counter-intuitive “Falsey” values
* Auto semi-colon insertion

Statically typed:
FFI sucks
* Foreign function interface
* Have to map every function you want to use
* Tedious and error prone - may as well go dynamic
* This is Fay. But same in Roy, js_of_ocaml, etc.
* Can do this in FunScript too.

The Lonely Island
* If you have to use FFI you are a lonely island
* Cannot easily access any of the existing JavaScript infrastructure

Bypass FFI with type
providers
* Uses similar techniques to those I described in the Movie example
* The TypeScript library creates a bunch of types and tells the compiler how to turn them into
JavaScript.
* F# is the only language that supports this workflow at the moment!

Just the beginning
•TypeScript only has mappings for 10s of
JavaScript libraries.
•Google Closure annotations
•JavaScript type inferrer
* Google closure might provide many more mappings
* JavaScript type inferrer would probably be very hard to build but it would be awesome
- EDIT: Colin Bull has already made a little progress towards this: https://github.com/
colinbull/IronJS/commit/612b799351a37d720920d4c68797787d2b72aaca
- EDIT: We could even have a type provider to the node package manager (NPM) then we
wouldn’t even need to mess around with files. For example:
type npmProvider = NodePacakgeManager()
let npm = npmProvider.GetContext()
let express = npm.express.v3_1_2
let connect = npm.connect.v2_7_2
...

GitHub numbers

JavaScript: #1

FSharp: #43
Sources:
www.github.com/languages/
www.r-chart.com/2010/08/github-stats-on-programming-languages.html
So this is the sell...
Why should you go out and build me a JavaScript type inferrer...
21% of the projects on GitHub are _labelled_ as JavaScript

2010-2012: http://t.arboreus.com/post/31469214663/visualizing-changes-in-popularity-rankings-of
* This is how the popularity of programming languages has changed (according to fairly
arbitrary measures) in the last two years.
* JavaScript is still on top.

LinkedIn numbers
914,000 people 2,000 people
JavaScript F#
in scale

Thanks to the
FunScript contributors
•Tomas Petricek
•Phillip Trelford
•James Freiwirth
•Robert Pickering
•Steffen Forkmann
If you’d like to contribute come and talk to me afterwards.

Summary
•FunScript compiles F# into JavaScript
•It is extensible: re-route any method call
•F# is the only statically typed language (that
I’m aware of) capable of taking advantage of
JavaScript libraries without FFI or code-gen

Questions?