This is one of the 100 recipes of the IPython Cookbook, the definitive guide to high-performance scientific computing and data science in Python.

For this recipe, you need to install Julia and IJulia. You'll find the installation instructions in the book.

- We can't avoid the customary
*Hello World*example. The`println()`

function displays a string and adds a line break at the end.

In [ ]:

```
println("Hello world!")
```

- We create a polymorphic function
`f`

that computes the expression $z*z+c$. We will notably evaluate this function on arrays, so we use elementwise operators with a dot (`.`

) prefix.

In [ ]:

```
f(z, c) = z.*z .+ c
```

- Let's evaluate
`f`

on scalar complex numbers (the imaginary number $i$ is`1im`

).

In [ ]:

```
f(2.0 + 1.0im, 1.0)
```

- Now, we create a
`(2, 2)`

matrix. Components are separated by a space, rows are separated by a semicolon (`;`

). The type of this`Array`

is automatically inferred from its components. The`Array`

type is a built-in data type in Julia, similar, but not identical, to NumPy's`ndarray`

type.

In [ ]:

```
z = [-1.0 - 1.0im 1.0 - 1.0im;
-1.0 + 1.0im 1.0 + 1.0im]
```

- We can index arrays with brackets
`[]`

. A notable difference with Python is that indexing starts from 1 instead of 0. MATLAB has the same convention. Besides, the keyword`end`

refers to the last item in that dimension.

In [ ]:

```
z[1,end]
```

- We can evaluate
`f`

on the matrix`z`

and a scalar`c`

(polymorphism).

In [ ]:

```
f(z, 0)
```

- Now, we create a function
`julia`

that computes a Julia set. Optional named arguments are separated from positional arguments by a semicolon (`;`

). Julia's syntax for flow control is close from Python's, except that colons are dropped, indentation doesn't count, and block`end`

keywords are mandatory.

In [ ]:

```
function julia(z, c; maxiter=200)
for n = 1:maxiter
if abs2(z) > 4.0
return n-1
end
z = f(z, c)
end
return maxiter
end
```

- We can use Python packages from Julia. First, we have to install the
`PyCall`

package by using Julia's built-in package manager (`Pkg`

). Once the package is installed, we can use it in the interactive session with`using PyCall`

.

In [ ]:

```
Pkg.add("PyCall")
using PyCall
```

- We can import Python packages with the
`@pyimport`

**macro**(a metaprogramming feature in Julia). This macro is the equivalent of Python's`import`

command.

In [ ]:

```
@pyimport numpy as np
```

- The
`np`

namespace is now available in the Julia interactive session. NumPy arrays are automatically converted to Julia`Array`

s.

In [ ]:

```
z = np.linspace(-1., 1., 100)
```

- We can use list comprehensions to evaluate the function
`julia`

on many arguments.

In [ ]:

```
m = [julia(z[i], 0.5) for i=1:100]
```

- Let's try the Gadfly plotting package. This library offers a high-level plotting interface inspired by Grammar of Graphics. In the notebook, plots are interactive thanks to the
**d3.js**library.

In [ ]:

```
Pkg.add("Gadfly")
using Gadfly
```

In [ ]:

```
plot(x=1:100, y=m, Geom.point, Geom.line)
```

- Now, we compute a Julia set by using two nested loops. In general, and unlike Python, there is no significant performance penalty using
`for`

loops instead of vectorized operations in Julia. High-performance code can be written either with vectorized operations or`for`

loops.

In [ ]:

```
@time m = [julia(complex(r, i), complex(-0.06, 0.67))
for i = 1:-.001:-1,
r = -1.5:.001:1.5];
```

- Finally, we use the
`PyPlot`

package to draw matplotlib figures in Julia.

In [ ]:

```
Pkg.add("PyPlot")
using PyPlot
```

In [ ]:

```
imshow(m, cmap="RdGy",
extent=[-1.5, 1.5, -1, 1]);
```

You'll find all the explanations, figures, references, and much more in the book (to be released later this summer).

IPython Cookbook, by Cyrille Rossant, Packt Publishing, 2014 (500 pages).