Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

F# 'function' functions cannot inline

The following 2 functions

let episodeDict1 (a: obj) = 
    match a with
    | :? (Episode -> _) as generator ->
        let episodes = [D; W; M]
        let values = episodes |> List.map generator
        List.zip episodes values
    | :? _ as value -> [D, value; W, value; M, value]
    |> dict |> Dictionary


let episodeDict2: obj -> Dictionary<Episode, _> = function
    | :? (Episode -> _) as generator ->
        let episodes = [D; W; M]
        let values = episodes |> List.map generator
        List.zip episodes values |> dict |> Dictionary
    | :? _ as value -> [D, value; W, value; M, value] |> dict |> Dictionary

do the same thing, however the second cannot be marked inline

let inline episodeDict2…

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

FS0832 Only functions may be marked ‘inline’

Which seems really weird.

Can someone explain?

>Solution :

In your case, the two functions are really equivalent and so the compiler could be smarter and figure this out. However, the problem is that the second function is defined as a "value" that is not "syntactic function", i.e., it is not defined as let func x y z = .... The compiler uses a simple rule and only allows inlinding of syntactic functions.

The reason for this is that, when you have a function that is not defined as a syntactic function, it may not be possible to inline it. For example:

let foo = 
  let mutable counter = 0
  fun () -> counter <- counter + 1; counter

If you took the body of this definition and placed it into the place where the function is used, it would change the meaning of the program! For example foo () + foo () returns 3, but if you did the inlining naively:

( let mutable counter = 0
  fun () -> counter <- counter + 1; counter ) () + 
( let mutable counter = 0
  fun () -> counter <- counter + 1; counter ) ()

You would get 2 as the result! Again, you could imagine more clever compiler dealing with this – but I believe the F# decision here is reasonable – have a simple rule that is easy to understand (and ensures you get the right thing).

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading