-
Notifications
You must be signed in to change notification settings - Fork 793
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
FS0971: copyOfStruct not defined #8069
Comments
That line creates a tuple of two mutable values, and then you use the Just saying: I understand that the compiler complains, but:
I'd assume this is a bug, but someone from the MS's F# team will have to have their say in it ;). Btw, you seem to want to set two values at once, why not just do: let mutable a, b = ([|1|],[|2|]) This will set If you want to create a mutable value from the return of a function (i.e., hold a reference to the original computed value), instead of using let f x =
let a = ref (2 * x)
let b = ref (3 * x)
b, a
let (x, y) = f 12 // x and y are now mutable reference cells and will color yellow in VS
VS 2019 has been out for a while and a lot has improved in the F# area, perhaps time to upgrade? ;) |
Forgot to add, arrays are mutable by default in F#, you an use the reverse arrow syntax to set an item at an index inside the array. The variables in the let binding merely hold a reference to the array, making them mutable usually doesn't have much benefit: let x = [|3;4:5|]
x.[2] <- 9 // 5 changed to 9 |
Labeling as a bug for the error message, which should be better. This pattern is not supported since |
Sorry you feel that way. Your search for a proper algorithm that is tail recursive is a good one, and anything can be made tail recursive, or imperative, with F#. The easiest you can do to avoid copying, is to use byref/outref/inref, but this is only available in VS 2019, which you aren't using yet. If you're stuck with VS 2017, there are still many other ways to get to the function calling paradigm you want (one such way is perhaps with an I'll have a look at your function you showed above by tomorrow (it's late now). On the feature suggestion: that may be a good thing, but a function always returns only one value (which can be a tuple, which is two values wrapped in a type), which is why it isn't as easy as it seems from a technical standpoint. Hence my suggestion to use inref/outref/byref to overcome that issue the easy way.
Disclaimer: The example code you showed is without arrays and without a lot of copying and only uses reference types, perhaps with the exception of |
@giuliohome I'm re-opening this so that we have a open bug tracking the error message, which is not correct. Please feel free to unsubscribe from the thread if you'd prefer not to get notifications. |
Glad to hear that! Note that this syntax doesn't create a mutable tuple per se, but two individual values that are mutable. The assignment operator, contrary to the original syntax, recognizes that it should decompose the tuple from the r-side. You can see that when you use reflector to inspect the generated code. I'm assuming then that you won't need further help with your algorithm?
Indeed ;) BTW, this report is best left open so we can address the confusing error message. |
You don't need assignment anymore when you use And you're right, you cannot use For the algorithm, we'd need to choose: either it returns a single tuple, with the content set in the function, which can be assigned to either a mutable tuple, or auto-deconstructed into two mutable values. Or you choose that the function must update the values that are referenced, in which case these should be given as The magic deconstruction can also be used if the 2nd param is |
Yes, I know. But your original issue was (if I understood it correctly) to return values that are references. Returning byrefs (and having I may be wrong, but I think the notion of managed pointers did not exist prior to F# 4.5, apart from some workarounds you could use in your code for interop by using attributes. Such highly efficient memory-manipulating code is now possible directly from F# without resorting to C# and the proper IL is now emitted. Part of the discussion on |
Edit, I just read:
So, while F# 4.5 got a lot, some of it already existed before. I have to admit, I don't know exactly what went in when, but you can always check the changes log, or try your code with a recent version to see if you have benefits by upgrading (you can install side-by-side, meaning you'll never lose your old VS 2017 and can always go back). |
Indeed it is, one shadows the existing variables, the other doesn't. The variable to start the loop with should already be mutable and not be redeclared. I wholeheartedly agree to the language suggestion, it seems to be a natural thing to support. |
This has become a rather strange thread now that @giuliohome removed all his comments. It was a valuable discussion, but that's now gone. I believe the original issue is still a bug, and if I remember correctly, we should do something about it. But without the original discussion, it's a bit hard to reconstruct it. @cartermp, I haven't seen this happening on other threads before (people deleting their own valuable insights), should we close this issue as it appears the original poster has lost interest in pursuing it, or should we re-create it with the knowledge we still have? The reported error message was most certainly a bug... |
Good that the thread exists, because I ran into the same issue and found the answer here. |
@Martin521 Note that your environmental settings are different here; Visual Studio is up to date but it sounds like your Ionide environment is not. |
@abelbraaksma @cartermp @Martin521 Do you know a repro for this problem? |
@dsyme, the problem here is that @giuliohome removed his original issue (still there in the history) and a lot of a very valuable discussion about assignment and deconstruction with tuples containing mutables. The removed posts makes this thread look rather odd and one-sided now. IIRC, there was discussion about his example, because it was possibly invalid code that just didn't show a compile error. I could be off, it's been half a year since. I also believe there was some discussion about upgrading VS 2017, which he (or she) wasn't inclined to do. But again, I may not remember it correctly, as a lot of the discussion is lost. The problem was deconstruction while using the assignment operator, which isn't supported and doesn't show an error until you compile: (x, y) <- ([|1|],[|2|]) // where x and y are mutable The error: error FS0971: Undefined value 'copyOfStruct : (int [] * int []) ref' The original post was this, the error still reproduces in VS 2019, but is shown when compiling, not in the editor: Repro stepsA simple Console pgm [<EntryPoint>]
let main argv =
let mutable way1 = [|0|]
let mutable way2 = [|0|]
(way1,way2) <- ([|1|],[|2|])
printfn "%A" argv
0 // return an integer exit code Expected behaviorIt should be equivalent of [<EntryPoint>]
let main argv =
let mutable way1 = [|0|]
let mutable way2 = [|0|]
let (_way1,_way2) = ([|1|],[|2|])
way1 <- _way1
way2 <- _way2
printfn "%A" argv
0 // return an integer exit code Actual behaviorI'm getting a compile error:
Known workaroundsMy second equivalent version above. Related information
|
Cool, thanks for the info. Duplicate of #8899 I believe. |
Please rewrite it with your words if you need to keep it open. Thank you.
The text was updated successfully, but these errors were encountered: