3

Is there a modifier that can be put on a function declaration that will force it to not be a closure? I would like the following not to compile with this supposed modification to inner:

let outer() =
    let i = 7
    let inner() =
        printf "%i" i
    inner()

but to complain about i not defined. The reason for this is safety -- I want to make sure I'm not capturing and perhaps modyfing anything when I'm intending not to, and performance of closures versus functions.

Arbil
  • 999
  • 1
  • 7
  • 15
  • I suspect the only possible answer is to make `inner` a private top level function in a module only containing `outer` – John Palmer Jun 03 '14 at 10:20
  • @JohnPalmer Yup, that would be the obvious one. I just like the layout of inline definitions better, especially if `outer` is a method. – Arbil Jun 03 '14 at 10:23
  • 5
    I think the right solution for not worrying about modifying data is to use only immutable variables and types. – svick Jun 03 '14 at 10:27
  • @svick It is not viable for performance reasons to have every single variable and type immutable. Even if it were, I'd still like to make sure I don't have closures where not needed due to overhead. – Arbil Jun 03 '14 at 11:05
  • Has the overhead you're worried about caused you to miss specific end-to-end performance goals? If not, then this is a case of premature optimization. See Eric Lippert's excellent description of how to think about optimization [here](http://stackoverflow.com/a/2473829/82959) (and [here](http://stackoverflow.com/a/3770194/82959), and [here](http://stackoverflow.com/a/1313152/82959), etc.). – kvb Jun 03 '14 at 13:47
  • @kvb No, it hasn't made me miss any goals (I'm writing my first f# application so haven't missed or met any goals yet!). I gather it is impossible? I believe it would be a good idea, when I think of an algorithm that uses a self-contained function, to be able to tell this to the compiler and let it verify this. – Arbil Jun 03 '14 at 14:30
  • 1
    I don't think it's possible, but I also don't think it's worth worrying about. I've written a lot of F# code, and inadvertent capture has never been an issue. As @svick says, you should be using immutability wherever feasible, and you should aim for correctness first and foremost. In particularly performance sensitive code you may find (after profiling!) that you need to reorder definitions, but otherwise just write things in the order that seems most natural. – kvb Jun 03 '14 at 15:59
  • 1
    @kvb I agree with just one caveat. What I'd like to do would increase, and not decrease, correctness and expressibility! If one could write (say) `let pure inner() = ...` it would immediately tell the reader that there is no need to look upwards of the definition to understand what it does. It wouldn't be a premature optimization, which by definition decreases correctness and/or clarity. – Arbil Jun 03 '14 at 16:28
  • 2
    Note that in your particular case, the closure is optimized away by the compiler in Release mode via inlining of `i`. There are lots of other optimizations the F# compiler performs in Release mode. In addition to @kvb's comment, that's one more reason not to "preemptively" worry about performance. – Marc Sigrist Jun 04 '14 at 09:51

1 Answers1

3

Aside from moving functions to locations where there is nothing in scope to capture, there is no way to achieve this. That being said, in the example you gave there is a simple way to partially achieve this:

let outer() =        
    let inner() =
        printf "%i" i
    let i = 7
    inner()
N_A
  • 19,799
  • 4
  • 52
  • 98