11

This is what I have so far.

let Swap (left : int , right : int ) = (right, left)

let mutable x = 5
let mutable y = 10

let (newX, newY) = Swap(x, y) //<--this works

//none of these seem to work
//x, y <- Swap(x, y)
//(x, y) <- Swap(x, y)
//(x, y) <- Swap(x, y)
//do (x, y) = Swap(x, y)
//let (x, y) = Swap(x, y)
//do (x, y) <- Swap(x, y)
//let (x, y) <- Swap(x, y)
svick
  • 236,525
  • 50
  • 385
  • 514
Jonathan Allen
  • 68,373
  • 70
  • 259
  • 447
  • I am learning python and imagine how cool F# could be if we allow: `a, b <- b, a`, `x.[a], x.[b] <- x[b], x[a]` So that `swap` is no longer needed. – colinfang Sep 30 '13 at 11:55

3 Answers3

12

You can't; there's no syntax to update 'more than one mutable variable' with a single assignment. Of course you can do

let newX, newY = Swap(x,y)
x <- newX
y <- newY
Brian
  • 117,631
  • 17
  • 236
  • 300
  • I was hoping for a more favorable answer, but at least this is a correct one. Sigh, F#'s inconsistencies are quickly becomming a pain in my side. I realize that I'm pushing against the boundries, but I shouldn't be hitting them this soon. – Jonathan Allen Jun 03 '09 at 21:39
  • 5
    I'm not sure I'd characterize as a "boundary" the idea that language constructs that are discouraged have less-convenient syntax than the preferred constructs. Making best practices also the most convenient seems like a smart idea to me. – Joel Mueller Jun 03 '09 at 21:57
  • 2
    @Joel. Isn't that the definition of boundary? If I was using the preferred syntax I wouldn't have used that term. – Jonathan Allen Jun 07 '09 at 06:37
  • 1
    @Brian and if that stuff is in a while loop? Trying to implement alphabeta search and ran into this issue... – BitTickler Feb 15 '15 at 20:30
5

F# has "by reference" parameters just like C#, so you can write a classic swap function similarly:

let swap (x: byref<'a>) (y: byref<'a>) =
    let temp = x
    x <- y
    y <- temp

let mutable x,y = 1,2
swap &x &y
Stephen Swensen
  • 22,107
  • 9
  • 81
  • 136
  • This code doesn't work as written, `byref` must be used in tupled arguments, they cannot be curryable. Other than that, it's a fine solution. – Abel Jan 06 '20 at 01:37
4

The code you have commented doesn't work because when you write "x, y" you create a new tuple that is an immutable value, so can't be updated. You could create a mutable tuple and then overwrite it with the result of the swap function if you want:

let mutable toto = 5, 10 

let swap (x, y) = y, x

toto  <- swap toto

My advice would be to investigate the immutable side of F#, look at the ways you can use immutable structures to achieve what you previously would have done using mutable values.

Rob

Robert
  • 6,407
  • 2
  • 34
  • 41
  • This is what is probably wanted – John Weldon Jun 03 '09 at 20:46
  • If you want to generalize this, you still have to unpack the mutable tuple back to the original values. So really using a mutable tuple is a waste. – Jonathan Allen Jun 03 '09 at 21:35
  • 1
    It's unclear to me why you need to unpack or even replace the new x and y in the original variable. I any real world exmaple you'd just write "let x', y' = swap x y" and directly use x and y prime. – Robert Jun 04 '09 at 05:56
  • @Robert, This isn't about using idomatic F#. This is about pushing on the edges and seeing where the cracks are. I never use swap in real code, but I still need to know whether or not it is possible because other designs may require it. – Jonathan Allen Jun 07 '09 at 06:41
  • 1
    I would be interested to know what kind of design could require this behaviour. – Robert Jun 07 '09 at 08:10