Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why should successive arguments involving method application be parenthesized?

Tags:

f#

Suppose the following F# function:

let f (x:int) (y:int) = 42

I suspect that the reason I need to parenthesize the arguments in example z2 below is because of type inference; my example might not be great, but it's easy to imagine how things could get very hairy:

let z1 = f 2 3
let z2 = f 2 (f 3 5)

However, the following case is less clear to me:

let rng = System.Random()
let z3 = f 1 rng.Next(5)

z3 doesn't work, with a clear error message:

error FS0597: Successive arguments should be separated by spaces or tupled, and arguments involving function or method applications should be parenthesized.

Fixing it is trivial (parenthesize all the things), but what I am not clear about is why such an expression is a problem. I assume this has to do with type inference again, but naively, it seems to me that here, methods having a list of arguments surrounded by a parenthesis would actually make things less potentially ambiguous. Does this have to do with the fact that rng.Next(5) is equivalent to rng.Next 5?

Can someone hint, give an example or explain why this rule is needed, or what type of problems would arise if it were not there?

like image 540
Mathias Avatar asked May 24 '14 18:05

Mathias


1 Answers

I think that the problem here is that the code could be treated as:

let z3 = f 1 rng.Next (5)

This would be equivalent to omitting the parentheses and so it would be calling f with 3 arguments (the second being a function value). This sounds a bit silly, but the compiler actually does not strictly insist on having a space between parameters. For example:

let second a b = b
add 5(1)          // This works fine and calls 'add 5 1'
add id(1)         // error FS0597
add rng.Next(5)   // error FS0597
add (rng.Next(5)) // This works fine (partial application)

I think the problem is that if you look at the sequence of the 4 examples in the above snippet, it is not clear which behavior should you get in the second and the third case.

The call rng.Next(5) is still treated in a special way, because F# allows you to chain calls if they are formed by single-parameter application without space. For example rng.Next(5).ToString(). But, for example, writing second(1)(2) is allowed, but second(1)(2).ToString() will not work.

like image 200
Tomas Petricek Avatar answered Oct 26 '22 01:10

Tomas Petricek