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 this a reality by consuming TypeScript definitions files. However, the F# community has more ambitious plans to consume pure JavaScript files too. Seamless integration with the node package manager might also be on the horizon. Find out more at: http://funscript.info/ http://fsharp.org/ and http://zbray.com/
2. Me
• Energy trading systems
• C#/F#/C++
• Functional
zbray.com
@zbray
* Lots of F#
* Calculation Engine
* Not a JS expert
3. 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.
4. What does it support?
• Most F# code
• A little mscorlib
• 400+ bootstrapped tests
* Bootstrapped: FSharp.PowerPack + JInt
5. Primitives
• Strings
• Numbers (beware!)
• Booleans
* Ints/Bytes/etc. all converted to number.
* Loops that look infinite can turn out to be finite...
6. Flow
var _temp1;
if (x)
let y = {
_temp1 = "foo";
if x then "foo" }
else
else "bar" {
_temp1 = "bar";
y };
var y = _temp1;
return y;
var xs = List_CreateCons(1.000000,
List_CreateCons(2.000000,
List_CreateCons(3.000000,
List_Empty())));
let xs = [1; 2; 3] if ((xs.Tag == "Cons"))
{
match xs with var _xs = List_Tail(xs);
var x = List_Head(xs);
| x::xs -> x return x;
}
| _ -> failwith "never" 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
7. Functions
var isOdd = (function (x)
let isOdd x = x % 2 <> 0 {
return ((x % 2.000000).CompareTo(0.000000) != 0.000000);
isOdd 2 });
return isOdd(2.000000);
return (function (x)
{
(fun x -> x % 2 = 0)(2) return ((x % 2.000000).CompareTo(0.000000) == 0.000000);
})(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.
8. Records
type Person = var i_Person__ctor;
i_Person__ctor = (function (Name, Age)
{ Name: string; Age: int } {
this.Name = Name;
let bob = this.Age = Age;
});
{ Name = "Bob"; Age = 25 } var bob = (new i_Person__ctor("Bob", 25.000000));
var now = (new i_Person__ctor("Bob", 25.000000));
let now = { Name = "Bob"; Age = 25 } var _temp1;
var Age = 26.000000;
let soon = { now with Age = 26 } _temp1 = (new i_Person__ctor(now.Name, Age));
var soon = _temp1;
...but also discriminated unions, classes and modules
* 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.
9. Operators
let xs = [10 .. 20] var xs = Seq_ToList(Range_oneStep(10.000000, 20.000000));
let xs = [10 .. 2 .. 20] var xs = Seq_ToList(Range_customStep(10.000000, 2.000000, 20.000000));
var incr = (function (x)
let incr x = x + 1 {
return (x + 1.000000);
let x = 10 });
var x = 10.000000;
x |> incr return incr(x)
var incr = (function (x)
{
return (x + 1.000000);
});
let incr x = x + 1. var divBy2 = (function (x)
{
let divBy2 x = x / 2. return (x / 2.000000);
});
(incr << divBy2) 10. return (function (x)
{
return incr(divBy2(x));
})(10.000000);
* Logic & Arithmetic too (obviously)
* But also... identity, ignore, defaultArg, reference assignment etc.
* Can also define your own.
* See the tests for a complete list.
10. Computation
expressions
return (function (arg00)
{
return Async_StartImmediate(arg00, {Tag: "None"});
})((function (builder_)
async { return () } {
return builder_.Delay((function (unitVar)
|> Async.StartImmediate {
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
15. Not just for the browser.
* Desktop Apps.
* Tablet/Phone Apps.
* Servers.
16. 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.
CoffeeScript appeared in 2009.
But FunScript is focusing on something slightly different...
17. Extensibility
We cannot port the whole framework.
... but we can give you the tools to chip off the bits you need.
19. * Who is familar with type providers?
* Like code gen, but without the manual step and can be lazy (which is great for stuff like
freebase)...
20. 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?
21. * OK so...
* That’s one feature that existing implementations don’t have.
* What else?
22. What about these?
Elm
See: http://altjs.org/
* 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.
23. 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
24. 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.
25. The Lonely Island
* If you have to use FFI you are a lonely island
* Cannot easily access any of the existing JavaScript infrastructure
26. 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!
27. 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
...
28. 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
31. 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.
32. Summary
• FunScript compiles F# into JavaScript
• It is extensible: re-route any method call
• F# is the only statically typed language (that
capable of taking advantage of
I’m aware of)
JavaScript libraries without FFI or code-gen