Daniel
Daniel

Reputation: 47904

Why aren't patterns allowed in "use" bindings?

According to the spec, a use binding requires an identifier (unlike let) instead of a pattern. Why is this? Here's an example of a scenario that doesn't work.

type Disposable = Resource of IDisposable

let f disposable =
  use (Resource d) = disposable //ERROR: 'use' bindings must be of the form 'use <var> = <expr>'
  ()

Upvotes: 1

Views: 215

Answers (1)

kvb
kvb

Reputation: 55185

I think the likely answer is that lots of patterns don't make sense. For instance, how would you expect the compiler to handle the following code?

type DisposablePair = DisposablePair of IDisposable * IDisposable

let f disposablePair =
    use (DisposablePair(x,y)) = disposablePair
    ()

Your weird error message is probably due to the fact that even if you were using a let binding, you'd need to bind (Resource d) rather than Resource(d) (the compiler thinks you're declaring a new function).

For what it's worth, I do find the inability to use an underscore pattern to be an annoyance at times (particularly when dealing with IDisposable instances that exist only to demarcate scopes, like System.Transactions.TransactionScope). One way to generalize use bindings to handle underscores and a few other situations would be to require the right hand side of a use binding to be an IDisposable but to allow any pattern on the left hand side, so that:

use p = v in e 

would syntactically translate to something like

let ((p:System.IDisposable) as d) = v in try e finally d.Dispose()

Upvotes: 1

Related Questions