Nats De - 2 months ago 17

C# Question

I am doing a Machine Learning using F# book. I am converting the F# code to C# and doing the tutorials as I do not understand F# that much. I really got stuck in a part of code and wonder if someone can tell me how to write the code in c#. Even just the explanation of what the code does in F# would be helpful.. The code I am stuck is

`let tokenScore (group:DocsGroup) (token:Token) =`

if group.TokenFrequencies.ContainsKey token

then log group.TokenFrequencies.[token]

else 0.0

let score (document:TokenizedDoc) (group:DocsGroup) =

let scoreToken = tokenScore group

log group.Proportion +

(document |> Seq.sumBy scoreToken)

I'm really stuck with the

`let scoreToken = tokenScore group`

log group.Proportion +

(document |> Seq.sumBy scoreToken)

This is the tutorial in the Machine Learning Projects for .Net Developers - Chapter 2. If you can help me that would be great. Thanks in advance

Answer Source

F# functions are curried. That means that if a function is declared with two parameters, and you call it with just one parameter, the result is *another function*, of one parameter. Here's an example:

```
let add x y = x + y
let n = add 2 3 // Now n has the value 5
let addFive = add 5 // This is a *function* that takes one parameter
let altAddFive y = add 5 y // Another way to define the same thing
let result = addFive 3 // Now result has the value 8
let altResult = altAddFive 3 // This one also has the value 8
```

So in the `score`

function, the name `scoreToken`

now refers to a function that takes one parameter, and then calls `tokenScore`

with two parameters: `group`

, and the value it was just passed. In other words, the definition of `scoreToken`

could have been written as:

```
let scoreToken token = tokenScore group token
```

And that would have been the same thing.

Now for the next line. First, `log`

is the natural logarithm function, usually written as `ln`

in mathematical notation. It takes a single floating-point number, and returns a floating-point number. The rules of operator precedence in F# are that function calls are **higher** precedence than operators, so `log 3.0 + 5.0`

would be interpreted as `(log 3.0) + 5.0`

, which would *not* be the same value as `log 8.0`

. Therefore, the following lines:

```
log group.Proportion +
(document |> Seq.sumBy scoreToken)
```

are equivalent to this:

```
let score1 = log group.Proportion
let score2 = document |> Seq.sumBy scoreToken
score1 + score2
```

Finally, the `document |> Seq.sumBy scoreToken`

line may also be confusing you. There are two parts to it. First, `Seq.sumBy`

is the equivalent of the two-parameter version of the LINQ `Sum`

method, but the parameter order in F# is the opposite of the one in C#. The F# `Seq.sumBy`

function takes two parameters; first, the function that should be applied to each element to produce a value, and second, the sequence of elements. I.e., if you were calling it without that `|>`

operator, it would look like this:

```
Seq.sumBy scoreToken document
```

This would go through the `document`

sequence (which is of type `TokenizedDoc`

and, given the way it's used, clearly can be treated as a sequence of tokens). For each token in the document, the `scoreToken`

function would be called (if you'll remember, calling `scoreToken t`

, where `t`

is some token, is the same as calling `tokenScore group t`

). That call would produce a floating-point value. Finally, all the floating-point values will be added together to produce the final score.

However, in F#, it's traditional to use the "pipe" operator `|>`

when summing sequences or doing similar things: `document |> Seq.sumBy scoreToken`

is exactly equivalent to `Seq.sumBy scoreToken document`

. The `|>`

operator is rather well explained in the answer to another SO question so I won't duplicate that answer here.

So what this function is doing is taking the natural log of the `group.Proportion`

value, and adding it to the score of each token in the document. The result of this addition is the last expression in the function, so that's the result of the function: in F#, unlike C#, you don't need to type `return`

at the end of functions. (The `return`

keyword has a different meaning in F#, which I won't get into now as that's a whole different topic).