-
Notifications
You must be signed in to change notification settings - Fork 21
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
Support inref
in computation expression operations
#1360
Comments
Hey @xperiandri 👋! This looks interesting, but can you please update the example code such that it doesn't have unresolved types? I.e., And can you explain what is currently not working for you? If I copy your code and fix the missing types, it just compiles. Can you update the original post such that it shows what part with Some related suggestions (but not the same): |
😆 no, definitely not an XS task. XS tasks are to fix some invalid xmldocs, or add one function to, let's say, |
There are currently no conversion between let foo (a: inref<string>) =
a = "foo"
foo "bar" So, the issues is not really about CEs, but rather about supporting implicit conversion from let foo (a: inref<string>) =
a = "foo"
let mutable f = "bar"
foo &f Not sure we want to do it for arbitrary expressions. It's up to @dsyme. |
In my mind, it is only about CEs. I have no opinion about the need for implicit conversion in other places. |
It's an interesting suggestion to allow this in a limited place (or perhaps in arguments with an opt-in attribute). IIRC it's not hard to implement this - it was more a policy decision about code correctness and understanding semantics. I think I'd be ok with an opt-in F#-specific attribute on the parameter as a general mechanism for call-by-address-to-inref. WDYT? |
I like that idea |
Passing it by ref won't always mean "more efficient". Passing by value oftentimes is more efficient, since JIT knows that structure is 100% on the stack and can optimize a bunch of stuff. On the other hand if you have a ref parameter, JIT doesn't really know where it's pointing - can be heap (class field), and in this case it will need write barriers. |
This, or warning, should be okay. |
Hm, I thought |
JIT doesn't differentiate between types of byref, so it can do defensive write barriers |
Is it possible to declare a read-only struct in F#? |
Yes @xperiandri: https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/structs#readonly-structs
See: https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/byrefs#inref-semantics For pinning, you can use |
What is |
It's way of pinning local onto stack. |
@xperiandri in case sharplab is ever down, copy pasted here open System
type PartitionKey (value : string) = struct end
type ItemRequestOptions () =
member val EnableContentResponseOnWrite = true with get, set
[<Struct>]
type CreateOperation<'a> = {
Item : 'a
PartitionKey : PartitionKey voption
RequestOptions : ItemRequestOptions
}
type CreateBuilder<'a> (enableContentResponseOnWrite : bool) =
member _.Yield _ =
{
Item = Unchecked.defaultof<_>
PartitionKey = ValueNone
RequestOptions = ItemRequestOptions (EnableContentResponseOnWrite = enableContentResponseOnWrite)
}
: CreateOperation<'a>
/// Sets the item being created
[<CustomOperation "item">]
member _.Item (state : inref<CreateOperation<_>>, item) = { state with Item = item }
/// Sets the partition key
[<CustomOperation "partitionKey">]
member _.PartitionKey (state : inref<CreateOperation<_>>, partitionKey : PartitionKey) = {
state with
PartitionKey = ValueSome partitionKey
}
/// Sets the partition key
[<CustomOperation "partitionKey">]
member _.PartitionKey (state : inref<CreateOperation<_>>, partitionKey : string) = {
state with
PartitionKey = ValueSome (PartitionKey partitionKey)
}
/// Sets the request options
[<CustomOperation "requestOptions">]
member _.RequestOptions (state : inref<CreateOperation<_>>, options : ItemRequestOptions) = {
state with
RequestOptions = options
}
let create<'a> = CreateBuilder<'a>(false)
let operation = create {
item "item"
partitionKey "partitionKey"
}
() |
I propose we support accepting
inref<'T>
as the first parameter of computation expression operationThe existing way of approaching this problem in F# is not using
inref
s and causing structs to be copiedPros and Cons
The advantages of making this adjustment to F# are performant object builders using computation expressions and value type state
The disadvantages of making this adjustment to F# do not exist
Extra information
Estimated cost (XS, S, M, L, XL, XXL): XS
Related suggestions: No
Affidavit
Please tick these items by placing a cross in the box:
Please tick all that apply:
For Readers
If you would like to see this issue implemented, please click the 👍 emoji on this issue. These counts are used to generally order the suggestions by engagement.
The text was updated successfully, but these errors were encountered: