Technically, Ruby doesn't have functions, but methods. However, a Ruby method behaves almost identically to functions in other language:

```
def double(n)
n * 2
end
```

This normal method/function takes a parameter `n`

, doubles it and returns the value. Now let's define a higher order function (or method):

```
def triple(n)
lambda {3 * n}
end
```

Instead of returning a number, `triple`

returns a method. You can test it using the Interactive Ruby Shell:

```
$ irb --simple-prompt
>> def double(n)
>> n * 2
>> end
=> :double
>> def triple(n)
>> lambda {3 * n}
>> end
=> :triple
>> double(2)
=> 4
>> triple(2)
=> #<Proc:0x007fd07f07bdc0@(irb):7 (lambda)>
```

If you want to actually get the tripled number, you need to call (or "reduce") the lambda:

```
triple_two = triple(2)
triple_two.call # => 6
```

Or more concisely:

```
triple(2).call
```

This is not useful in terms of defining very basic functionality, but it is useful if you want to have methods/functions that are not instantly called or reduced. For example, let's say you want to define methods that add a number by a specific number (for example `add_one(2) = 3`

). If you had to define a ton of these you could do:

```
def add_one(n)
n + 1
end
def add_two(n)
n + 2
end
```

However, you could also do this:

```
add = -> (a, b) { a + b }
add_one = add.curry.(1)
add_two = add.curry.(2)
```

Using lambda calculus we can say that `add`

is `(λa.(λb.(a+b)))`

. Currying is a way of *partially applying* `add`

. So `add.curry.(1)`

, is `(λa.(λb.(a+b)))(1)`

which can be reduced to `(λb.(1+b))`

. Partial application means that we passed one argument to `add`

but left the other argument to be supplied later. The output is a specialized method.

Let's say we have really big general formula, that if we specify certain arguments to it, we can get specific formulae from it. Consider this formula:

```
f(x, y, z) = sin(x\*y)*sin(y\*z)*sin(z\*x)
```

This formula is made for working in three dimensions, but let's say we only want this formula with regards to y and z. Let's also say that to ignore x, we want to set it's value to pi/2. Let's first make the general formula:

```
f = ->(x, y, z) {Math.sin(x*y) * Math.sin(y*z) * Math.sin(z*x)}
```

Now, let's use currying to get our `yz`

formula:

```
f_yz = f.curry.(Math::PI/2)
```

Then to call the lambda stored in `f_yz`

:

```
f_xy.call(some_value_x, some_value_y)
```

This is pretty simple, but let's say we want to get the formula for `xz`

. How can we set `y`

to `Math::PI/2`

if it's not the last argument? Well, it's a bit more complicated:

```
f_xz = -> (x,z) {f.curry.(x, Math::PI/2, z)}
```

In this case, we need to provide placeholders for the parameter we aren't pre-filling. For consistency we could write `f_xy`

like this:

```
f_xy = -> (x,y) {f.curry.(x, y, Math::PI/2)}
```

Here's how the lambda calculus works for `f_yz`

:

```
f = (λx.(λy.(λz.(sin(x*y) * sin(y*z) * sin(z*x))))
f_yz = (λx.(λy.(λz.(sin(x*y) * sin(y*z) * sin(z*x)))) (π/2) # Reduce =>
f_yz = (λy.(λz.(sin((π/2)*y) * sin(y*z) * sin(z*(π/2))))
```

Now let's look at `f_xz`

```
f = (λx.(λy.(λz.(sin(x*y) * sin(y*z) * sin(z*x))))
f_xz = (λx.(λy.(λz.(sin(x*y) * sin(y*z) * sin(z*x)))) (λt.t) (π/2) # Reduce =>
f_xz = (λt.(λz.(sin(t*(π/2)) * sin((π/2)*z) * sin(z*t))))
```

For more reading about lambda calculus try this.