DEV Community

Cover image for F# For Dummys - Day 8 Function && Pipeline
AllenZhu
AllenZhu

Posted on • Edited on

F# For Dummys - Day 8 Function && Pipeline

Today we learn how to define a function and pipeline

what is function

function is a block of code that takes input values (parameters), and returns an output value
normally we perform some task with the input, it will be less useful just return the input value

  • funtion no param input:
let say_hello() = "Hello"
printfn "say_hello: %s" (say_hello())
Enter fullscreen mode Exit fullscreen mode
  • funtion one param input
let say_hello_to name = "Hello " + name
printfn "say_hello_to: %s" (say_hello_to "Lucy")
Enter fullscreen mode Exit fullscreen mode
  • funtion two param input
let say_hello_to name0 name1 = name0 + " say Hello to " + name1
printfn "say_hello_to: %s" (say_hello_to "Lucy" "Lily")
Enter fullscreen mode Exit fullscreen mode
  • function can be a param of other function
let applyTwice f x = f (f x)
let increment x = x + 1
let result = applyTwice increment 5

printfn "Result: %d" result
Enter fullscreen mode Exit fullscreen mode

increment is the first param of function applyTwice here, it's increment(increment(x)), result is (5 + 1) + 1 = 7

lambda

lambda expression is an anonymous function (a function without a name) that you can define in place, often to be passed as an argument to higher-order functions
syntax of a lambda expression

fun arguments -> expression
Enter fullscreen mode Exit fullscreen mode

a simple add function

let add x y = 
    x + y
printfn "%d" (add 3 5)  // Output: 8
Enter fullscreen mode Exit fullscreen mode

a lambda version

printfn "%d" ((fun x y -> x + y) 3 5)  // Output: 8
Enter fullscreen mode Exit fullscreen mode

you can not use this fun at other place as it Dispose after finish

pipeline

  • forward pipeline |>, data flow from left to right

we can combine multiple functions one after one
function1 |> function2 |> function3, it's called pipeline
the function param example could be like this:

let applyTwice f x = f x |> f
let increment x = x + 1
let result = applyTwice increment 5

printfn "Result: %d" result
Enter fullscreen mode Exit fullscreen mode

another longer pipeline

let addOne x = x + 1
let square x = x * x
let subtractFive x = x - 5

let result = 5 |> addOne |> square |> subtractFive // (5 + 1)^2 - 5
printfn "The result is %d" result // output: The result is 31
Enter fullscreen mode Exit fullscreen mode

the output of first function is the input of next function
result = 5 |> addOne, addOne get 5, return 5 + 1 = 6, square get 6, return 6 * 6 = 36, substractFive get 36, return 36 -5 = 31

  • <| backward pipeline, data flow from right to left
let addOne x = x + 1
let square x = x * x
let subtractFive x = x - 5

let result = subtractFive <| (square <| (addOne 5))
printfn "The result is %d" result // output: The result is 31
Enter fullscreen mode Exit fullscreen mode

why pipeline

an example for morning routine

let getOutOfBed () = "Out of bed"
let brushTeeth state = state + " -> Brushed teeth"
let takeShower state = state + " -> Took shower"
let getDressed state = state + " -> Got dressed"
let eatBreakfast state = state + " -> Ate breakfast"

let morningRoutine =
    getOutOfBed ()
    |> brushTeeth
    |> takeShower
    |> getDressed
    |> eatBreakfast

printfn "Morning routine completed: %s" morningRoutine // output: Morning routine completed: Out of bed -> Brushed teeth -> Took shower -> Got dressed -> Ate breakfast
Enter fullscreen mode Exit fullscreen mode

there is an equivalent way to get the same result, which is nested function calls

let getOutOfBed () = "Out of bed"
let brushTeeth state = state + " -> Brushed teeth"
let takeShower state = state + " -> Took shower"
let getDressed state = state + " -> Got dressed"
let eatBreakfast state = state + " -> Ate breakfast"

let morningRoutine = eatBreakfast(getDressed(takeShower(brushTeeth(getOutOfBed()))))
printfn "Morning routine completed: %s" morningRoutine
Enter fullscreen mode Exit fullscreen mode

the last function eatBreakfast is put in the first place
which way do you prefer
we can see the pipeline way is more readable in this style:

  • The order of operations is written in a natural, top-to-bottom manner, which is easier to read and understand
  • It is more intuitive because it reads like a sequence of steps or instructions
  • Adding or removing steps is straightforward, you just add or remove lines
  • Each function operates on the result of the previous function, clearly showing the flow of data

pipeline way is recommended in F#, the data flows in pipeline, elegant!

Top comments (0)