Coming from the world of C# I’ve noticed that there are a couple of things that I sometimes get confused about when playing around with stuff in F# land.

Passing arguments to functions

The way that we pass arguments to functions seems to be a fairly constant cause of confusion at the moment especially when doing that as part of a chain of other expressions where the use of brackets starts to become necessary.

In C# I’m used to putting the arguments in parentheses but that doesn’t quite work in F#.

…
The extra space implies that should_do_something is a function, which takes one argument which is a unit. This is more similar to the syntax for declaring a one argument function where the argument is actually a value, such as

let square_it x = x * x

When we put brackets around the arguments we are passing to functions they stop being passed as arguments as the compiler now tried to evaluate what’s in the brackets first and pass it to the function.

To give an example from playing around with Seq.append, if we do this:

let joined_items = Seq.append (first_item second_item)

We get a compilation error over ‘first_item’:

The value is not a function can cannot be applied

Here the compiler attempts to evaluate the function ‘first_item’ with an argument ‘second_item’ but since ‘first_item’ is actually a value and not a function this is impossible.

Referencing other types in our code

From my experiences so far it seems that F# uses one pass compilation such that you can only reference types or functions which have been defined either earlier in the file you’re currently in or appear in a file which is specified earlier in the compilation order.

This seems a bit restrictive to me although I’m sure there’s probably some benefits of this approach that I’m not yet aware of, maybe around type checking.

Just for clarification, in your point about Passing arguments to functions

1) The culprit isn’t the parens, it’s the comma. A Tuple is defined as a comma-separated list of items. The parens are not specifically needed. With that said, the precedence of the “,” operator is fairly low, so the expression “foo a,b” is taken as a 2-tuple, the first part being the value of “foo a” and the second being “b”. However if you wrote it with parens, “foo (a, b)”, this applies the function “foo” to the 2-tuple “a, b”.

2) Technically, when you call a .NET Framework function (“foo”) that takes (say) three arguments, the F# interface requires that you pass a *single* parameter, which in this case would be a 3-tuple. Hence the parens are required (as per the previous point). So the difference is that in F# you need the parens so that the statement parses the way you want it to, whereas in C# they’re necessary simply because that’s a syntactic requirement of the language.

2a) I’ve never tried it, but presumably you could rewrite “foo(a, b, c)” as two statements, “let args = a, b, c” followed by “foo args” (and with no parens at all).

Re your point about single pass compilation, I recently asked Don Syme about making multiple source passes to improve the type inference process. His reply was “Yes, it’s possible to do multi-pass type inference. There are also single-pass variations that generate a finite set of constraints.