Does OCaml have the ability to pass by reference?

2019-06-25 13:10发布

问题:

In C++ a program can pass a reference, not value to a function.

void incrementInt(int &x) 
{
  ++x;
}

Does OCaml offer this same functionality?

回答1:

No, there is no strict equivalent.

There are refs, which are like pointers to new-allocated memory, and there are records, arrays, objects and values of other compound data types, that are passed "by object reference", which again means they act like pointer to new-allocated memory.

However there's no equivalent to a pointer to a variable or a C++ reference.



回答2:

There would be no distinguishable difference between pass-by-value and pass-by-reference in OCaml, because it's impossible to assign to a variable in OCaml. For example, your ++x is impossible in OCaml.

The difference between pass-by-value and pass-by-reference is in what happens when a parameter is assigned to inside the called function -- in pass-by-value, it has no effect on the passed variable (if a variable was passed); in pass-by-reference, it has the same effect as assignment to the passed variable in the calling scope. In OCaml, you cannot assign to a variable, so this distinction does not exist. If OCaml were "pass-by-reference", it would work the exact same way as if it were "pass-by-value".

You can pass around references to mutable data structures, and use this to share state between functions, but this has nothing to do with pass-by-reference, as you can do this in pass-by-value-only languages like C and Java.



回答3:

In OCaml, parameters are passed by value. A value by itself can be mutable, or immutable. The former can be modified by a callee, and it will be seen by the caller. Immutable value, obviously, can't be modified. The mutability of a value is defined by its type. Most of the value types in OCaml are immutable. The notable exceptions are arrays and strings (in the newer version of OCaml stings became immutable, but let's skip this topic). For example, values of type int are immutable. This is quite natural -- if you have the number 5 it is always the number 5, you can't mutate it. However, you can put this number into a mutable cell and pass this cell to a function. So that the function, can change the contents of the cell. Note, we are not changing the number itself, we are just putting another number into the same cell, e.g.,

type cell = {
  mutable value : int;
}

let incr x = 
   x.value <- x.value + 1

The incr function takes a value from a cell, creates a new value by incrementing it, and then puts the new value into the cell.

We can parametrize type cell, so that it can contain a value of any type, e.g.,

type 'a cell = {
    mutable value : 'a;
}

In fact, the ref type actually looks the same (modulo name). It is defined in the standard library as follows;

type 'a ref = {
  mutable contents : 'a;
}

The notion of passing by a reference was created by languages that leaked their own abstractions and made it necessary to a programmer to understand how parameters are passed to a function. In OCaml, you can forget this as a nightmare. Every parameter in OCaml takes only one machine word and is passed via a register, or via the stack if there are too many parameters. From a C programmer perspective, every value is a scalar or a pointer. Integers and unary constructors (variants) are passed as scalars, where compound data types, are always passed by a pointer.



回答4:

The closest, could be:

let x=ref 3;;        
let incrementInt x = 
  x := !x+1;;

incrementInt x;;
# !x;;
- : int = 4

As said sepp2k, it is not the same.