﻿ F# Topics on Functions
 Topics on Functions

 Fundamentals of Functions

 The Return Type of a Function
 When a function has performed its assignment, it may or may not produce a value. If a function produces a value, that function is said to return a value. If you create a function and appropriately define it, the compiler will try to find out the type of value the function must return. In some cases, you may want to specify the type of value that a function must return. To specify the return type, before the = sign, type a colon followed by the desired data type. Here is an example:

```let getValue() : int =
1450```

Do the same even if the function takes more than one parameter. Here is an example:

```let getFullName first_name middle_initial last_name : string =
first_name + " " + middle_initial + ". " + last_name```

If you specify the data type(s) of the parameter(s) and you want to indicate the return type of the function, specify it after the parentheses of the (last) parameter. Here is an example:

`let add (x:int) (y:int) (z:int) : int = x + y + y`
 Techniques of Returning a Value

Consider the following function:

`let calculate x y z = x + y + y`

If a function has only one statement in its body, that statement produces the value that the function returns. In the above case, the function returns the value that would be produced by the expression x + y + z. As mentioned previously, the body of a function can start and/or end on a line other than the one with the = sign. Here is an example:

```let calculate x y z =
x + y + y;```

Still, in this case, the return value is the one produced by x + y + z.

In some cases, before giving its last expression, the body of a function may contain multiple statements. Here is an example:

```let calculate x y z =
sprintf "Number 1: %d" x
sprintf "Number 2: %d" y
sprintf "Number 3: %d" z
x + y + y```

In this case also, the last expression constitutes the return value of the function.

 A Function in a Function

One of the characteristics of functional programming is that a function can be created in the body of another function. Here are examples:

```open System
open System.Windows.Forms

let create caption =
let calculateValueOfAnnuity yearlyDeposit interestRate periods =
let interestPercent = interestRate / 100.00
let interestPlus1 = 1.00 + interestPercent
let poweredInterest = interestPlus1 ** periods
let poweredInterestMinus1 = poweredInterest - 1.00
yearlyDeposit * poweredInterestMinus1 / interestPercent
let calculateInterestEarned futureValue deposit periods =
let deposits = deposit * periods
futureValue - deposits

// Form: Future Value of an Ordinary Annuity
let ordinaryAnnuity : Form = new Form()
ordinaryAnnuity.Width  <- 288
ordinaryAnnuity.Height <- 210
ordinaryAnnuity.Text <- caption

// Label: Yearly Deposit
let lblYearlyDeposit : Label = new Label()
lblYearlyDeposit.Left <- 18
lblYearlyDeposit.Top  <- 24
lblYearlyDeposit.Width <- 85
lblYearlyDeposit.Text <- "Yearly Deposit:"

// Text Box: PurchasePrice
let txtYearlyDeposit : TextBox = new TextBox()
txtYearlyDeposit.Left  <- 106
txtYearlyDeposit.Top   <- 21
txtYearlyDeposit.Width <- 60
txtYearlyDeposit.Text  <- "0.00"

// Label: Interest Rate
let lblInterestRate : Label = new Label()
lblInterestRate.Left  <- 18
lblInterestRate.Top   <- 55
lblInterestRate.Width <- 85
lblInterestRate.Text  <- "Interest Rate:"

// Text Box: Interest Rate
let txtInterestRate : TextBox = new TextBox()
txtInterestRate.Left <- 106
txtInterestRate.Top <- 51
txtInterestRate.Width <- 44
txtInterestRate.Text <- "0.00"

// Label: Percent %
let lblPercent : Label = new Label()
lblPercent.Left  <-  150
lblPercent.Top   <-  55
lblPercent.Width <-  60
lblPercent.Text  <- "%"

// Label: Periods
let lblPeriods : Label = new Label()
lblPeriods.Left  <-  18
lblPeriods.Top   <-  82
lblPeriods.Width <-  68
lblPeriods.Text  <- "Periods:"

// Text Box: Periods
let txtPeriods : TextBox = new TextBox()
txtPeriods.Left  <- 106
txtPeriods.Top   <-  81
txtPeriods.Width <-  44
txtPeriods.Text  <- "0.00"

// Label: Years
let lblYears : Label = new Label()
lblYears.Left  <-  150
lblYears.Top   <-   85
lblYears.Width <-   36
lblYears.Text  <- "Years"

// Button: Calculate
let btnCalculate : Button = new Button()
btnCalculate.Left <- 190
btnCalculate.Top  <-  78
btnCalculate.Text <- "Calculate"

// Label: Future Value
let lblFutureValue : Label = new Label()
lblFutureValue.Left  <-   18
lblFutureValue.Top   <-  118
lblFutureValue.Width <-  80
lblFutureValue.Text  <- "Future Value:"

// Text Box: Future Value
let txtFutureValue : TextBox = new TextBox()
txtFutureValue.Left  <- 106
txtFutureValue.Top   <- 115
txtFutureValue.Width <-  64
txtFutureValue.Text  <- "0.00"

// Label: Interest Earned
let lblInterestEarned : Label = new Label()
lblInterestEarned.Left  <-  18
lblInterestEarned.Top   <-  145
lblInterestEarned.Width <-  88
lblInterestEarned.Text  <- "Interest Earned:"

// Text Box: Interest Earned
let txtInterestEarned : TextBox = new TextBox()
txtInterestEarned.Left  <- 106
txtInterestEarned.Top   <-  142
txtInterestEarned.Width <-  64
txtInterestEarned.Text  <- "0.00"

// Button: Close
let btnClose : Button = new Button()
btnClose.Left <- 190
btnClose.Top  <- 140
btnClose.Text <- "Close"

let btnCalculateClick e =
let principal   = float txtYearlyDeposit.Text
let intRate     = float txtInterestRate.Text
let years       = float txtPeriods.Text
let futureValue = calculateValueOfAnnuity principal intRate years
let earned      = calculateInterestEarned futureValue principal years

let strFutureValue = sprintf "%0.02f" futureValue
let strInterestEarned = sprintf "%0.02f" earned

txtFutureValue.Text <- strFutureValue
txtInterestEarned.Text <- strInterestEarned

let btnCloseClick e = ordinaryAnnuity.Close()

Application.Run ordinaryAnnuity

create "Future Value of Ordinary Annuity"```

Here is an example of executing the program:

 Automatic Generalization

Remember that you can pass a parameter to a function without specifying the data type of that parameter, in which case the compiler would consider that the parameter uses an integer value. We also saw that the way a parameter is used, whether in the function's body or when the function is called, can specify the actual value of the parameter. This is also valid if the function takes more than one parameter. This is referred to as automatic generalization.

 Functions in a Variable

Like many languages, F# wants you to initialize a variable when declaring it. Like most languages, F# allows you initialize a variable by calling a function, that is, by using the return value of a function. Unlike many languages, F# allows you to create one or many expressions by which you would get a value for the variable. For example, you can declare variables, call functions, and create a value that the variable would use. Here is an example:

```let totalArea =
let length = 36.88
let width  = 27.99
let height = 12.74
let side1 = multiply length width
let side2 = multiply length height
let side3 = multiply width height```

When you do this, the variable behaves like a function: the last line would hold the value that will be given to the variable. Here is an example:

```let multiply x y = x * y

let totalArea =
let length = 36.88
let width  = 27.99
let height = 12.74
let side1 = multiply length width
let side2 = multiply length height
let side3 = multiply width height
side1 + side2 + side3

sprintf "Total Box Area: %0.04f"  totalArea```

You can then use the variable as you want. Here is an example:

```open System
open System.Windows.Forms

let subtract a b = a - b
let divide   a b : float = a / b

// Form: Depreciation - Straight-Line Method
let depreciationSLM : Form = new Form()
depreciationSLM.Width  <- 295
depreciationSLM.Height <- 170
depreciationSLM.Text <- "Depreciation - Straight-Line Method"

// Label: Cost
let lblCost : Label = new Label()
lblCost.Left  <- 22
lblCost.Top   <- 19
lblCost.Width <- 80
lblCost.Text  <- "Cost:"

// Text Box: Machine Cost
let txtCost : TextBox = new TextBox()
txtCost.Left  <- 105
txtCost.Top   <- 16
txtCost.Width <- 54

// Label: Salvage Value
let lblSalvageValue : Label = new Label()
lblSalvageValue.Left  <- 22
lblSalvageValue.Top   <- 45
lblSalvageValue.Width <- 80
lblSalvageValue.Text  <- "Salvage Value:"

// Text Box: SalvageValue
let txtSalvageValue : TextBox = new TextBox()
txtSalvageValue.Left  <- 105
txtSalvageValue.Top   <- 43
txtSalvageValue.Width <- 54

// Label: Estimated Life
let lblEstimatedLife : Label = new Label()
lblEstimatedLife.Left  <- 22
lblEstimatedLife.Top   <- 74
lblEstimatedLife.Width <- 80
lblEstimatedLife.Text  <- "Estimated Life:"

// Text Box: Estimated Life
let txtEstimatedLife : TextBox = new TextBox()
txtEstimatedLife.Left  <- 105
txtEstimatedLife.Top   <- 70
txtEstimatedLife.Width <- 34

// Label: Years
let lblYears : Label = new Label()
lblYears.Left  <- 142
lblYears.Top   <-  76
lblYears.Width <-  40
lblYears.Text  <- "Years"

// Button: Calculate
let btnCalculate : Button = new Button()
btnCalculate.Left <- 196
btnCalculate.Top  <-  71
btnCalculate.Text <- "Allocate"

// Label: Depreciation
let lblDepreciation : Label = new Label()
lblDepreciation.Left  <-  22
lblDepreciation.Top   <- 108
lblDepreciation.Width <-  74
lblDepreciation.Text  <- "Depreciation:"

// Text Box: Depreciation
let txtDepreciation : TextBox = new TextBox()
txtDepreciation.Left  <- 105
txtDepreciation.Top   <- 105
txtDepreciation.Width <- 54

// Label: /Years
let lblPerYear : Label = new Label()
lblPerYear.Left  <- 162
lblPerYear.Top   <- 106
lblPerYear.Width <-  34
lblPerYear.Text  <- "/Year"

// Button: Close
let btnClose : Button = new Button()
btnClose.Left  <- 196
btnClose.Top   <- 104
btnClose.Text <- "Close"
let btnCloseClick e =  depreciationSLM.Close()

let btnCalculateClick e =
let depreciation =
let cost  = float txtCost.Text
let value = float txtSalvageValue.Text
let life  = float txtEstimatedLife.Text

let numerator = subtract cost value
divide numerator life

let strDepreciation = sprintf "%0.02f" depreciation
txtDepreciation.Text <- strDepreciation

Application.Run depreciationSLM```

Here is an eample of running the program:

 The Signature of a Function

The signature of a function is a technique of indicating its arguments and its return type. The basic formula of a function signature is:

`function-name : parameter-type(s) -> return-type`

The signature starts with the name of the function. This is followed by a colon. If the function takes one argument, specify its type. This is followed by -> and the data type of the value the function returns. Here is an example:

`calculateSquareArea : float -> float`

This means that we are using a function named calculateSquareArea. The function takes one argument that is a decimal number. The function returns a decimal number.

Here is how to specify or read the signature of a function:

• If the function doesn't take any argument, in which case it may have empty parentheses, specify its parameter-type as unit. This would be done as follows:
`presentGreetings : unit -> return-type`
• If the function doesn't return a value, specify its return-type as unit. This would be done as follows:
`presentGreetings : parameter-type(s) -> unit`
• If the function takes more than one argument, in the parameter-type(s) placeholder, specify the data type of each argument but separate them with ->. Here is one example:
`calculateCylinderVolume : float -> float -> float`
This indicates that we have a function named calculateCylinderVolume. The function takes two arguments of type float. The function returns a floating-point number. Here another example:
`showStudentRecord : string -> int -> unit`
This indicates that we have a function named showStudentRecord. The function takes two arguments. The first argument is a string. The second argument is a character. The function doesn't return a known value
 A Variable as a Function

When you assign a lambda expression to a variable, the variable becomes a function, or you can use this characteristic to declare a variable and assign a lambda expression to it without specifying the that will be processed. Here is an example:

``` let grossSalary = (fun units ->
if units <= 100.00 then units * 2.25
elif units <= 250.00 then
let first100 = 100.00 * 2.45
let others = (units - 100.00) * 2.25
first100 + others
else
let first100 = 100.00 * 2.25
let between100And250 = 150.00 * 2.45
let others = (units - 250.00) * 2.68
first100 + between100And250 + others)```

To treat the variable as a function, assign it to another variable and pass the appropriate value(s), the same way it would be done when calling a normal function. Here is an example:

```let btnCalculateClick(e) =
let items = float txtUnits.Text

let grossSalary = (fun units ->
if units <= 100.00 then units * 2.25
elif units <= 250.00 then
let first100 = 100.00 * 2.45
let others = (units - 100.00) * 2.25
first100 + others
else
let first100 = 100.00 * 2.25
let between100And250 = 150.00 * 2.45
let others = (units - 250.00) * 2.68
first100 + between100And250 + others)

let wages = grossSalary items
txtGrossSalary.Text <- sprintf "%0.02f" wages```

In the same way, if the lambda expression is made to process many values, pass them as arguments to the variable. Here are example:

```let btnCalculateClick(e) =
let weeklySales = float txtWeeklySales.Text
let commissionRate = float txtCommissionRate.Text

let commissionAmount = fun x y -> x * y / 100.00
let payment = commissionAmount weeklySales commissionRate

let strCommissionAmount = sprintf "%0.02f" payment
txtCommissionAmount.Text <- strCommissionAmount```

Another option is to create the lambda expression where it is needed. In this case, the expression must be included in parentheses. Here is an example:

```let btnCalculateClick(e) =
let items = float txtUnits.Text

txtGrossSalary.Text <- sprintf "%0.02f" ((fun units ->
if units <= 100.00 then units * 2.25
elif units <= 250.00 then
let first100 = 100.00 * 2.45
let others = (units - 100.00) * 2.25
first100 + others
else
let first100 = 100.00 * 2.25
let between100And250 = 150.00 * 2.45
let others = (units - 250.00) * 2.68
first100 + between100And250 + others) items)```

Or like this:

```let btnCalculateClick e =
let weeklySales = float txtWeeklySales.Text
let commissionRate = float txtCommissionRate.Text

let strCommissionAmount = sprintf "%0.02f" ((fun x y -> x * y / 100.00) weeklySales commissionRate)
txtCommissionAmount.Text <- strCommissionAmount```

Or like this:

```let btnCalculateClick(e) =
let strCommissionAmount = sprintf "%0.02f" ((fun x y -> x * y / 100.00) (float txtWeeklySales.Text) (float txtCommissionRate.Text))
txtCommissionAmount.Text <- strCommissionAmount```

Or like this:

```let btnCalculateClick(e) =
txtCommissionAmount.Text <- (sprintf "%0.02f" ((fun x y -> x * y / 100.00) (float txtWeeklySales.Text) (float txtCommissionRate.Text)))```