fslang-suggestions icon indicating copy to clipboard operation
fslang-suggestions copied to clipboard

Allow let-bound fields in object expressions

Open GratianPlume opened this issue 4 years ago • 5 comments

Currently when we use object expressions, the outer mutable variable will be promoted to Ref, if multiple variable variables are used, multiple Ref will be generated. In fact, most of the time, we don’t share these variables, can any way to add variable variables directly in the object is provided? For example, in the following code

  let foo() = 
      let mutable isDisposed = false
      {
         new IDisposable with
            member __.Dispose() = 
               if not isDisposed then
                  isDisposed <- true
      }

can the variable isDisposed be moved inside

  let foo() =       
      {
         let mutable isDisposed = false
         new IDisposable with
            member __.Dispose() = 
               if not isDisposed then
                  isDisposed <- true
      }

or else alternatives?

GratianPlume avatar Jan 08 '21 07:01 GratianPlume

I believe that a more sensible approach would be to allow let and member val bindings in object expressions just like in classes, with the same syntax.

  let foo() =       
      {
         new IDisposable with
            let mutable isDisposed = false
            member val K = 1
            member __.Dispose() = 
               if not isDisposed then
                  isDisposed <- true
      }

Happypig375 avatar Jan 08 '21 11:01 Happypig375

Promoting the mutable value to a ref when it's closed over in an object expression like that is by design. Object expressions are objects that are allocated on the heap, so we need to promote this to the heap. It's just like when we promote a mutable value to a ref when it is passed to a lambda.

I agree with @Happypig375 that any work in this area would be to allow scoping mutability to the expression itself. Is that what you'd like to suggest?

cartermp avatar Jan 08 '21 19:01 cartermp

Promoting the mutable value to a ref when it's closed over in an object expression like that is by design. Object expressions are objects that are allocated on the heap, so we need to promote this to the heap. It's just like when we promote a mutable value to a ref when it is passed to a lambda.

I agree with @Happypig375 that any work in this area would be to allow scoping mutability to the expression itself. Is that what you'd like to suggest?

Yes, I think, the object generated by the object expression has already been allocated in the heap, if the field is not shared, there is no need to generate another object

GratianPlume avatar Jan 09 '21 02:01 GratianPlume

I believe that a more sensible approach would be to allow let and member val bindings in object expressions just like in classes, with the same syntax.

  let foo() =       
      {
         new IDisposable with
            let mutable isDisposed = false
            member val K = 1
            member __.Dispose() = 
               if not isDisposed then
                  isDisposed <- true
      }

If it is written below, it is necessary to distinguish between member and override. Currently, member and override are the same, And if you use object + interface, you need to consider more permissions, as I mentioned in another discussion

GratianPlume avatar Jan 09 '21 04:01 GratianPlume

I agree let mutable should be usable inside the scope of the object expression

Marking this as approved in principle.

dsyme avatar Jan 14 '21 12:01 dsyme