Created
February 15, 2013 15:08
-
-
Save 1tgr/4960921 to your computer and use it in GitHub Desktop.
Adventures in inlining
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| module Program | |
| // Copy and paste from the FSharp.Core source code | |
| let inline zeroCreateUnchecked (count:int) = | |
| (# "newarr !0" type ('T) count : 'T array #) | |
| let inline map fn a = | |
| let b = zeroCreateUnchecked (Array.length a) | |
| for i in 0 .. Array.length a - 1 do | |
| b.[i] <- fn a.[i] | |
| b | |
| let numbers = [| 1; 2; 3 |] | |
| let addOne n = n + 1 | |
| let one () = | |
| // Our own map function, using the fun keyword | |
| // Everything is inlined; loops like a C# for loop | |
| printfn "%A" (map (fun a -> a + 1) numbers) | |
| let two () = | |
| // Our own map function, using the let keyword and the function defined elsewhere | |
| // Identical to one(). The let keyword makes no difference. | |
| printfn "%A" (map addOne numbers) | |
| let three () = | |
| // Standard Array.map, using the fun keyword | |
| // Everything is inlined, including a null reference check at the start of Array.map, which is | |
| // arguably not needed (the 'numbers' array can't be null). | |
| // The loop syntax ends up being slightly different compared to one(). ILSpy recognises this | |
| // as a while loop, and one() as a for loop. | |
| printfn "%A" (Array.map (fun a -> a + 1) numbers) | |
| let four () = | |
| // Standard Array.map, using the let keyword and the function defined elsewhere | |
| // Idential to three(). The let keyword makes no difference. | |
| printfn "%A" (Array.map addOne numbers) | |
| let five () = | |
| // Sequence syntax, writing the loop body directly | |
| // The compiler generates a hidden class which implements IEnumerable<int>, and generates the | |
| // numbers. It calls Seq.toArray on an instance of this class. The 'a + 1' code is inlined | |
| // inside this class. | |
| printfn "%A" [| for a in numbers -> a + 1 |] | |
| let six () = | |
| // Sequence syntax, calling another function from the loop body | |
| // Identical to three(). The let keyword makes no difference. | |
| printfn "%A" [| for a in numbers -> addOne a |] | |
| one () | |
| two () | |
| three () | |
| four () | |
| five () | |
| six () |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment