Believe it or not but the following is actual Julia code which generates Fibonacci numbers:

```
julia> (n->((l->[l[2],l/+])^n)(0:1)[1]).(1:10)
10-element Array{Int64,1}:
1
1
2
3
5
8
13
21
34
55
```

Julia 0.6 introduced the new ∘ (\circ) function composition operator. It currcntly has one method:

```
julia> methods(∘)
# 1 method for generic function "∘":
∘(f, g) in Base at operators.jl:884
```

which has a rather straightforward definition:

`∘(f,g) = (x...)->f(g(x...))`

It takes functions `f`

and `g`

and *composes* them in the following way:

`(f∘g)(x) == (f(g(x)))`

For example

```
julia> sin(cos(2))
-0.4042391538522658
julia> (sin∘cos)(2)
-0.4042391538522658
julia> (sin∘cos∘log)(2)
0.6955886362231636
julia> sin(cos(log(2)))
0.6955886362231636
```

The operator provides a nice way of creating anonymous functions for broadcasting across arrays:

```
julia> map(reverse∘string, 230:240)
11-element Array{String,1}:
"032"
"132"
"232"
"332"
"432"
"532"
"632"
"732"
"832"
"932"
"042"
```

Ultimately, the ∘ operator is a great demonstration of Julia's flexibility as a language. Which leads to the question: What else can we do with Julia's operators?

For starters, it may be nice to be able to compose functions and arguments so that `(arg∘f)(x)`

is equivalent to `f(arg,x)`

. For example, the following does not work:

```
julia> map(10∘(-), 1:3)
ERROR: MethodError: objects of type Int64 are not callable
Stacktrace:
[1] _collect(::UnitRange{Int64}, ::Base.Generator{UnitRange{Int64},Base.##55#56{Int64,Base.#-}}, ::Base.EltypeUnknown, ::Base.HasShape) at ./array.jl:454
[2] map(::Function, ::UnitRange{Int64}) at ./abstractarray.jl:1865
```

However, thanks to Julia's overloading abilities, we can make it work ourselves. Here we define both `arg∘f`

and `f∘arg`

:

```
julia> import Base.∘
julia> (∘)(f::Function, arg) = (x...)->f(x...,arg)
∘ (generic function with 2 methods)
julia> (∘)(arg, f::Function) = (x...)->f(arg,x...)
∘ (generic function with 3 methods)
```

```
julia> map(10∘(-), 1:3)
3-element Array{Int64,1}:
9
8
7
julia> map((-)∘10, 1:3)
3-element Array{Int64,1}:
-9
-8
-7
```

We can now define some simple functions very easily:

```
julia> my_log2 = 2∘log
(::#7) (generic function with 1 method)
julia> my_log2(10)
3.3219280948873626
julia> log2(10) # Julia built-in
3.321928094887362
```

This is great but we created an additional problem. Our old code no longer works!

```
julia> (sin∘cos)(3)
ERROR: MethodError: ∘(::Base.#sin, ::Base.#cos) is ambiguous. Candidates:
∘(arg, f::Function) in Main at REPL[32]:1
∘(f::Function, arg) in Main at REPL[31]:1
Possible fix, define
∘(::Function, ::Function)
```

Julia doesn't know which of our functions to call. Since both `arg`

and `f`

are of type `Function`

(`typeof(sin) <: Funtion == true`

and `typeof(cos) <: Function == true`

), it doesn't know which to use as `f::Function`

and which to use as `args::Any`

. In fact, we don't want it to use either, we want it to use the original definition if both arguments are functions. Luckily, this is a very easy fix in Julia. We can define a specialized version of the original definition like so:

```
julia> ∘(f::Function, g::Function) = (x...)->f(g(x...))
∘ (generic function with 4 methods)
```

Notice that this definition is exactly the same as the one above except that it includes specific types for its arguments `f`

and `g`

. Julia is now able to choose the proper function:

```
julia> (sin∘cos)(3)
-0.8360218615377305
```

Another way we can abuse- *ahem* demonstrate Julia's flexibility with operators is to use them to perform common complex operations, for example, here we define the `/`

operator to run `fold`

on a single dimensional list:

```
julia> import Base./
julia> /{T}(l::AbstractArray{T,1}, f::Function) = foldr(f,l)
/ (generic function with 74 methods)
```

Which can be used in the following way:

```
julia> foldr(+, [1,2,3])
6
julia> [1,2,3]/+
6
```

Or perhaps we want the `^`

operator to *repeat* a function:

```
julia> import Base.^
julia> function ^(f::Function, iters::Int)
fn = f
for i in 1:(iters-1)
fn = fn ∘ f
end
fn
end
^ (generic function with 53 methods)
```

Which allows the following:

```
julia> sin(sin(2))
0.7890723435728884
julia> (sin^2)(2)
0.7890723435728884
```

Gauss would be proud.

Lets use our new operators to generate Fibonacci numbers. The first few terms of this sequence are the following:

`0,1,1,2,3,5,8,13,21,34,55,...`

The recursive definition for this sequence is:

Lets say we have an array containing two adjacent numbers in the sequence:

`julia> x = [8,13]`

In order to generate the next Fibonacci number, we simply add the two items together.

```
julia> x[1] + x[2]
21
```

If we want to continue generating the next Fibonacci number, we will also need to save the previous one:

```
julia> next_x = [x[2], x[1] + x[2]]
[13,21]
```

Or equivalently, using our `/`

operator to add `l[1]`

and `l[2]`

:

```
julia> next_x = [x[2], x/+]
2-element Array{Int64,1}:
13
21
```

Lets define a function so we can easily generate Fibonacci numbers:

```
julia> next_fib(x) = [x[2], x/+]
next_fib (generic function with 1 method)
julia> x = next_fib([8,13])
2-element Array{Int64,1}:
13
21
julia> x = next_fib(x)
2-element Array{Int64,1}:
21
34
julia> x = next_fib(x)
2-element Array{Int64,1}:
34
55
```

We can generate the `n`

th Fibonacci number if we start at the first two Fibonacci numbers `[0,1]`

and run the function `n-1`

times:

```
julia> function fib(n)
x = [0,1]
for i in 1:n-1
x = next_fib(x)
end
return x[2]
end
fib (generic function with 1 method)
julia> fib(10)
55
```

Or equivalently, using our `^`

operator:

```
julia> fib(n) = (next_fib^(n-1))([0,1])[2]
fib (generic function with 1 method)
julia> fib(10)
55
```

Now we can swap out `next_fib`

for it's definition:

```
julia> fib(n) = ((l -> [l[2], l/+])^(n-1))([0, 1])[2]
fib (generic function with 1 method)
```

And finally, to make the code a little more concise (why not?) we use `0:1`

instead of `[0,1]`

and index the first element of the `n`

th list instead of the second element of the `n-1`

th list.

```
julia> fib(n) = ((l->[l[2],l/+])^n)(0:1)[1]
fib (generic function with 1 method)
julia> fib(10)
55
julia> fib.(1:10)
10-element Array{Int64,1}:
1
1
2
3
5
8
13
21
34
55
```