Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal for a Go-esque defer keyword #827

Open
teo-tsirpanis opened this issue Jan 18, 2020 · 3 comments
Open

Proposal for a Go-esque defer keyword #827

teo-tsirpanis opened this issue Jan 18, 2020 · 3 comments

Comments

@teo-tsirpanis
Copy link

@teo-tsirpanis teo-tsirpanis commented Jan 18, 2020

Title of Suggestion

I propose we add a keyword that executes a statement at the end of the block it was declared at, similar to Golang's defer keyword.

The existing way of approaching this problem in F# is the use keyword for IDisposables. For objects with more complex disposing logic like array pools, a solution is either a try/finally which pushes the indentation level deeper, or a use __ = {new IDisposable with member __.Dispose() = finishMe()} which is verbose and causes a memory allocation.

My proposal is to introduce a keyword called defer which would compile the following code block:

let arr = ArrayPool.Shared.Rent 521
defer ArrayPool.Shared.Return arr // It would be nice to omit parentheses
absolutelyOverImportantCalculations arr

into this:

let arr = ArrayPool.Shared.Rent 521
try
    absolutelyOverImportantCalculations arr
finally
    ArrayPool.Shared.Return arr

The defer keyword should be nothing more than a wrapper of try/finally as described above. A defer inside a loop would just be a block with a try/finally inside a loop. Using multiple defers means nesting multiple try/finallies. defering inside a computation expression would emit a call to the TryFinally method of the builder if it exists (otherwise we would error, or maybe allow custom behavior via a Defer method?).

Pros and Cons

The advantage of making this adjustment to F# is an easier way to make simple try/finally statements..

The disadvantages of making this adjustment to F# are 🙄

Extra information

Estimated cost (XS, S, M, L, XL, XXL): S

Related suggestions: N/A

Affidavit (please submit!)

Please tick this by placing a cross in the box:

  • This is not a question (e.g. like one you might ask on stackoverflow) and I have searched stackoverflow for discussions of this issue
  • I have searched both open and closed suggestions on this site and believe this is not a duplicate
  • This is not something which has obviously "already been decided" in previous versions of F#. If you're questioning a fundamental design decision that has obviously already been taken (e.g. "Make F# untyped") then please don't submit it.

Please tick all that apply:

  • This is not a breaking change to the F# language design
  • I or my company would be willing to help implement and/or test this
@Happypig375

This comment has been minimized.

Copy link
Contributor

@Happypig375 Happypig375 commented Jan 19, 2020

I'm unconvinced. You could as well define a

type [<Struct>] RentedArray(length) =
    member val Array = ArrayPool.Shared.Rent length
    interface System.IDisposable with
        member this.Dispose() = ArrayPool.Shared.Return this.Array
use rentedArr = new RentedArray(521)
let arr = rentedArr.Array
absolutelyOverImportantCalculations arr

The number of lines are the same: 2, and you don't have to remember to type defer ArrayPool.Shared.Return arr over and over again.

@cartermp

This comment has been minimized.

Copy link
Member

@cartermp cartermp commented Jan 19, 2020

See the matching C# proposal here: dotnet/csharplang#513

Note that this does fall under the following category for exclusion:

  • whether this gives multiple ways to achieve the same thing

There are other instances in the language where X is just a nicer way to do Y, but since try/finally is already an existing idiomatic pattern for this in .NET I don't find this likely to be accepted.

@cartermp

This comment has been minimized.

Copy link
Member

@cartermp cartermp commented Jan 19, 2020

But I do recognize the syntax is nicer in general, so having a way to obviate current .NET-idiomatic patterns doesn't seem half bad to me

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
3 participants
You can’t perform that action at this time.