Angelos Bimpoudis (ISO) • Angelos Mpimpoydhs (what the university gave me) • Aggelos Biboudis (how I always preferred :P) • Engel Bimpoudis (in Dutch?) • PhD Student, University of Athens, advised by Yannis Smaragdakis
APIs • Benchmarks in Scala, Java, C#, F# • Bird’s eye view of the lambda translation techniques • Simple pipelines • Sequential and Parallel, Windows and Linux • Optimising Frameworks (ScalaBlitz, LinqOptimizer): declarative queries -> loop based code
Functional Interface is needed • Like inner and anonymous classes, lambdas can capture variables • invokedynamic refers to a recipe instead of generating bytecode (1-time cost) • class-generation at compile time is avoided • fewer classes for class-loading • favours inlining optimisations (e.g., in non-capturing lambdas we get constant loads)
of characteristics • source/generator |> lazy |> lazy |> lazy |> terminal • intermediate ops are gathered in CPS-style • a compact data structure of transformations is applied at the source • flow of characteristics can be used for optimisations • a bulk operation can be optimised (e.g. a do … while loop)
If they capture free variables, these are fields in a compiler-generated type (otherwise just static- methods). • F# lambdas are represented as compiler-generated classes that inherit FSharpFunc<T,R>
fluent-style method calls nums.Where(x => x % 2 == 0).Select(x => x * x).Sum(); • with the equivalent query comprehension syntactic sugar (from x in nums where x % 2 == 0 select x * x).Sum(); • F# is inspired by OCaml and first class citizen of .NET. The Seq module is the Streaming API of F# nums |> Seq.filter(funx->x%2=0) |> Seq.map (fun x -> x * x) |> Seq.sum
• IEnumerator keeps state of the iteration (Current & MoveNext) e.g., a .Select(func) combinator: • Returns a SelectEnumerable object encapsulating the inner source. We get a SelectEnumerator that passes inner’s Current to func. • 3 virtual calls (MoveNext, Current, func) per element per iterator.
support zip (being naturally pull) • push to pull transition is not performant • infinite & early termination combinators do not play well • for-based loops are not yet matched
problem: • Duncan Coutts et al. (Stream Fusion 2007) proposed a deforestation technique that still didn’t fuse concatMap (a pull-based approach btw) • Andrew Farmer et al. (Hermit in the Stream 2014) use Hermit (not just ghc RULES) • Implement list fusion using streams instead of foldr/ build (ticket opened 9 years ago, “we close this ticket as requiring more research”)
bool | El of 'a code | Stream of 'a repr and ('a,'st) gen = { init: 'w. ('st -> 'w code) -> 'w code; advance: 'w. 'st -> ('a stream_val -> 'w code) -> 'w code } and 'a repr = G : ('a,'st) gen -> 'a repr
expressions methods • Computation expressions is a language feature of F# to allow overridable semantics • Computation expressions = monadic bind + monadic return + methods that correspond to the syntax of F#
continuation types (statements, expressions, exceptions, etc) • F# uses continuation monad for asynchronous workflows • async/await in C# and Dart as essentially, reset/shift in languages that support it • await in expressions means that we could write int i = 1 + await (async { some computation }) + 3 • scala supports reset/shift • regular continuations (T -> Unit) -> Unit • polymorphic in the return type (A -> B) -> C • a syntax driven shift/reset with with bind and return is super easy • Filinski’s Representing Monads is followed by effects people (all monads are encoded as the cont monad) • scala-virtualized follows tagless interpreters approach (thus object algebras), not Filinski’s