1

I'm trying to pass by reference in F#. In C#, it is pretty easy using the ref and out keywords, but it seems in F#, it is not that simple. I just read this: http://davefancher.com/2014/03/24/passing-arguments-by-reference-in-f/, which suggests using a reference cell. (I suppose this means there is no analog to the out keyword in C# where you don't have to initialize a variable to pass it.)

But anyway, I'm wondering if this is the best/only way to pass by reference in F#, and if this is even a good idea in a functional language.

EDIT:

I am interested because I just realized that exceptions were slowing down my code. I'm on a crusade to eliminate them. Basically, my plan is this: say a function returns a double or throws an exception if there is an error. Instead, I'll pass in a double and an ErrorCode type by reference as a bit mask and then pass the values and the errors down. I'm guessing I'll just have to make all these variables mutable.

user3685285
  • 6,066
  • 13
  • 54
  • 95
  • 3
    Why do you need to do this? If it's to be able to call existing BCL methods like `TryParse`, here's how to do it: http://stackoverflow.com/a/13589596/126014 – Mark Seemann May 11 '15 at 16:30
  • 1
    @WesleyWiser's answer is the correct one given your edit, but I just wanted to add the following. Trying to translate C# into F# one-to-one is a mistake. Do not do this, or you will inevitably end up in a bind like the current one. Instead, look at the _actual problem_ you're trying to solve instead of particular technical details of some language. In this instance: "the actual problem" is "reporting errors", and "technical details" is "by-ref parameters". – Fyodor Soikin May 11 '15 at 17:11

4 Answers4

4

Your question has a number of parts which I will try to answer:

  • which suggests using a reference cell

    • Yes, Reference Cells (or ref cells) are the idiomatic way to pass mutable data into a function
  • I suppose this means there is no analog to the out keyword in C# where you don't have to initialize a variable to pass it.

    • C# usually uses out parameters to signify additional return values. The idomatic way to do that in F# is with tuples. For example the C# function int TryParse(string s, out bool succeeded) is simply TryParse(s : string) -> (int, bool)
  • if this is even a good idea in a functional language.

    • This is certainly not what I would consider to be normal, idiomatic F# code. The way I would represent this would be with a Discriminated Union representing the possible results:

type MyFunctionResult = 
    | Success of double
    | ErrorCase1
    | ErrorCase2 of AddditionalDataType

etc

If you have a number of functions that use this style, it's very easy to compose them together with a bind function.

Wesley Wiser
  • 9,491
  • 4
  • 50
  • 69
3

You could use & instead of C#'s ref, but a variable prefixed with & must be mutable. A nice article that covers even PInvoke gotchas: https://pblasucci.wordpress.com/2012/07/23/managing-pointers-or-fs-platform-invoke-gotcha/.

  open System.Collections.Generic
  let dic = new Dictionary<string, string>()
  dic.Add("key", "myvalue")
  let mutable v = "" // v is mutable
  let success = dic.TryGetValue("key", &v);
  System.Console.WriteLine(v)
  let succ, value = dic.TryGetValue("key") // this is what Mark Seemann says is the comment, a shortcut for C#'s `Try...(.., out ...)` is using tuples in F#
V.B.
  • 6,236
  • 1
  • 33
  • 56
1

Let me describe what OCaml does because I do not know F# and someone can confirm that F# is similar enough that my answer applies.

In a functional programming language such as OCaml or F# data are immutable by default. That is, you need to declare things to be mutable before they are, and in fact mutable data structures are less common than the immutable ones (but not uncommon).

Now, because data are immutable by default it does not matter how you pass arguments, as they won't get altered anyway. Under these circumstances it makes sense to pass simple datatypes which fit into registers by value and everything else by reference.

Mutable data types are passed by reference, of course, or else there would be little value in having them.

Perhaps you can give us an example of what you're trying to do. Are you passing mutable or immutable data?

Andrej Bauer
  • 2,458
  • 17
  • 26
0

I was just getting an error message in F# that told me I need obj ref and was passing just obj

browser.Navigate2(url_obj)

so I just added ref and it worked

browser.Navigate2(ref url_obj)

So I guess you just add ref.

It's very useful when working with COM objects.