• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Progressive f# tutorials nyc dmitry mozorov & jack pappas on code quotations code as-data for f#

Progressive f# tutorials nyc dmitry mozorov & jack pappas on code quotations code as-data for f#



Code Quotations: Code-as-Data for F# ...

Code Quotations: Code-as-Data for F#
This tutorial will cover F# Code Quotations in-depth. You'll learn what Code Quotations are, how to use them, and where to apply them in your applications. We'll work through several real-world examples to highlight the important features -- and potential pitfalls -- of Code Quotations.



Total Views
Views on SlideShare
Embed Views



3 Embeds 48

http://skillsmatter.com 44
http://smash 2
http://smash2 2



Upload Details

Uploaded via as OpenOffice

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
Post Comment
Edit your comment

    Progressive f# tutorials nyc dmitry mozorov & jack pappas on code quotations code as-data for f# Progressive f# tutorials nyc dmitry mozorov & jack pappas on code quotations code as-data for f# Presentation Transcript

    • F# Quotations: “Code as Data” Jack Pappas Dmitry Morozov SkillsMatter Progressive F# Tutorials NYC September 19th, 2013
    • Code as Data • Code & Data – What is the difference? • Is there a difference? • Programs exist to process data – The F# compiler processes data (your source code) • Source code is no different than other kinds of data
    • This Session • What is a “quoted expression”? – A simple, immutable data structure – Represents a fragment of F# code • Syllabus – Background – Working with Quotations – Manipulating Quotations – Applications of Quotations
    • Background • The idea of treating code as data first appeared in Lisp Lisp F# Code (1 2 3) [1; 2; 3] Code as Data ‘(1 2 3) <@ [1; 2; 3] @>
    • Background • A language that has the natural ability to manipulate itself is extremely powerful • “Amplify” a developer’s productivity using metaprogramming techniques
    • Background • Other languages can manipulate their own code – clang: C++ program, manipulates C++ – Roslyn: C# library, manipulates C# – f2c: C program, manipulates FORTRAN and C • What makes Lisp and F# different? – Reflective meta-programming – Built-in language feature vs. external functionality
    • Background • Now that we can manipulate code as data, what can we do with it? • Transform – modify, convert, translate • Analyze – Static analysis – Advanced testing techniques (e.g., verification) – Collect and record code metrics (e.g., complexity)
    • Background • Execute – Interpret the code/data – Translate to another lang., compile, execute – Specialized hardware (e.g., GPU, FPGA) – Specialized execution (e.g., auto-parallelization) – Execute remotely (e.g., web service) – Some combination of the above – (Rarely) execute in same context, e.g., by translating to IL and executing
    • Use Cases • LINQ support in F# – Extension of this idea: Cheney, Lindley, Wadler. “The essence of language-integrated query” • Use as an IL when developing type providers – Quotations much easier to work with – Create quotations, translate to IL
    • Use Cases • Testing – Moq/Foq/Unquote • GPU programming – Compute: FSCL, QuantAlea – Graphics: SharpShaders (F# -> HLSL) • Web Development (F# -> JavaScript) – WebSharper – FunScript – PitFw
    • Comparing Alternatives • What alternatives exist to quotations? – F# AST – LINQ Expression Trees – CIL (MSIL) • Imperative: Expression Trees, CIL – C# lambdas compiled into Expression Trees by the C# compiler • Functional: F# AST, Quotations
    • Comparing Alternatives • F# AST – Designed for the compiler’s internal use – Carries more information than quotations – Requires additional library – Unwieldy for simple use cases
    • Comparing Alternatives • LINQ Expression Trees – Introduced in .NET 3.5; initially somewhat limited – Expanded in .NET 4.0; now roughly 1:1 with CIL – Doesn’t support certain functional features like closures
    • Comparing Alternatives • Common Intermediate Language (CIL) – Low-level; relatively difficult to work with – Supports all CLR features – F# Quotations don’t support all CLR features ● Notably, throw and rethrow – these need to be wrapped in a function and compiled using the proto compiler ● No fault/filter clauses • F# Quotations don’t support open generics
    • Quotations: How-To • Open some namespaces • Define a module, then some functions within the module open System.Reflection open Microsoft.FSharp.Reflection open Microsoft.FSharp.Quotations module Foo = let addTwo x = x + 2
    • Quotations: How-To • Apply [<ReflectedDefinition>] to your function – Or, apply it to your module as a shortcut for applying it to all functions in the module module Foo = /// Dummy class used to retrieve /// the module type. type internal Dummy = class end [<ReflectedDefinition>] let addTwo x = x + 2
    • Quotations: How-To • Using Reflection, get the MethodInfo for your function • Call Expr.TryGetReflectedDefinition with the MethodInfo to get the Expr for the method
    • Quotations: How-To [<EntryPoint>] let main argv = let fooType = typeof<Foo.Dummy>.DeclaringType let addTwoMethodInfo = match fooType.GetMethod "addTwo" with | null -> None | x -> Some x addTwoMethodInfo |> Option.map Expr.TryGetReflectedDefinition |> Option.iter (printfn "addTwo: %A")
    • Quotations: How-To • For each active pattern in Quotations.Patterns, there is a corresponding static member of the Expr type. – These are used to construct and destructure each quotation “case”. • Two types of quotations: typed and untyped – Typed: Expr<‘T> – Untyped: Expr
    • Quotations: How-To • Expr<‘T> is just a wrapper around Expr – Use the .Raw property for Expr<‘T> -> Expr – Use the Coerce pattern for Expr -> Expr<‘T> • Quoting an expression – Typed: <@ fun x -> x + 2 @> – Untyped: <@@ fun x -> x + 2 @@>
    • Quotations: How-To • “Splicing” – a way to combine quotations – Inserts one quotation into another – Typed: let bar = <@ 3 + "Blah".Length @> let foo = <@ fun x -> x + %bar @> – Untyped: let bar = <@@ 3 + "Blah".Length @@> let foo = <@@ fun x -> x + %%bar @@>
    • Quotations: How-To • Note: You don’t always need [<ReflectedDefinition>] to use quotations • Using our previous example, this is equivalent let addTwo = <@ fun x -> x + 2 @>
    • Computations on Trees • When working with Quotations, it’s critical you’re comfortable with trees and recursion • Tree computations in imperative languages usually built around the “visitor” pattern – Visitor class usually holds private, mutable state – Often implemented as an abstract base class per tree type, and one virtual method per node type – Mechanics of the traversal intermixed with computation happening at nodes
    • Computations on Trees • Possible to implement a functional alternative to the “visitor” pattern? • Knuth did – decades ago! • Introducing “attribute grammars” – Initially used as a means of describing how LL/LR parsers annotate a parse tree – Later, used to describe how “attributes” are computed from on tree
    • Computations on Trees • Attribute grammars are declarative – They do not define any traversal order • Attribute grammars allow you to define purely functional, monadic computations over trees – For those familiar with Haskell – attribute evaluation is actually co-monadic • AGs on ASTs (or Quotations) can be used to implement purely functional AOP
    • Computations on Trees • Three main kinds of attributes • Inherited (L-attributes) – Attribute “inherited” from parent node – Compare to the reader workflow • Synthesized (S-attributes) – Attribute “synthesized” by a child node, passed back up to parent node – Compare to the writer workflow
    • Computations on Trees • Threaded (SL-attributes) – Attribute value inherited from parent node, modified by child, then passed back up to parent – Combination of Inherited and Synthesized – Compare to the state workflow • Attribute values can be int, string, UDTs, etc. • They can also be tree nodes – We can use this to define tree transformations
    • Exercises • Implement a function(s) which, given an Expr: – Print the equiv. F# source code – Invert the mathematical operators (+)/(-), (*)/(/) – Compute the set of methods called by the Expr ● Bonus: Compute this transitively – Determine if the Expr can ever raise an exn – Determine if the Expr is pure (side-effect free) – Rewrite it so all strings are passed through String.Intern