Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

2. Functions, currying, and pipes

A function in Pyfun is a let binding with parameters before the =. In Python you would write def add(a, b): return a + b. Pyfun writes the parameters inline and the body is the expression after =. Calls leave off the parentheses and commas: you write add 1 2, not add(1, 2).

let add a b = a + b

let inc = add 1

let double x = x * 2

let result = 5 |> inc |> double

print (add 2 3)
print (inc 10)
print result

Running this prints:

5
11
12

Two things there are new. First, add 1 is a call with one argument to a two-argument function. Instead of an error, it produces a new function that is waiting for the second argument. That is currying: every function takes its arguments one at a time, so a partial call like add 1 hands you back a function. Here inc adds one to whatever you give it.

Second, 5 |> inc |> double is a pipeline. The pipe |> takes the value on its left and feeds it to the function on its right, so you read it left to right as “start with 5, then inc, then double.” In Python you would nest the calls as double(inc(5)), which reads inside out. The pipe keeps the order of operations the same as the order you read.

None of this adds a runtime layer. A fully applied call compiles straight to a normal Python call, and the pipeline unwinds to plain nesting:

import functools
def add(a, b):
    return a + b
inc = functools.partial(add, 1)
def double(x):
    return x * 2
result = double(inc(5))

Currying shows up only where you actually leave an argument off: inc becomes a functools.partial. Everything else is ordinary Python. When you want to name a pipeline without a starting value, >> composes two functions into one, left to right, so inc >> double is the function that runs inc and then double.

Exercise

Finish the pipeline. The value 3 flows through double, then through one more stage. Run pyfun check and the compiler tells you the hole wants a function from int. Put the stage that makes the result 18.

let double x = x + x
let triple x = x + x + x

let result = 3 |> double |> ?stage
print result

Expected output:

18

Open in the playground

Show solution
let double x = x + x
let triple x = x + x + x

let result = 3 |> double |> triple
print result

double 3 is 6, and triple 6 is 18. The stage is just the next function in the chain.