Skip to content

Instantly share code, notes, and snippets.

@amatiasq
Created April 19, 2020 23:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save amatiasq/258e6aeb70065a05151b395d018a8fd4 to your computer and use it in GitHub Desktop.
Save amatiasq/258e6aeb70065a05151b395d018a8fd4 to your computer and use it in GitHub Desktop.
Created with Fable REPL
html, body {
margin: 0;
padding: 0;
background-color: black;
}
module Tour.Functions
// From https://docs.microsoft.com/en-us/dotnet/fsharp/tour
// Visit the link above for more information on each topic
// You can also find more learning resources at https://fsharp.org/
module BasicFunctions =
/// You use 'let' to define a function. This one accepts an integer argument and returns an integer.
/// Parentheses are optional for function arguments, except for when you use an explicit type annotation.
let sampleFunction1 x = x*x + 3
/// Apply the function, naming the function return result using 'let'.
/// The variable type is inferred from the function return type.
let result1 = sampleFunction1 4573
// This line uses '%d' to print the result as an integer. This is type-safe.
// If 'result1' were not of type 'int', then the line would fail to compile.
printfn "The result of squaring the integer 4573 and adding 3 is %d" result1
/// When needed, annotate the type of a parameter name using '(argument:type)'. Parentheses are required.
let sampleFunction2 (x:int) = 2*x*x - x/5 + 3
let result2 = sampleFunction2 (7 + 4)
printfn "The result of applying the 2nd sample function to (7 + 4) is %d" result2
/// Conditionals use if/then/elif/else.
///
/// Note that F# uses white space indentation-aware syntax, similar to languages like Python.
let sampleFunction3 x =
if x < 100.0 then
2.0*x*x - x/5.0 + 3.0
else
2.0*x*x + x/5.0 - 37.0
let result3 = sampleFunction3 (6.5 + 4.5)
// This line uses '%f' to print the result as a float. As with '%d' above, this is type-safe.
printfn "The result of applying the 2nd sample function to (6.5 + 4.5) is %f" result3
module Immutability =
/// Binding a value to a name via 'let' makes it immutable.
///
/// The second line of code fails to compile because 'number' is immutable and bound.
/// Re-defining 'number' to be a different value is not allowed in F#.
let number = 2
// let number = 3
/// A mutable binding. This is required to be able to mutate the value of 'otherNumber'.
let mutable otherNumber = 2
printfn "'otherNumber' is %d" otherNumber
// When mutating a value, use '<-' to assign a new value.
//
// Note that '=' is not the same as this. '=' is used to test equality.
otherNumber <- otherNumber + 1
printfn "'otherNumber' changed to be %d" otherNumber
module PipelinesAndComposition =
/// Squares a value.
let square x = x * x
/// Adds 1 to a value.
let addOne x = x + 1
/// Tests if an integer value is odd via modulo.
let isOdd x = x % 2 <> 0
/// A list of 5 numbers. More on lists later.
let numbers = [ 1; 2; 3; 4; 5 ]
/// Given a list of integers, it filters out the even numbers,
/// squares the resulting odds, and adds 1 to the squared odds.
let squareOddValuesAndAddOne values =
let odds = List.filter isOdd values
let squares = List.map square odds
let result = List.map addOne squares
result
printfn "processing %A through 'squareOddValuesAndAddOne' produces: %A" numbers (squareOddValuesAndAddOne numbers)
/// A shorter way to write 'squareOddValuesAndAddOne' is to nest each
/// sub-result into the function calls themselves.
///
/// This makes the function much shorter, but it's difficult to see the
/// order in which the data is processed.
let squareOddValuesAndAddOneNested values =
List.map addOne (List.map square (List.filter isOdd values))
printfn "processing %A through 'squareOddValuesAndAddOneNested' produces: %A" numbers (squareOddValuesAndAddOneNested numbers)
/// A preferred way to write 'squareOddValuesAndAddOne' is to use F# pipe operators.
/// This allows you to avoid creating intermediate results, but is much more readable
/// than nesting function calls like 'squareOddValuesAndAddOneNested'
let squareOddValuesAndAddOnePipeline values =
values
|> List.filter isOdd
|> List.map square
|> List.map addOne
printfn "processing %A through 'squareOddValuesAndAddOnePipeline' produces: %A" numbers (squareOddValuesAndAddOnePipeline numbers)
/// You can shorten 'squareOddValuesAndAddOnePipeline' by moving the second `List.map` call
/// into the first, using a Lambda Function.
///
/// Note that pipelines are also being used inside the lambda function. F# pipe operators
/// can be used for single values as well. This makes them very powerful for processing data.
let squareOddValuesAndAddOneShorterPipeline values =
values
|> List.filter isOdd
|> List.map(fun x -> x |> square |> addOne)
printfn "processing %A through 'squareOddValuesAndAddOneShorterPipeline' produces: %A" numbers (squareOddValuesAndAddOneShorterPipeline numbers)
module RecursiveFunctions =
/// This example shows a recursive function that computes the factorial of an
/// integer. It uses 'let rec' to define a recursive function.
let rec factorial n =
if n = 0 then 1 else n * factorial (n-1)
printfn "Factorial of 6 is: %d" (factorial 6)
/// Computes the greatest common factor of two integers.
///
/// Since all of the recursive calls are tail calls,
/// the compiler will turn the function into a loop,
/// which improves performance and reduces memory consumption.
let rec greatestCommonFactor a b =
if a = 0 then b
elif a < b then greatestCommonFactor a (b - a)
else greatestCommonFactor (a - b) b
printfn "The Greatest Common Factor of 300 and 620 is %d" (greatestCommonFactor 300 620)
/// This example computes the sum of a list of integers using recursion.
let rec sumList xs =
match xs with
| [] -> 0
| y::ys -> y + sumList ys
/// This makes 'sumList' tail recursive, using a helper function with a result accumulator.
let rec private sumListTailRecHelper accumulator xs =
match xs with
| [] -> accumulator
| y::ys -> sumListTailRecHelper (accumulator+y) ys
/// This invokes the tail recursive helper function, providing '0' as a seed accumulator.
/// An approach like this is common in F#.
let sumListTailRecursive xs = sumListTailRecHelper 0 xs
let oneThroughTen = [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
printfn "The sum 1-10 is %d" (sumListTailRecursive oneThroughTen)
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
</head>
<body>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment