# Introduction

The Julia programming language is easy to use, fast, and powerful. This wikibook is intended as an introduction to the language for the less experienced and occasional programmer. For more learning materials, including links to books, videos, articles/blogs and notebooks, refer to the learning section at Julia's official site.
The official Julia documentation is the authoritative guide, and you should refer to it as often as possible as you learn. It's the "reference" guide both for the langugage itself and for the set of standard packages (the "standard library") that are provided as part of the basic installation.
A feature of Julia is the extensive use of add-on packages to add functionality and features, and to extend the syntax of built-in functions. Good places to look for packages (which are mostly free to download from github.com) include the JuliaHub and the Julia Packages sites. Packages provide their own documentation and many provide extensive tutorials.
The Julia community has established a good ethos of encouraging participation in the development of the language on github. The advantage of this wikibook is that it's made and edited by the Julia community – you can edit anything at any time. If you find something that's wrong, or unclear, feel free to correct it, or add examples. (Your first few edits are reviewed, just in case you have less than good intentions. And, as with the Wikipedia, you should expect your writing to be edited by others!) The focus should be largely on the new user, rather than the computer science expert.

## External links

* The Julia manual – the official rulebook: current and in-development documentation is available here.
* The JuliaLang Discourse - the main Julia programming language discussion forum
* JuliaHub – a Julia Computing service that includes search of all registered open source package documentation, code search, and navigation by tags/keywords. It is powered by Julia Team.
* JuliaPackages – see what packages are popular and/or trending, navigate by package categories.
* Julia.jl – a manually curated taxonomy of Julia packages
* A Month of Julia – 38 blog posts about using Julia.

# Getting started

To install Julia on your computer, visit http://julialang.org/downloads/ and follow instructions. You can then run the Julia interpreter using a terminal app on your computer. This is known as using the REPL.
Alternatively, you can use Julia online, in your browser, at sites such as NextJournal and Repl.it.
If you’d prefer to work locally, you can also use free but more powerful (and complicated) software packages such as Juno (based on Atom) and VisualStudio Code. Another popular way to run Julia is from a Jupyter notebook, via the IJulia.jl package. Jupyter is the interactive notebook technology that lets you run code in Julia, Python, and R in a browser window. Setting these up for working with Julia is usually straightforward, but you’ll probably have to follow a list of instructions carefully. The simplest way to start is to fire up the REPL.

## On macOS

On a Mac, you download the Julia DMG, double-click to open it, and drag the icon to the Applications folder. To run Julia, you can double-click the icon of the Julia package in the /Applications folder. This opens the terminal application, and starts a new window. This is the REPL, introduced in the next section:
Alternatively, you can type, in a terminal, something like this:
Here you’re specifying the path name of the Julia binary executable that lives inside the Julia application bundle. The exact version name might be different — check it using this command, which shows all available versions:

### Running directly from terminal

Typically, Julia is installed in /Applications, which isn't included in your PATH, and so the shell can't find it when you type julia on the command line.
But there are clever things you can do with paths and profiles, so that you can log in to a terminal and type julia with immediate success.
For example, after you find out the location of the Julia binary executable file (see above), you can define the following alias:
Obviously this will have to be updated every time the version number changes.
As an alternative, you could add the /Applications/Julia... path to the PATH variable (the mechanism that the OS uses to find executable programs on your system):
A different approach is to create a link to the executable and put it into the /usr/local/bin directory (which should already be in your path), so that typing julia is the exact equivalent of typing /Applications/Julia/.../julia. This command does that:
Whichever method you choose, you can add the relevant command to your ~/.bash_profile or ~/.zprofile files, which run every time you start a new shell.
You can add the 'shebang' line at the top of a text file ('script') containing Julia code, so that the shell can find Julia and execute the file:
This also works in a lot of text editors, where you can choose Run to run the file. This works if the editor reads the user's environment variables before running the file. (But not all do!)

### Running a Julia program

If you have a text file containing Julia code, you can run it from the command line:
or from within the Julia REPL:
If the first line specifies a Julia interpreter:
or
you can run the file like this:

### Running a script with Julia

If you want to write Julia code in an editor and run it, in true scripting-language fashion, you can. At the top of the script file, add a line like the following:
where the pathname points to the right place on your system, somewhere inside the relevant Julia application bundle, or:
This is called the shebang line.
Now you can run the script from inside the editor in the same way that you'd run any other script, such as a shell or Perl script.

### Using Homebrew

If you're a fan of homebrew, you should be able to install Julia with:

## On Windows

On a Windows machine, you download the Julia Self-Extracting Archive (.exe) 32-bit or 64-bit. Double-click to start the installation process.
By default, it will install to your AppData folder. You may keep the default or choose your own directory (eg. C:\Julia).
After the installation has finished, you should create a System Environment variable called JULIA_HOME and set its value to the \bin directory under the folder where you installed Julia.
It is important to point JULIA_HOME to the /bin directory instead of the JULIA directory.
Then you can append ;%JULIA_HOME% to your PATH System Environment variable, so you can run scripts from any directory. Make sure that the registry key HKEY_CURRENT_USER\Environment\Path is of type REG_EXPAND_SZ, so %JULIA_HOME% gets expanded properly.

## On FreeBSD

To install Julia on FreeBSD (including TrueOS) or DragonFly BSD you can use either a binary package or using the ports system.

### Installing from package

Installing the Julia package is straightforward. Open up a terminal and type:
To remove the package again you can use:

### Installing from ports

If you have the ports collection installed on your system (you can do so using running the command portsnap auto) the following is the canonical way to compile and install Julia onto your system:

## On Linux
### Using Binaries

You can use Julia direct from the binaries, without installing it on your machine. This is useful if you have old Linux distributions or if you don't have administrator's access to the machine. Just download the binaries from the website, and extract to a directory. Go into this directory (using cd), then into the bin folder. Now type:
If the program doesn't have permission to run, use the following command to give this permission:
In principle, this method could be used on any Linux distribution.

#### A better setup

If you want to run it by just typing julia in the terminal, you can set it up as follows. We'll assume you've downloaded the binary and extracted it to the folder /home/user/julia13.
Do one or more of the following:
1: add the following line to your ~/.bashrc file:
(You'll have to re-run this file, either by restarting the terminal or using ~/.bashrc.
2: Add /home/user/julia13/bin/julia to your PATH environment variable.
3: Create a symlink to the julia executable to somewhere that is in PATH. For example:

### Installing from package

This is the easiest way to install Julia if you're using Linux distributions based on RedHat, Fedora, Debian or Ubuntu. To install, download the respective package from the website (or JuliaPro), and install using your favorite way (double-clicking on the package file usually works). After doing this, Julia will be availabe from command line. On a terminal you can do:

#### Arch Linux

On Arch Linux, Julia is available from community repository, and can be installed running:
To remove Julia package and it's dependencies (if not used by any other software on your system), you can run:

#### Void Linux

On Void Linux distributions, Julia is available from main repository, and can be installed running:

#### Fedora

On Fedora distributions, Julia is available from the updates repository (a default repository) and can be installed running:
To remove Julia package and its dependencies (again, if not used by other software on your system), you can run:
Note that this applies only to Fedora, downstream distributions such as RHEL or CentOS must check their own repositories to see if Julia is available.

### Running a script with Julia

To tell your operating system that it should run the script using Julia, you can use what is called the shebang syntax. To do this, just use the following line on the very top of your script:
With this as the first line of the script, the OS will search for "julia" on the path, and use it to run the script.

# The REPL
### The REPL

The julia program starts the interactive REPL, the Read/Evaluate/Print/Loop, by default. It lets you type expressions in Julia code and see the results of the evaluation printed on the screen immediately. It:
* Reads what you type;
* Evaluates it;
* Prints out the return value; then
* Loops back and does it all over again.
The REPL is a great place to start experimenting with the language. But it's not the best environment to do serious programming work of any scale – for that, a text editor, or interactive notebook environment (e.g. IJulia/Jupyter) is a better choice. But there are advantages to using the REPL: it's simple, and should work without any installation or configuration. There's a built-in help system, too.

#### Using the REPL

You type some Julia code and then press Return/Enter. Julia evaluates what you typed and returns the result:
If you're using the Jupyter (IPython) notebook, you probably have to type Control-Enter, or Shift-Enter.
If you don't want to see the result of the expression printed, use a semicolon at the end of the expression:
Also, if you want to access the value of the last expression you typed on the REPL, it's stored within the variable ans:
If you don't complete the expression on the first line, continue typing until you finish. For example:
now Julia waits patiently until you finish the expression:
and then you'll see the answer:

#### Help and searching for help

Type a question mark ?
and you'll immediately switch to Help mode, and the prompt changes to yellow (in the terminal):
Now you can type the name of something (function names should be written without parentheses):
Notice that the help system has tried to find all the words that match the letters you typed, and shows you what it found.
If you want to search the documentation, you can use apropos and a search string:
You'll see a list of functions whose names or descriptions contain the string.
and so on.

#### Shell mode

If you type a semicolon
you immediately switch to shell mode:
(And the prompt changes to red). The commands available within this mode are the ones used by your system's command-line shell. In shell mode you can type any shell (i.e., non-Julia) command and see the result:
How you leave shell mode depends on your Julia version:
* In Julia 1.6 and later, shell mode is "sticky" (persistent). Press Backspace as the first character, or CTRL+C, to go back to the julia> prompt
* In earlier Julia versions, the prompt switches immediately back to julia>, so you have to type a semicolon every time you want to give a shell command.

#### Package mode

If you type a right bracket as the first character:
you immediately switch to Package mode:
This is where you carry out package management tasks such as adding packages, testing them, and so on.
To leave package mode press Backspace or CTRL+C on an otherwise empty line.

#### Orientation

Here are some other useful interactive functions and macros available at the REPL-prompt:
* varinfo – prints information about the exported global variables in a module
* @which – tells you which method will be called for a function and particular arguments:
* versioninfo – gets Julia version and platform information:
There's also a quick way to find out the version:
* edit("pathname") – launch the default editor and open the file pathname for editing
* @edit rand – launch the default editor and open the file containing the definition of the built-in function rand
* less("filename-in-current-directory") – displays the file in the pager
* clipboard("stuff") – copies "stuff" to the system clipboard
* clipboard – pastes the contents of the clipboard into the current REPL line
* dump(x) – displays information about a Julia object x on the screen
* names(x) – gets an array of the names exported by the module x
* fieldnames(typeof(x)) – gets an array of the data fields that belong to a symbol of type x

#### The <TAB> key: autocompletion

The TAB key is usually able to complete – or suggest a completion for – something whose name you start typing. For example, if I type w and then press the TAB key (press twice when there are multiple options), all the functions that are currently available beginning with 'w' are listed:
This works both for Julia entities and in shell and package modes. Here, for example, is how I can navigate to a directory from inside Julia:
Remember you can get help about functions using ? and typing in its full name (or using TAB-completion).
TAB-completion also works for Unicode-symbols: eg type \alp and press TAB to get \alpha and then press TAB again to get α. And for Emoji: eg type \:fe and press TAB to get \:ferris_wheel: and then press TAB again to get 🎡.

#### History

You can look back through a record of your previous commands using the Up and Down arrow keys (and you can quit and restart without erasing that history). So you don't have to type a long multi-line expression again, because you can just recall it from history. And if you've typed loads of expressions, you can search through them, both back and forwards, by pressing Ctrl-R and Ctrl-S.

#### Fancy editing

Julia's REPL supports features that make command-line entry more efficient, and these features are bound to particular key combinations. For example, Alt+bgoes back one word, while Alt+fgoes forward one word. A complete list of key bindings, together with instructions for customizing them, can be found in the REPL documentation. Note that some editors, like VS Code, may override certain key combinations.

#### Scope and performance

One warning about the REPL. The REPL operates at the global scope level of Julia. Usually, when writing longer code, you would put your code inside a function, and organise functions into modules and packages. Julia's compiler works much more effectively when your code is organized into functions, and your code will run much faster as a result. There are also some things that you can't do at the top level – such as specify types for the values of variables.

#### Changing the prompt and customising your Julia session

The following Julia file runs every time you start up Julia (unless you use the startup-file=no option).
This lets you load any package that you know you are going to want later. For example, if you want to customise your REPL session automatically, you can install the Julia package OhMyREPL.jl (https://github.com/KristofferC/OhMyREPL.jl) which lets you customize the REPL's appearance and behaviour, then, in the startup file:
If you just want to set the prompt every time you start a Julia session, you could just add these instructions:
This just sets the current REPL prompt to show the Julia version number that your session is using.

### Julia and mathematics

You can use Julia as a powerful calculator, using the REPL. It's good practice, too. (This is a tradition in introductions to interactive programming languages, and it's a good way to meet the language.)

#### Typing numbers

Half the world uses a comma (,) to divide long numbers into groups of three, the other half uses a period (.). (And the rest of us use scientific notation...) In Julia you can use an underscore (_) to separate groups of digits:
although you won't see one in the response.
To use scientific notation, just type "e" (or "E") and don't add any spaces:
To type imaginary numbers, use im:

#### Operators as functions

An equivalent form for adding numbers is:
The operators that you usually use between values are ordinary Julia functions, and can be used in the same way as other functions. Similarly:
can be written as
and
can be written as
Some maths constants are provided:
You can find other maths constants in the MathConstants module:
All the usual operators are available:
Notice the precedence of the operators. In this case it's:
If you want to check the precedence of operators, enclose the expression in :( and ):
(More on this in Metaprogramming).
Multiplication is usually written *, but this can be omitted when multiplying a variable by a number literal:
This makes equations much easier to write.
You'll sometimes need parentheses to control the evaluation order:
Some others to watch out for include:
* ^ power
* % remainder
To make rational numbers, use two slashes (//):
Technically, / means "right division." There's also left division "\". For numbers, x/y = y\x. However, for vectors and matrices, x = A\y solves A*x = y and x = y/A solves x*A = y.
The standard arithmetic operators also have special updating versions, which you can use to update variables quickly:
For example, after defining a variable x:
you can add 2 to it:
then multiply it by 100:
and then reduce it to its modulus 11 value:
There are element-wise operators which work on arrays. This means that you can multiply two arrays element by element:
Arrays are fundamental to Julia, and so have their own chapter in this book.
If you divide two integers using /, the answer is always a floating-point number. If you've used Python version 2, you'll remember that Python returns an integer result. Python (3) returns a float now.
Julia offers an integer division operator ÷ (type \div TAB, or use the function version div. This should be used when you want an integer result rather than the floating-point returned by /.
Notice that Julia doesn't convert the answer to an integer type, even if the result is effectively an integer.
This is to avoid type instability problems, which can slow down your code.

#### Integer overflow

If you think your calculations are going to burst out of the 64-bit restriction, choose Big Integers by applying the big function to store the operands as big numbers:
To get the fastest execution speeds for your Julia programs, you should be aware of how your data and variables can be stored without introducing 'type instability'.

#### Number bases

These handy utility functions might come in useful when using the REPL as a calculator.
The bitstring function shows the literal binary representation of a number, as stored:
Notice that the floating point 'version' is, as you would expect, stored differently.
To go from a binary string back to decimal, you can use parse, which accepts a target type and number base:
For working in number bases other than the default 10, use the string function to convert integers to strings:
Whereas digits(number, base=b) returns an array of the digits of number in the given base:

#### Variables

In this expression:
x is a variable, a named storage location for a data object. In Julia, variables can be named pretty much how you like, although don't start variable names with numbers or punctuation. You can use Unicode characters, if you want.
To assign a value, use a single equals sign.
To test equality, you should use the == operator or isequal function.
In Julia, you can also assign multiple variables at the same time:
Notice that the return value of this expression is a parenthesis-bounded comma-separated ordered list of elements: tuple for short.

##### Multiplying numbers and variables

It's worth repeating that you can preface a variable name with a number to multiply them, without having to use an asterisk (*). For example:

#### Special characters

The Julia REPL provides easy access to special characters, such as Greek alphabetic characters, subscripts, and special maths symbols. If you type a backslash, you can then type a string (usually the equivalent LATEX string) to insert the corresponding character. For example, if you type:
Julia replaces the \sqrt with a square root symbol:
Some other examples:
| \pi | π |
| \Gamma | Γ |
| \mercury | ☿ |
| \degree | ° |
| \cdot | ⋅ |
| \in | ∈ |
There's a full list in the Julia source code. As a general principle, in Julia you're encouraged to look at the source code, so there are useful built-in functions for looking at Julia source files. For example, on macOS these symbols are stored in:
less runs the file through a pager (ie the less command in Unix). If you're brave, try using edit rather than less. This launches an editor and opens the file.
It's also possible to use Emoji and other Unicode characters in the REPL.
For emoji, type the Emoji character name, between colons, after the backslash, then press <TAB>:
which changes to:
You can find a list at https://docs.julialang.org/en/latest/manual/unicode-input/#Unicode-Input-1.
Entering Unicode symbols that aren't in this list is possible but more OS-dependent: on macOS you 'hold down' the Ctrl/Alt key while typing the Unicode hex digits (with the Unicode Hex Input keyboard enabled); on Windows it's Ctrl+Shift+u followed by the hex digits.)

#### Maths functions

Because Julia is particularly suited for scientific and technical computing, there are many mathematical functions that you can use immediately, and you often don't have to import them or use prefixes – they're already available.
The trigonometry functions expect values in radians:
but there are degree-based versions too: sind(90) finds the sine of 90 degrees. Use deg2rad and rad2deg to convert between degrees and radians.
There are also lots of log functions:
and the accurate hypot function:
The norm function (after loading via "using LinearAlgebra") returns the "p"-norm of a vector or the operator norm of a matrix. Here's divrem:
There are dozens of others.
There's a system-wide variable called ans that remembers the most recent result, so that you can use it in the next expression.

##### Exercise

Guess, then find out using the help system, what mod2pi and isapprox do.
Descriptions of all the functions provided as standard with Julia are described here:

#### Random numbers

rand – gets one random Float64 between 0 and 1
rand(2, 2) – an array of Float64s with dimensions 2, 2
rand(type, 2, 2) – an array of values of this type with dims 2, 2
rand(range, dims) – array of numbers in a range (including both ends) with specified dimensions:
(See the Arrays chapter for more about range objects.)
The rand function can generate a true or false value if you tell it to, by passing the Bool keyword:
or a bunch of trues and falses:

##### Random numbers in a distribution

randn gives you one random number in a normal distribution with mean 0 and standard deviation 1. randn(n) gives you n such numbers:
If you've installed the Plots plotting package, you can plot this:

#### Seeding the random number generator

The Random package contains many more random functions, such as randperm, shuffle, and seed!.
Before you use random numbers, you can seed the random number generator with a specific value. This ensures that subsequent random numbers will follow the same sequence, if they start from the same seed. You can seed the generator using the seed! or MersenneTwister functions.
Once you've added the Random package, you can do:
After restarting Julia, the same seed guarantees the same random numbers.

### Simple keyboard input

Here's an example of how you'd write and run a function that reads input from the keyboard:
This works in a Julia REPL session; when called, the function waits for the user to type a string on the keyboard and press Return/Enter.

# Arrays and Tuples
## Storage: Arrays and Tuples

In Julia, groups of related items are usually stored in arrays, tuples, or dictionaries. Arrays can be used for storing vectors and matrices. This section concentrates on arrays and tuples; for more on dictionaries, see Dictionaries and Sets.

## Arrays

An array is an ordered collection of elements. It's often indicated with square brackets and comma-separated items. You can create arrays that are full or empty, and arrays that hold values of different types or restricted to values of a specific type.
In Julia, arrays are used for lists, vectors, tables, and matrices.
A one-dimensional array acts as a vector or list. A 2-D array can be used as a table or matrix. And 3-D and more-D arrays are similarly thought of as multi-dimensional matrices.

## Creating arrays
### Creating simple arrays

Here's how to create a simple one-dimensional array:
Julia informs you ("5-element Array{Int64,1}") that you've created a 1-dimensional array with 5 elements, each of which is a 64-bit integer, and bound the variable a to it. Notice that intelligence is applied to the process: if one of the elements looks like a floating-point number, for example, you'll get an array of Float64s:
Similarly for strings:
returns an array of strings, and:
returns an array of Julia functions.
There are many different ways to create arrays: you can make them empty, uninitialised, full, based on sequences, sparse, dense, and more besides. It depends on the task in hand.

#### Uninitialized

You can specify the type and the dimensions of an array using Array{type}(dims) (notice that upper-case "A"), putting the type in curly braces, and the dimensions in the parentheses. The undef means that the array hasn't been initialized to known values.
The random-looking numbers are a reminder that you've created an uninitialized array but haven't filled it with any sensible information.

#### Arrays of anything

It's possible to create arrays with elements of different types:
Here, the array has five elements, but they're an odd mixture: numbers, strings, functions, constants — so Julia creates an array of type Any:

#### Empty arrays

To create an array of a specific type, you can also use the type definition and square brackets:
If you think you can fool Julia by sneaking in a value of the wrong type while declaring a typed array, you'll be caught out:
You can create empty arrays this way too:

### Creating 2D arrays and matrices

If you leave out the commas when defining an array, you can create 2D arrays quickly. Here's a single row, multi-column array:
Notice the 1x4 {...,2} in the first row of the response.
You can use a semicolon to add another row:

#### Row and column vectors

Compare these two: [1,2,3,4,5] and [1 2 3 4 5].
With the commas, this array could be called a "column vector", with 5 rows and 1 column:
But with the spaces, this array could be called a "row vector", with 1 row and 5 columns:
- notice the {Int64,2} here, which tells you that this is a 2D array of Int64s (with 1 row and 5 columns). In both cases, they're standard Julia arrays.
Arrays created like this can be used as matrices:
And of course you can create arrays/matrices with 3 or more dimensions.
There are a number of functions which let you create and fill an array in one go. See Creating and filling an array.
Notice how Julia distinguishes between Array{Float64,1} and Array{Float64,2}:
Julia provides the Vector and Matrix constructor functions, but these are simply aliases for uninitialized one and two dimensional arrays:

### Creating arrays using range objects

In Julia, the colon (:) has a number of uses. One use is to define ranges and sequences of numbers. You can create a range object by typing it directly:
It may not look very useful in that form, but it provides the raw material for any job in Julia that needs a range or sequence of numbers.
You can use it in a loop expression:
Or you can use collect to build an array consisting of those numbers:
You don't have to start and finish on an integer either:
There's also a three-piece version of a range object, start:step:stop, which lets you specify a step size other than 1. For example, this builds an array with elements that go from 0 to 100 in steps of 10:
To go down instead of up, you have to use a negative step value:
Instead of using collect to create an array from the range, you could use the ellipsis (...) operator (three periods) after the last element:
(The ... ellipsis is sometimes called the splat operator. It represents a sequence of arguments.)
However, collect is faster and the recommended method of converting ranges to arrays. But you can use range objects in many situations in Julia, and you don't always need to expand them into arrays.

### More range objects

Another useful function is range, which constructs a range object that goes from a start value to an end value taking a specific number of steps of a certain size. You don't have to calculate all the information, because Julia calculates the missing pieces for you by combining the values for the keywords step, length, and stop. For example, to go from 1 to 100 in exactly 12 steps:
or take 10 steps from 1, stopping at or before 100:
If you really want it in array form, you can use the range object to build an array:
Notice that it provided you with a Float64 array, rather than an Integer array, even though the values could have been integers.
For logarithmic ranges (sometimes called 'log space'), you can use simple range objects and then broadcast the exp10 function (10^x) to every element of the range.
See Broadcasting and dot syntax.
Use step on a range object to find out what the step size is:
Use range if you know the start and step, but not the end, and you know how many elements you want:

### Collecting up the values in a range

As you've seen, if you're not using your range object in a for loop, you can, if you want, use collect to obtain all the values from a range object directly:
However, you don't always have to convert ranges to arrays before working on them — you can usually iterate over things directly. For example, you don't have to write this:
because it works just as well (and probably faster) if you leave out the collect:

### Using comprehensions and generators to create arrays

A useful way to create arrays where each element can be produced using a small computation is to use comprehensions (described in Comprehensions).
For example, to create an array of 5 numbers:
With two iterators, you can easily create a 2D array or matrix:
You can add an if test at the end to filter (keep) values that pass a test:
Generator expressions are similar, and can be used in a similar way:
The advantage of generator expressions is that they generate values when needed, rather than build an array to hold them first.

### Creating and filling an array

There are a number of functions that let you create arrays with specific contents. These can be very useful when you're using 2D arrays as matrices:
- zeros(m, n) creates an array/matrix of zeros with m rows and n columns:
You can specify the type of the zeros if you want:
- ones(m, n) creates an array/matrix of ones with m rows and n columns
- rand(m, n) creates an m-row by n-column matrix full of random numbers:
- rand(range, m, n) creates a matrix full of numbers in the supplied range:
- randn(m, n) creates an m-row by n-column matrix full of normally-distributed random numbers with mean 0 and standard deviation 1.
As well as the zeros, ones functions, there are trues, falses, fill, and fill! functions as well.
The trues and falses functions fill arrays with the Boolean values true or false:
Notice how the result is a BitArray.
You can use fill to create an array with a specific value, i.e. an array of repeating duplicates:
With fill!, the exclamation mark (!) or "bang" is to warn you that you're about to change the contents of an existing array (a useful indication that's adopted throughout Julia).
Let's change an array of falses to trues:
You can use the range function to create vector-like arrays, followed by reshape to change them into 2D arrays:
The result is a 10 by 3 array featuring evenly-spaced numbers between 0 and 100.

#### Repeating elements to fill arrays

A useful function for creating arrays by repeating smaller ones is repeat.
The first option for its syntax is repeat(A, n, m), the source array is repeated by n times in the first dimension (rows), and m times in the second (columns).
You don't have to supply the second dimension, just supply how many rows you want:
The second option specifies the extra columns:
The repeat function also lets you create arrays by duplicating rows and columns of a source array. The inner and outer options determine whether rows and/or columns are repeated. For example, inner = [2, 3] makes an array with two copies of each row and three copies of each column:
By contrast, here's outer = [2,3]:
Note that the latter is equivalent to repeat([1, 2], 2, 3). A more meaningful example of the outer keyword is when it is combined with inner. Here, each element of each line of the initial matrix is line-duplicated and then, each line slice of the resulting matrix is column-triplicated:

### Array constructor

The Array function we saw earlier builds arrays of a specific type for you:
This is uninitialized; the odd-looking numbers are simply the old contents of the memory before it was assigned to hold the new array.

#### Arrays of arrays

It's easy to create an array of arrays. Sometimes you want to specify the original contents:
The Array constructor can also construct an array of arrays:
With the reshape function, you could of course just create a simple array and then change its shape:
The same techniques can be used to create 3D arrays. Here's a 3D array of strings:
Each element is set to 'undefined' — #undef.
The push! function pushes another item onto the back of an array:
or you might want to create them empty:
You can use Vector as an alias for Array:

### Copying arrays

If you have an existing array and want to create another array having the same dimensions, you can use the similar function:
Notice that the array dimensions are copied, but the values aren't, they've been copied from random bits of memory. You can, though, change the type and dimensions anyway, so they don't have to be that similar:
And in any case there's a copy function.

### Matrix operations: using arrays as matrices

In Julia, a 2-D array can be used as a matrix. All the functions available for working on arrays can be used (if the dimensions and contents permit) as matrices.
A quick way of typing a matrix is to separate the elements using spaces (to make rows) and to use semicolons to separate the rows. So:
| julia> [1 0 ; 0 1] 2x2 Array{Int64,2}: 1 0 0 1 | ${\begin{pmatrix}1&0\\0&1\\\end{pmatrix}}$ |
You could also do this:
which takes a standard array and reshapes it to run in two rows and two columns. Notice that the matrix is filled column by column.
If you don't use commas or semicolons:
you'll create a single row array/matrix:
In each case, notice the 2 in the braces ({Int64,2}) following the type value. This indicates a 2-dimensional array.
You can create an array of arrays by sticking two arrays next to each other, like this:
When you omit the comma, you're placing columns next to each and you'll get this:

## Accessing the contents of arrays

To access the elements of an array or matrix, follow the name of the array by the element number in square brackets. Here's a 1D array:
Here's the fifth element:
The first element is index number 1. Julia is one of the languages that starts indexing elements in lists and arrays starting at 1, rather than 0. (And thus it's in the elite company of Matlab, Mathematica, Fortran, Lua, and Smalltalk, while most of the other programming languages are firmly in the opposite camp of 0-based indexers.)
The last element is referred to as end (not -1, as in some other languages):
Similarly, you can access the second to last element with
(with similar syntax for the third to last element and so on).
You can provide a bunch of index numbers, enclosed in a pair of brackets at each end:
or supply a range of index numbers:
You can even select elements using true and false values:
Here's a 2D array, with the rows separated by semicolons:
If you just ask for one element of a 2D array, you'll receive it as if the array is unwound column by column, i.e. down first, then across. In this case you'll get 4, not 2:
Asking for row then column works as you expect:
which is row 1, column 2. Here's row 1, column 3:
but don't get the row/column indices the wrong way round:
By the way, there's an alternative way of obtaining elements from arrays: the getindex function:
Use the colon to indicate every row or column. For example, here's "every row, second column":
and here's "second row, every column":

### Elementwise and vectorized operations

Many Julia functions and operators are designed specifically to work with arrays. This means that you don't always have to work through an array and process each element individually.
A simple example is the use of the basic arithmetic operators. These can be used directly on an array if the other argument is a single value:
and every element of the new array is the original multiplied by 2. Similarly:
and every element of the new array is the original divided by 100.
These operations are described as operating elementwise.
Many operators can be used preceded with a dot (.). These versions are the same as their non-dotted versions, and work on the arrays element by element. For example, the multiply function (*) can be used elementwise, using .*. This lets you multiply arrays or ranges together element by element:
and the first element of the result is what you get by multiplying the first elements of the two arrays, and so on.
As well as the arithmetic operators, some of the comparison operators also have elementwise versions. For example, instead of using == in a loop to compare two arrays, use .==. Here are two arrays of ten numbers, one sequential, the other disordered, and an elementwise comparison to see how many elements of array b happened to end up in the same place as array a:

#### Broadcasting: dot syntax for vectorizing functions

This technique of applying functions elementwise to arrays with the dot syntax is called broadcasting. Follow the function name with a dot/period before the opening parenthesis, and supply an array or range as an argument. For example, here's a simple function which multiplies two numbers together:
It works as expected on two scalars:
But it's easy to apply this function to an array. Just use the dot syntax:
In the first example, Julia automatically treated the second argument as if it was an array, so that the multiplication would work correctly.
Watch out for this when combining ranges and vectorized functions:
The first example is equivalent to 0:(10 .* 0.5), and you might have intended (0:10) .* 0.5.

### min and max

Watch out for max and min. You might think that max can be used on an array, like this, to find the largest element:
but no…
The max function returns the largest of its arguments. To find the largest element in an array, you can use the related function maximum:
You can use max on two or more arrays to carry out an elementwise examination, returning another array containing the maximum values:
min and minimum behave in a similar way.
A way to make max work on an array is to use the ellipsis (splat) operator:
You can test each value of an array and change it in a single operation, using element-wise operators. Here's an array of random integers from 0 to 10:
Now you can test each value for being equal to 0, then set only those elements to 11, like this:
This works because a .== 0 returns an array of true and false values, and these are then used to select the elements of a which are to be set to 11.
If you're doing arithmetic on 2D matrices, you might want to read more about matrix arithmetic: Matrix arithmetic

### Rows and Columns

With a 2D array, you use brackets, colons, and commas to extract individual rows and columns or ranges of rows and columns.
With this table:
you can find a single row using the following (notice the comma):
and you can get a range of rows with a range followed by a comma and a colon:
To select columns, start with a colon followed by a comma:
On its own, the colon accesses the entire array:
To extract a range of columns:

### Finding items in arrays

If you want to know whether an array contains an item, use the in function, which can be called in two ways:
Or phrased as a function call:
There's a set of functions starting with find — such as findall, findfirst, findnext, findprev and findlast — that you can use to get the index or indices of array cells that match a specific value, or pass a test. Each of these has two or more more forms.
Here's an array of small primes:
To find the first occurrence of a number, and obtain its index, you can use the following method of the findfirst function:
so the first occurrence of 13 in the array is in the sixth cell:
This function is similar to many in Julia which accepts a function as the first argument. The function is applied to each element of an array, and if the function returns true, that element or its index is returned. This function returns the index of the first element.
Here's another example using an anonymous function:
The findall function returns an array of indices, pointing to every element where the function returns true when applied:
Remember that these are arrays of index numbers, not the actual cell values. The indices can be used to extract the corresponding values using the standard square bracket syntax:
whereas findfirst returns a single number — the index of the first matching cell:
The findnext function is very similar to the findall and findfirst functions, but accepts an additional number that tells the functions to start the search from somewhere in the middle of the array, rather than from the beginning. For example, if findfirst(smallprimes,13) finds the index of the first occurrence of the number 13 in the array, we can continue the search from there by using this value in findnext:
To return the indices of the elements in array B where the elements of array A can be found, use findall(in(A), B):
The order in which the indices are returned should be noted.

#### Finding out about an array

With our 2D array:
we can find out more about it using the following functions:
* ndims
* size
* length
* count
ndims returns the number of dimensions, i.e. 1 for a vector, 2 for a table, and so on:
size returns the row and column count of the array, in the form of a tuple:
length tells you how many elements the array contains:
You can use count to find out how many times a particular value occurs. For example, how many non-zero items are there?
For finding the inverse, determinant and other aspects of an array/matrix, see Manipulating matrices.
To convert between index numbers (1 to n) and row/column numbers (1:r, 1:c), you can use:
to find the row and column for the sixth element, for example.
And to go in the other direction, what index number corresponds to row3, column 2? Use the opposite of Cartesian indices, Linear indices:
diff is useful to find the differences between each element of an array:

#### Comparing arrays

union builds a new array that's the union or combination of two or more arrays. The operation removes duplicates, and the result contains a single version of each element:
Notice that the ordering of the new union reflects the original order. This example doesn't sort the numbers at all:
intersect returns a new array that's the intersection of two or more arrays. The result contains one occurrence of each element, but only if it occurs in every array:
setdiff finds the difference between two arrays, i.e. the elements that are in the first array but not the second:

#### Filtering

There's a set of related functions that let you work on an array's elements.
filter finds and keeps elements if they pass a test. Here, we're using the isodd function (passing it as a named function without parentheses, rather than a function call with parentheses) to filter (keep) everything in the array that's odd.
Like many Julia functions, there's a version which changes the array. So filter returns a copy of the original, but filter! changes the array.
The count function we met earlier is like filter, but just counts the number of elements that satisfy the condition:
Also, the any function just tells you whether any of the elements satisfy the condition:
and the all function tells you if all of the elements satisfy the condition. Here, all checks to see whether filter did the job properly.

#### Random element of an array

To choose a random element from an array:

#### Other functions

Because arrays are fundamental to Julia, there are dozens of array-handling functions that can't be described here. But here are a few selections:
Find the extreme values of an array:
findmax finds the maximum element and returns it and its index in a tuple:
Use argmax to return just the index.
The maximum and minimum functions let you supply functions to determine how the "maximum" is determined. This is useful if your arrays are not simple vectors. This example find the maximum array element, where maximum here means, "has the largest last value":
Functions such as sum, prod, mean, middle, do what you would expect:
(mean and middle have been moved into the Statistics module in the standard library; you may need to first enter "using Statistics" to use them)
sum, mean, and prod also let you supply functions: the function is applied to each element and then the results are summed/mean-ed/prod-ded:
There are functions in the Combinatorics.jl package that let you find combinations and permutations of arrays. combinations finds all the possible combinations of elements in an array: you can specify how many elements in each combination:
and permutations generates all permutations. There are a lot — in practice you probably won't need to use collect to collect the items into an array:

## Modifying array contents: adding and removing elements

To add an item at the end of an array, use push!:
As usual, the exclamation mark reminds you that this function changes the array. You can push only onto the end of vectors.
To add an item at the front, use pushfirst!:
To insert an element into an array at a given index, use the splice! function. For example, here's a list of numbers with an obvious omission:
Use splice! to insert a sequence at a specific range of index values. Julia returns the values that were replaced. The array grows larger to accommodate the new elements, and elements after the inserted sequence are pushed down. Let's insert, at position 4:5, the range of numbers 4:6:
You'll be tempted to check that the new values were inserted correctly:
Now, if you want to insert some values at a specific inter-index location, you will have to use a feature known as empty ranges. In this case the interspace between indexes n-1 and n is denoted as n:n-1.
For example:

### Removing elements

If you don't supply a replacement, you can also use splice! can remove elements and move the rest of them along.
To remove the last item:
and the first:
More aggressive modification of arrays (and similar data structures) can be made with functions such as deleteat! and splice!. You can find out the indices of elements in various ways. Once you know the indices, you can use deleteat! to delete an element, given its index number:
deleteat! also accepts a range or iterator to specify the indices, so you can do this:
Remember that you can always remove a group of elements using a filter: see Filtering.

### Other functions

If you want to do something to an array, there's probably a function to do it, and sometimes with an exclamation mark to remind you of the potential consequences. Here are a few more of these array-modifying functions:
* resize! change the length of a Vector
* append! push a second collection at the back of the first one
* prepend! insert elements at the beginning of the first Vector
* empty!(a) remove all elements
* unique(a) remove duplicate elements from the array "a" without overwriting the array.
* unique!(a) remove duplicate elements from the array "a" and overwrites the array.
* rotr90(a) make a copy of an array rotated 90 degrees clockwise:
* circshift(a) move the elements around 'in a circle' by a number of steps:
This function can also do circular shifts on 2D arrays too. For example, here's a table:
By supplying a tuple you can move rows and columns. For example: moving the columns by 0 and the rows by 1 moves the first dimension by 0 and the second by 1. The first dimension is downwards, the second rightwards:
There's a modifying version of circshift, circshift!

### Setting the contents of arrays

To set the contents of an array, specify the indices on the left-hand side of an assignment expression:
To check that the array has really changed:
You can set a bunch of elements at the same time, using the broadcasting assignment operator:
And you can set a sequence of elements to a suitable sequence of values:
Notice here that, although Julia shows the 7 element slice as the return value, in fact the whole array has been modified:
You can set ranges to a single value in one operation using broadcasting:
As an alternative to the square bracket notation, there's a function call version that does the same job of setting array contents, setindex!:
You can refer to the entire contents of an array using the colon separator without start and end index numbers, i.e. [:]. For example, after creating the array a:
we can refer to the contents of this array a using a[:]:

### Passing arrays to functions

A function can't modify a variable passed to it as an argument, but it can change the contents of a container passed to it.
Consider the following function, that changes its argument to 5:
Although the x inside the function is changed, the x outside the function isn't. Variable names in functions are local to the function.
But, you can modify the contents of a container, such as an array. The next function uses the [:] syntax to access the contents of the container x, rather than change the value of the variable x:
If, instead of accessing the container variable's contents, you try to change the variable itself, it won't work. For example, the following function definition creates an array of 5s in temp and then attempts to change the argument x to be temp.
It looks like it worked, but:
You can change elements of the array, but you can't change the variable so that it points to a different array. In other words, your function isn't allowed to change the binding between the argument and the array that was passed to it.
Julia's way of handling function arguments is described as “pass-by-sharing”. An array isn't copied when you pass it to a function (that would be very inefficient for large arrays).

### Matrix arithmetic

For matrix-on-matrix arithmetic action, you can:
- add (+) and subtract (-):
| julia> A = reshape(1:12, 3, 4) 3x4 Array{Int64,2}: 1 4 7 10 2 5 8 11 3 6 9 12 | ${\begin{pmatrix}1&4&7&10\\2&5&8&11\\3&6&9&12\\\end{pmatrix}}$ |
| julia> B = ones(3,4) 3x4 Array{Float64,2}: 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 | ${\begin{pmatrix}1.0&1.0&1.0&1.0\\1.0&1.0&1.0&1.0\\1.0&1.0&1.0&1.0\\\end{pmatrix}}$ |
| julia> A + B 3x4 Array{Float64,2}: 2.0 5.0 8.0 11.0 3.0 6.0 9.0 12.0 4.0 7.0 10.0 13.0 | ${\begin{pmatrix}1&4&7&10\\2&5&8&11\\3&6&9&12\\\end{pmatrix}}+{\begin{pmatrix}1.0&1.0&1.0&1.0\\1.0&1.0&1.0&1.0\\1.0&1.0&1.0&1.0\\\end{pmatrix}}={\begin{pmatrix}2.0&5.0&8.0&11.0\\3.0&6.0&9.0&12.0\\4.0&7.0&10.0&13.0\\\end{pmatrix}}$ |
| julia> A - B 3x4 Array{Float64,2}: 0.0 3.0 6.0 9.0 1.0 4.0 7.0 10.0 2.0 5.0 8.0 11.0 | ${\begin{pmatrix}1&4&7&10\\2&5&8&11\\3&6&9&12\\\end{pmatrix}}-{\begin{pmatrix}1.0&1.0&1.0&1.0\\1.0&1.0&1.0&1.0\\1.0&1.0&1.0&1.0\\\end{pmatrix}}={\begin{pmatrix}0.0&3.0&6.0&9.0\\1.0&4.0&7.0&10.0\\2.0&5.0&8.0&11.0\\\end{pmatrix}}$ |
- multiply (*), assuming the dimensions are compatible, so m1 * m2 is possible if last(size(m1)) == first(size(m2)). Note the difference between matrix multiplication and elementwise matrix multiplication. Here's a matrix A:
| julia> A = [1 2 ; 3 4] 2x2 Array{Int64,2}: 1 2 3 4 | ${\begin{pmatrix}1&2\\3&4\\\end{pmatrix}}$ |
and here's matrix B:
| julia> B = [10 11 ; 12 13] 2x2 Array{Int64,2}: 10 11 12 13 | ${\begin{pmatrix}10&11\\12&13\\\end{pmatrix}}$ |
The .* broadcasting operator multiplies them elementwise:
| julia> A .* B 2x2 Array{Int64,2}: 10 22 36 52 | ${\begin{pmatrix}1&2\\3&4\\\end{pmatrix}}.*{\begin{pmatrix}10&11\\12&13\\\end{pmatrix}}={\begin{pmatrix}10&22\\36&52\\\end{pmatrix}}$ |
Compare this with matrix multiplication, A * B:
| julia> A * B 2x2 Array{Int64,2}: 34 37 78 85 | ${\begin{pmatrix}1&2\\3&4\\\end{pmatrix}}\times {\begin{pmatrix}10&11\\12&13\\\end{pmatrix}}={\begin{pmatrix}34&37\\78&85\\\end{pmatrix}}$ |
which is:
- division of two matrices. You can use the backslash (\) for left division:
and the forward slash (/) right or slash division:
With a matrix and a scalar, you can add, subtract, multiply, and divide:
and more besides:
You can multiply matrix and a vector (the matrix-vector product), if the arrays have compatible shapes. Here's the matrix A:
| julia> A = reshape(1:12, 3, 4) 3x4 Array{Int64,2}: 1 4 7 10 2 5 8 11 3 6 9 12 | ${\begin{pmatrix}1&4&7&10\\2&5&8&11\\3&6&9&12\\\end{pmatrix}}$ |
and here's a vector V:
| julia> V = collect(1:4) 4-element Array{Int64,1}: 1 2 3 4 | ${\begin{pmatrix}1\\2\\3\\4\\\end{pmatrix}}$ |
The * operator multiplies them:
| julia> A * V 3-element Array{Int64,1}: 70 80 90 | ${\begin{pmatrix}1&4&7&10\\2&5&8&11\\3&6&9&12\\\end{pmatrix}}*{\begin{pmatrix}1\\2\\3\\4\\\end{pmatrix}}={\begin{pmatrix}70\\80\\90\\\end{pmatrix}}$ |
The dot or inner product (aTb) can be found using the dot function, but you'll have to import the LinearAlgebra library first:
| julia> dot([1:3...], [21:23...]) 134 | ${\begin{pmatrix}1&2&3\\\end{pmatrix}}\cdot {\begin{pmatrix}21&22&23\\\end{pmatrix}}=134$ |
The two arguments must have the same length. You can also use the dot operator, which you can obtain in the REPL by typing "\cdot" followed by a tab:

### Joining arrays and matrices

You can use hcat and vcat to join matrices together, if their dimensions permit.
hcat keeps the first dimension and extends (joins) in the second, vcat keeps the second dimension and extends the first.
Here are two 3 by 4 matrices:
hcat(A, B) makes a new array that still has 3 rows, but extends/joins the columns to make 8 in total:
vcat(A, B) makes a new array that keeps the 4 columns, but extends to 6 rows:
You'll probably find the shortcuts useful:
* [A ; B ] is vcat(A, B)
* [A B ] is hcat(A, B)
vec flattens a matrix into a vector, turning it into a (what some call a 'column') vector:
There's also an hvcat function ([A B; C D;]) that does both.
You can use hcat to convert an array of arrays to a matrix (using the hcat-splat):
Julia arrays are 'column-major'. This means that you read down the columns:
whereas 'row-major' arrays are to be read across, like this:
Column-major order is used in Fortran, R, Matlab, GNU Octave, and by the BLAS and LAPACK engines (the "bread and butter of high-performance numerical computation"). Row-major order is used in C/C++, Mathematica, Pascal, Python, C#/CLI/.Net and others.

### Growing or extending arrays

Often you want to create an array and then add more to it, or 'grow' it. While can do this with vcat and hcat, be aware that both these operations create new temporary arrays and copy elements, so they don't always produce the fastest code. A better way is to use push!. This is an efficient operation that extends the array. You can reshape the array later:
reshape lets you change the dimensions of an array. You can supply the dimensions or use a colon (:) to ask Julia to calculate valid dimensions:
reshape(a, (10, div(length(a), 10))) would have the same effect.
push! doesn't let you push new rows to a 2D array or matrix. The best way to do the job is to work on a 1D array, as above, adding more elements at the end, and then use reshape to convert it to two dimensions. If necessary, use transpose to flip the matrix.

### Manipulating matrices

To transpose an array or matrix, there's an equivalent ' operator for the transpose function, to swap rows and columns:
To find the determinant of a square matrix, use det, after remembering to load the LinearAlgebra library.
inv (in the Standard Library) finds the inverse of a square matrix, if it has one. (If the determinant of the matrix is zero, it won't have an inverse.)
LinearAlgebra.rank finds the rank of the matrix, and LinearAlgebra.nullspace finds the basis for the nullspace.
LinearAlgebra.tr sums the diagonal of a square matrix (trace):

### Applying functions to matrices

There are a number of functions that can be applied to a matrix:
- sum adds every element:
You can specify a dimension if you want to sum just columns or rows. So to sum columns, specify dimension 1:
To sum rows, specify dimension 2:
- mean finds the mean of the values in the matrix:
As with sum, you can specify a dimension, so that you can find the mean of columns (use dimension 1) or rows (use dimension 2):
- the min.(A, B) and max.(A, B) functions compare two (or more) arrays element by element, returning a new array with the largest (or smallest) values from each:
prod multiplies a matrix's elements together:
(Notice the use of BigInt, products are very large.)
You can specify a dimension if you want to multiply just columns or rows. To multiply the elements of columns together, specify dimension 1; for rows, use dimension 2:

### Matrix norms

Most of these functions live in the LinearAlgebra library:

#### Vector norms

The Euclidean norm, $\|x\|_{2}={\sqrt {x_{1}^{2}+x_{2}^{2}+\ldots +x_{n}^{2}}}$, is found by LinearAlgebra.norm(x):
If X is a 'row' vector:
The Euclidean distance between vectors $x$ and $y$, given by $\|x-y\|_{2}$, is found by norm(x - y):
The angle between two vectors $a$ and $b$ is $\arccos \left({\frac {a^{T}b}{\|a\|_{2}\|b\|_{2}}}\right)$:

#### Matrix norms

Here's the 1-norm of a matrix (the maximum absolute column sum):
And here's the infinity norm (the maximum absolute row sum):
Note they are different from vectorized 1-norm or infinity norm:
The Euclidean norm is the default:

### Scaling and rotating matrices

- rmul!(A, n) scales every element of the matrix in place by a scale factor n:
There are rotation and circular-shifting functions too:
reverse makes a copy of a matrix reversing rows or columns:
squeeze and reshape can be used to change the dimensions of a matrix. For example, this is how you can use squeeze to collapse a row vector (1 by 4) into a 4 by 1 array:

### Sorting arrays

Julia has a flexible sort function that returns a sorted copy of an array, and a companion sort! version that changes the array so that it's sorted.
You can usually use sort without options and obtain the results you'd hoped for:
You can sort 2D arrays:
although there are more powerful alternatives in sortrows and sortcolumns — see below for details.
The sortperm function is similar to sort, but it doesn't return a sorted copy of the collection. Instead it returns a list of indices that could be applied to the collection to produce a sorted version:

#### Sort by and comparisons

If you need more than the default sort offers, use the by and lt keywords and provide your own functions for processing and comparing elements during the sort.

##### sort by

The by function processes each element before comparison and provides the 'key' for the sort. A typical example is the task of sorting a list of numbers in string form into numerical order. Here's the list:
If you use the default sort, the numbers appear in the order in which the characters appear in Unicode/ASCII:
with "1E-10" appearing after "0.999".
To sort the numbers by their value, pass the parse function (from the Meta package) to by:
The strings are sorted 'by' their value. Notice that the by function you supply produces the numerical sort key, but the original string elements appear in the final result.
Anonymous functions can be useful when sorting arrays. Here's a 10 rows by 2 columns array of tuples:
You can sort this array by the second element of each tuple, not the first, by supplying an anonymous function to by that points to the second element of each. The anonymous function says, given an object x to sort, sort by the second element of x:

##### Sorting by multiple columns

You can supply a tuple of "column" identifiers in the by function, if you want to sort by more than one column.
This sorts the array first by column 1, then by column 2, then by column 3.

##### Redefining 'less than'

By default, sorting uses the built-in isless function when comparing elements. In a sorted array, the first element is less than the second.
You can change this behaviour by passing a different function to the lt keyword. This function should compare two elements and return true if they're sorted, i.e. if the first element is 'less than' the second, using some definition of 'less than'. The sorting process compares pairs of elements repeatedly until every element of the array is in the right place.
For example, suppose you want to sort an array of words according to the number of vowels in each word; i.e. the more vowels a word has, the earlier in the sorted results it occurs. For example, the word "orange" will be considered to be "less than" the word "lemon", because it has more vowels.
First we'll need a function that counts vowels:
Now you can pass an anonymous function to sort that compares the vowel count of two elements using this function and then returns the element with a higher count in each case:
The result is that the word with the most vowels appears first:
The sort function also lets you specify a reverse sort - after the by and lt functions (if used) have done their work, a true value passed to rev reverses the result.

#### Sorting 2-D arrays

In Julia 1.0, you can sort multidimensional arrays with sortslices.
Here's a simple array of nine strings (you can also use numbers, symbols, functions, or anything that can be compared):
You supply a number or a tuple to the dims ("dimensions") keyword that indicates what you want to sort. To sort the table so that the first column is sorted, use 1:
Note that sortslices returns a new array. The first column is in alphabetical order.
Use dims=2 to sort the table so that the first row is sorted:
Now the first row is in alphabetical order.
If you want to sort by something other than the first item, pass a function to by. So, to sort rows so that the middle column is in alphabetical order, use:
sortslices has most of the options that you'll find in sort, and more besides. You can reverse the order with rev, change the comparator with lt, and so on.

## Tuples

A tuple is an ordered sequence of elements, like an array. A tuple is represented by parentheses and commas, rather than the square brackets used by arrays. Tuples are mostly good for small fixed-length collections — they're used everywhere in Julia, for example, as argument lists and for returning multiple values from functions.
The important difference between arrays and tuples is that tuples are immutable. Other than that, tuples work in much the same way as arrays, and many array functions can be used on tuples too:
You can have two-dimensional tuples:
But you can't change a tuple:
And, because you can't modify tuples, you can't use any of the functions like push! that you use with arrays:

### Named tuples

A named tuple is like a combination of a tuple and a dictionary. Like a tuple, a named tuple is ordered and immutable, and enclosed in parentheses; like a dictionary, each element has a unique key that can be used to access it.
You can create a named tuple by providing keys and values directly:
To access the values, use the familiar dot syntax:
You can access all the values (destructuring) as with ordinary tuples:
or just some of them:
Elements can be the same type, or different types, but the keys will always be variable names.
You can iterate over a named tuple:
Another way to create a named tuple is to provide the keys and values in separate tuples:
You can combine two named tuples to make a new one:
You can use existing variables for keys:
Making single value Named Tuples requires a strategically-placed comma:
If you forget it, you'll see this:
You can make new named tuples by combining named tuples together.
Use a comma after a single element named tuple:
because without the comma, the tuple will be interpreted as a parenthesized keyword argument to merge.
To iterate over the "keys", use the fieldnames and typeof functions:
so you can do:
Merging two tuples is done intelligently. For example, if you have this named tuple:
and you want to add a center point and change the top color:
the new value is inserted, and the existing value is changed.

#### Using named tuples as keyword arguments

A named tuple is a convenient way to pass a group of keyword arguments to a function. Here's a function that accepts three keyword arguments:
You can define a named tuple that contains the names and values for one or more keywords:
To pass the named tuple to the function, use the ; when you call the function:
If you specify a keyword and value, it can be overridden by a later definition:

# Types
## Types

This section, on types, and the next section, on functions and methods, should ideally be read at the same time, because the two topics are so closely connected.

### Types of type

Data elements come in different shapes and sizes, which are called types.
Consider the following numeric values: a floating point number, a rational number, and an integer:
It's easy for us humans to add these numbers without much thought, but a computer won't be able to use a simple addition routine to add all three values, because the types are different. Code for adding rational numbers has to consider numerators and denominators, whereas code for adding integers won't. The computer will probably have to convert two of these values to be the same type as the third—typically the integer and the rational will first be converted to floating-point—then the three floating-point numbers will be added together.
This business of converting types obviously takes time. So, to write really fast code, you want to make sure that you don't make the computer waste time by continually converting values from one type to another. When Julia compiles your source code (which happens every time you evaluate a function for the first time), any type indications you've provided allow the compiler to produce more efficient executable code.
Another issue with converting types is that in some cases you'll be losing precision—converting a rational number to a floating-point number is likely to lose some precision.
The official word from the designers of Julia is that types are optional. In other words, if you don't want to worry about types (and if you don't mind your code running slower than it might), then you can ignore them. But you'll encounter them in error messages and the documentation, so you will eventually have to tackle them…
A compromise is to write your top-level code without worrying about types, but, when you want to speed up your code, find out the bottlenecks where your program spends the most time, and clean up the types in that area.

### The type system

There's a lot to know about Julia's type system, so the official documentation is really the place to go. But here's a brief overview.

#### Type hierarchy

In Julia types are organized in a hierarchy, with a tree structure.
At the tree's root, we have a special type called Any, and all other types are connected to it directly or indirectly. Informally, we can say that the type Any has children. Its children are called Any's subtypes. And a child's supertype is Any. (Note, however, hierarchical relationships between types are explicitly declared, rather than implied by compatible structure.)
We can see a good example of Julia's type hierarchy by looking at the Number types.
The type Number is a direct child of Any. To see what Number's supertype is, we can use the supertype function:
But we could also try to find Number's subtypes (Number's children, therefore Any's grandchildren). To do this, we can use the function subtypes:
We can observe that we have two subtypes of Number: Complex and Real. For mathematicians, Real and Complex numbers are both, indeed, numbers. As a general rule, Julia's type hierarchy reflect the real world's hierarchy.
As another example, if both Jaguar and Lion were Julia types, it would natural if their supertype were Feline. We would have:

#### Concrete and abstract types

Each object in Julia (informally, this means everything you can put into a variable in Julia) has a type. But not all types can have a respective object (instances of that type). The only ones that can have instances are called concrete types. These types cannot have any subtypes. The types that can have subtypes (e.g. Any, Number) are called abstract types. Therefore we cannot have a object of type Number, since it's an abstract type. In other words, only the leaves of the type tree are concrete types and can be instantiated.
If we can't create objects of abstract types, why are they useful? With them, we can write code that generalizes for any of its subtypes. For instance, suppose we write a function that expects a variable of the type Number:
In this example, the function expects a variable n. The type of n must be subtype of Number (directly or indirectly) as indicated with the :: syntax (but don't worry about the syntax yet). What does this mean? No matter if n's type is Int (Integer number) or Float64 (floating-point number), the function plus_one will work correctly. Furthermore, plus_one will not work with any types that are not subtypes of Number (e.g. text strings, arrays).
We can divide concrete types into two categories: primitive (or basic), and complex (or composite). Primitive types are the building blocks, usually hardcoded into Julia's heart, whereas composite types group many other types to represent higher-level data structures.
You'll probably see the following primitive types:
* the basic integer and float types (signed and unsigned): Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64, Int128, UInt128, Float16, Float32, and Float64
* more advanced numeric types: BigFloat, BigInt
* Boolean and character types: Bool and Char
* Text string types: String
A simple example of a composite type is Rational, used to represent fractions. It is composed of two pieces, a numerator and a denominator, both integers (of type Int).

### Investigating types

Julia provides two functions for navigating the type hierarchy: subtypes and supertype.
The sizeof function tells you how many bytes an item of this type occupies:
If you want to know how big a number you can fit into a particular type, these two functions are useful:
There are over 340 types in the base Julia system. You can investigate the type hierarchy with the following function:
It produces something like this for the different Number types:
This shows, for example, the four main subtypes of Real number: AbstractFloat, Integer, Rational, and Irrational, as seen in the tree diagram.

### Specifying the type of variables

We've already seen that Julia does its best to work out the types of things you put in your code, if you don't specify them:
And we've also seen that you can specify the type for a new empty array:
For variables, you can specify the type that its value must have. For technical reasons, you can't do this at the top level, in the REPL—you can only do it inside a definition. The syntax uses the :: syntax, which means "is of type". So:
means that the function f has a method that accepts an argument x which is expected to be an Int64. See Functions.

#### Type stability

Here's an example of how the performance of Julia code is affected by the choice of types for variables. This is some code for exploring the Collatz conjecture.
We can time this, using the @time macro (although better benchmarking tools are available with the BenchmarkTools package).
There are two lines of code which prevent the functions from being "type stable". These are places where the compiler is unable to use the best and most efficient types for the task in hand. Can you spot them?
The first is the division of n by 2, after testing whether n is even. n starts out as an integer, but the / division operator always returns a floating-point value. The Julia compiler can't produce pure integer code or pure floating-point code, and has to decide which to use at each stage. As a result, the compiled code isn't as fast or as concise as it could be.
The second problem is the definition of the dictionary here. It's defined without type information, so both the keys and the values can be literally any type. While this is often OK, in this sort of task, where frequent accesses occur within loops, the additional tasks of maintaining the possibility of there being different types of keys and values makes the code more complex.
If we tell the Julia compiler that this dictionary is only to contain integers (which is a good assumption here), the compiled code will be much more efficient, and type stable.
So, after changing n /= 2 to n ÷= 2, and terms = Dict to terms = Dict{Int, Int}, we would expect the compiler to make much more efficient code, and indeed it's much faster:
You can get some tips from the compiler about possible issues in your code due to type instability. For this function, for example, you could enter @code_warntype main and look for items or "Any" highlighted in red.

## Creating types

In Julia, it's very easy for the programmer to create new types, benefiting from the same performance and language-wise integration that the native types (those made by Julia's creators) have.

#### Abstract types

Suppose we want to create an abstract type. To do this, we use Julia's keyword abstract followed by the name of the type you want to create:
By default, the type you create is a direct subtype of Any:
You can change this using the <: operator. If you want your new abstract type to be a subtype of Number, for example, you can declare:
Now, we get:
Notice that in the same Julia session (without exiting the REPL or ending the script) it's impossible to redefine a type. That's why we had to create a type called MyAbstractType2.

#### Concrete types and composite

You can create new composite types. To do this, use the struct or mutable structkeyword, which have the same syntax as declaring the supertype. The new type can contain multiple fields, where the object stores values. As an example, let's define a concrete type that is a subtype of MyAbstractType:
We just created a composite struct type called MyType, a subtype of MyAbstractType, with two fields: foo that can be of any type, and bar, that is of type Int.
How do we create an object of MyType? By default, Julia automatically creates a constructor, a function that returns an object of that type. The function has the same name of the type, and each argument of the function correspond to each field. In this example, we can create a new object by typing:
This creates a MyType object, assigning Hello World! to the foo field and 10 to the bar field. We can access x's fields by using the dot notation:
Also, we can change the field values of mutable structs easily:
Notice that, since we didn't specify foo's type when we created the type definition, we can change its type at any time. This is different when we try to change the type of the x.bar field (which we specified as being an Int according to MyType's definition):
The error message tells us that Julia couldn't change x.bar's type. This ensures type-stable code, and can provide better performance when programming. As a performance tip, specifying a field's type when defining your types is usually good practice.
The default constructor is used for simple cases, where you type something like typename(field1, field2) to produce a new instance of the type. But sometimes you want to do more when you construct a new instance, such as checking the incoming values. For this you can use an inner constructor, a function inside the type definition. The next section shows a practical example.

### Example: British currency

Here's an example of how you can create a simple composite type that can handle the old-fashioned British currency. Before Britain saw the light and introduced a decimal currency, the monetary system used pounds, shillings, and pence, where a pound consisted of 20 shillings, and a shilling consisted of 12 pence. This was called the £sd or LSD system (Latin for Librae, Solidii, Denarii, because the system originated in the Roman empire).
To define a suitable type, start a new composite type declaration:
To contain a price in pounds, shillings, and pence, this new type should contain three fields: pounds, shillings, and pence:
The important task is to create a constructor function. This has the same name as the type, and accepts three values as arguments. After a few checks for invalid values, the special new function creates a new object with the passed-in values. Remember we're still inside the type definition—this is an inner constructor.
Now we can finish the type definition:
Here's the complete type definition again:
It's now possible to create new objects that store old-fashioned British prices. You create a new object of this type by using its name (which calls the constructor function):
And you can't create bad prices, because of the simple checks added to the constructor function:
If you inspect the fields of one of the price 'objects' we've created:
you can see the three fields, and these are storing the values:
The next task is to make this new type behave in the same way as other Julia objects. For example, we can't add two prices:
and the output could definitely be improved:
Julia already has the addition function (+) with methods defined for many types of object. The following code adds yet another method that can handle two LSD objects:
This definition teaches Julia how to handle the new LSD objects, and adds a new method to the + function, one that accepts two LSD objects, adds them together, and produces a new LSD object containing the sum.
Now you can add two prices:
which is indeed the result of adding LSD(5,10,6) and LSD(1,6,8).
The next problem to address is the unattractive presentation of LSD objects. This is fixed in exactly the same way, by adding a new method, but this time to the show function, which belongs to the Base environment:
Here, the io is the output channel currently used by all show methods. We've added a simple expression that displays the field values with appropriate punctuation and separators.
You can add one or more aliases, which are alternative names for a particular type. Since Price is a better way of saying LSD, we'll create an valid alternative:
So far, so good, but these LSD objects are still not yet fully developed. If you want to do subtraction, multiplication, and division, you have to define additional methods for these functions for handling LSDs. Subtraction is easy enough, just requiring some fiddling with shillings and pence, so we'll leave that for now, but what about multiplication? Multiplying a price by a number involves two types of object, one a Price/LSD object, the other - well, any positive real number should be possible:
Like the + method we added to Base's + function, this new * method for Base's * function is defined specifically to multiply a price by a number. It works surprisingly well for a first attempt:
However, some failures are to be expected. We didn't allow for the really old-fashioned fractions of a penny: the halfpenny and the farthing:
(The answer should be £1.7s.7½d. Unfortunately our LSD type doesn't allow fractions of a penny.)
But there's another, more pressing, problem. At the moment you have to give the price followed by the multiplier; the other way round fails:
This is because, although Julia can find a method that matches (a::LSD, b::Number), it can't find one the other way round: (a::Number, b::LSD). But adding it is very easy:
which adds yet another method to Base's * function.
The prices are now looking like an old British shop from the 19th century, forsooth!
If you want to see how many methods you've added for working with this old British pounds type so far, use the methodswith function:
Just four so far.... And you can continue to add methods to make the type more generally useful—it would depend on how you envisage yourself or others using it. For example, you probably want to add division and modulo methods, and to act intelligently about negative monetary values.

#### Mutable structs

This composite type for holding British prices was defined as an immutable type. You can't change the values of these price objects once you've created them:
To create a new price based on an existing one, you'd have to do this:
For this particular example this isn't a big problem, but there are many applications when you might want to modify or update the value of a field in a type, rather than create a new one with the right values.
For these cases, you'd want to create a mutable struct. Choose between struct and mutable struct depending on the requirements made on the type.
For more about modules, and importing functions from other modules, see Modules and packages.

# Controlling the Flow
### Different ways to control the flow

Typically each line of a Julia program is evaluated in turn. There are various ways to control and modify the flow of evaluation. These correspond with the constructs used in other languages:
* ternary and compound expressions
* Boolean switching expressions
* if elseif else end — conditional evaluation
* for end — iterative evaluation
* while end — iterative conditional evaluation
* try catch error throw exception handling
* do blocks

### Ternary expressions

Often you'll want to do job A (or call function A) if some condition is true, or job B (function B) if it isn't. The quickest way to write this is using the ternary operator ("?" and ":"):
Here's another example:
and Julia returned the value of sin(x), because x was less than 0.5. cos(x) wasn't evaluated at all.

### Boolean switching expressions

Boolean operators let you evaluate an expression if a condition is true. You can combine the condition and expression using && or ||. && means "and", and || means "or". Since Julia evaluates expressions one by one, you can easily arrange for an expression to be evaluated only if a previous condition is true or false.
The following example uses a Julia function that returns true or false depending on whether the number is odd: isodd(n).
With &&, both parts have to be true, so we can write this:
If the first condition (number is odd) is true, the second expression is evaluated. If the first isn't true, the expression isn't evaluated, and just the condition is returned.
With the || operator, on the other hand:
If the first condition is true, there's no need to evaluate the second expression, since we already have the one truth value we need for "or", and it returns the value true. If the first condition is false, the second expression is evaluated, because that one might turn out to be true.
This type of evaluation is also called "short-circuit evaluation".

### If and Else

For a more general — and traditional — approach to conditional execution, you can use if, elseif, and else. If you're used to other languages, don't worry about white space, braces, indentation, brackets, semicolons, or anything like that, but remember to finish the conditional construction with end.
The elseif and else parts are optional too:
Just don't forget the end!
How about 'switch' and 'case' statements? Well, you don't have to learn the syntax for those, because they don't exist!

#### ifelse

There's an ifelse function, too. It looks like this in action:
ifelse is an ordinary function, which evaluates all the arguments, and returns the second or third, depending on the value of the first. With the conditional if or ? ... :, only the expressions in the chosen route are evaluated. Alternatively, it is possible to write things like:

### For loops and iteration

Working through a list or a set of values or from a start value to a finish value are all examples of iteration, and the for ... end construction can let you iterate through a number of different types of object, including ranges, arrays, sets, dictionaries, and strings.
Here's the standard syntax for a simple iteration through a range of values:
The variable i takes the value of each element in the array (which is built from a range object) in turn — here stepping from 0 to 100 in steps of 10.
We haven't yet met sets and dictionaries, but iterating through them is exactly the same.
You can iterate through a 2D array, stepping "down" through column 1 from top to bottom, then through column 2, and so on:
You can use = instead of in.

##### Iterating over an array and updating it

When you're iterating over an array, the array is checked each time through the loop, in case it's changed. A mistake you should avoid making is to use push! to make an array grow in the middle of a loop. Run the following text carefully, and be ready to Ctrl-C when you've seen enough (otherwise your computer will eventually crash):

#### Loop variables and scope

The variable that steps through each item—the 'loop variable'—exists only inside the loop, and disappears as soon as the loop finishes.
If you want to remember the value of the loop variable outside the loop (eg if you had to exit the loop and needed to know the value you'd reached), use the global keyword to define a variable that outlasts the loop.
Here, howfar didn't exist before the loop, but it survived to tell its story when the looping was over. If howfar existed before the loop started, you can change its value only if you use global in the loop.
Working in the REPL is slightly different from how you write code inside functions. In a function, you would write this:

#### Variables declared inside a loop

In a similar way, if you declare a new variable inside a loop, it won't exist once the loop finishes. In this example, k is created inside:
so it doesn't exist after the loop has finished:
Variables created inside one iteration of a loop are forgotten at the end of each iteration. In this loop:
z is created afresh each time. If you want a variable to persist from iteration to iteration, it has to be global:
To see this in more detail, consider the following code.
Perhaps you expected only the first loop to produce the "z isn't defined error"? In fact, even if z is created in the body of the loop, it is undefined at the start of the next iteration.
Again, use the global keyword to force z to be available outside the loop once it's been created:
although, if you're working in global scope, z is now available everywhere, with the value 10.
This behaviour is because we're working in the REPL. It's generally better practice to put your code inside functions, where you don't need to mark variables inherited from outside the loop as global:

#### Fine tuning the loop: Continue

Sometimes on a particular iteration you might want to skip to the next value. You can use continue to skip the rest of the code inside the loop and start the loop again with the next value.

#### Comprehensions

This oddly-named concept is simply a way of generating and collecting items. In mathematical circles you would say something like this:
In Julia, you can write this as:
and the [n for n in 1:10] construction is called array comprehension or list comprehension ('comprehension' in the sense of 'getting everything' rather than 'understanding'). The outer brackets collect together the elements generated by evaluating the expression placed before the for iteration. Instead of end, use a square bracket to finish.
The type of elements can be specified:
But Julia can work out the types of the results you're producing:
Here's how to make a dictionary via comprehension:
Next, here are two iterators in a comprehension, separated with a comma, which makes generating tables very easy. Here we're making a tuple-table:
r goes through five cycles, one cycle for every value of c. Nested loops work in the opposite manner. Here the column-major order is respected, as shown when the array is filled with nanosecond time values:
You can supply a test expression as well to filter the production. For example, produce all the integers between 1 and 100 that are exactly divisible by 7:

##### Generator expressions

Like comprehensions, generator expressions can be used to produce values from iterating a variable, but, unlike comprehensions, the values are produced on demand.

#### Enumerating arrays

Often you want to go through an array element by element while also keeping track of the index number of each element. The enumerate function gives you an iterable version of something, producing both an index number and the value at each index number:
The array is checked for possible changes at each iteration of the loop.

#### Zipping arrays

Sometimes you want to work through two or more arrays at the same time, taking the first element of each array first, then the second, and so on. This is possible using the well-named zip function:
You'd think it would all go wrong if the arrays were different sizes. What if the third array is too big, or too small?
but Julia isn't fooled — any oversupply or undersupply in any one of the arrays is handled gracefully.
This however does not work in case of filling of arrays, in this case dimensions must match:

#### Iterable objects

The "for something in something" construction is the same for everything that you can iterate through: arrays, dictionaries, strings, sets, ranges, and so on. In Julia this is a general principle: there are a number of ways in which you can create an "iterable object", an object that is designed to be used as part of the iteration process that provides the elements one at a time.
The most obvious example we've already met is the range object. It doesn't look much when you type it into the REPL:
But it gives you the numbers when you start iterating through it:
Should you want the numbers from a range (or other iterable object) in an array, you can use collect to collect them up:
You don't have to collect every element of an iterable object, you can just iterate through it. This can be particularly helpful when you have iterable objects created by other Julia functions. For example, permutations creates an iterable object containing all the permutations of an array. You could of course use collect to grab them and make a new array:
but on anything large there are going to hundreds or thousands of permutations. That's the reason why iterator objects don't produce all the values from the iteration at the same time: memory and performance. A range object doesn't take up much room, even if iterating over it might take ages, depending on how big the range is. If you generate all the numbers at once, rather than only producing them when they're needed, they would all have to be stored somewhere until you need them…
Julia provides iterable objects for working with other types of data. For example, when you're working with files, you can treat an open file as an iterable object:

##### Use eachindex

A common pattern when iterating through arrays is to perform some task for each value of i, where i is the index number of each element, not the element:
That is idiomatic Julia code and correct in all cases, and faster in some situations (than the alternative following code). A bad code pattern to do the same, in cases where it works (which isn't always), is:

###### Note for advanced users

For the purposes of this introduction, it's probably OK to assume that arrays and matrices are indexed starting at 1 (it's not for fully generic code, i.e. for introducing in registered packages). However, it's certainly possible to use other indexing bases in Julia — for example, the OffsetArrays.jl package lets you choose any starting index. It's a good idea to read the official documentation at once you start working with more advanced types of array indexing.

#### Even more iterators

There's a Julia package called IterTools.jl that provides some advanced iterator functions.
For example, partition groups the objects in the iterator into easily-handled chunks:
chain works through all the iterators one after the other:
subsets works through all subsets of an object. You can specify a size:

#### Nested loops

If you want to nest one loop inside another, you don't have to duplicate the for and end keywords. Just use a comma:
(The useful @show macro prints out the names of things and their values.)
One difference between the shorter and longer forms of nesting loops is the behaviour of break:
Notice that break breaks out of both inner and outer loops in the shorter form, but only out of the inner loop in the longer form.

#### Optimizing nested loops

With Julia, inner loops should concern rows rather than columns. This is due to how arrays are stored in memory. In this Julia array, for example, cells 1, 2, 3, and 4 are stored next to each other in memory (the 'column-major' format). So moving down the columns from 1 to 2 to 3 is faster than moving along rows, because jumping across from column to column, from 1 to 5 to 9, requires an extra calculation:
The following examples consist of simple loops, but the way the rows and columns are iterated differ. The "bad" version looks along the first row column by column, then moves down to the next row, and so on.
In the "good" version, the two loops are nested properly, so that the inner loop moves down through the rows, following the memory layout of the array:
Another way to increase the speed is to remove the array bounds checking, using the macro @inbounds:
Here's the test function:
and the results show the difference in performance just based on the row/column scanning order. The "no check" version is even faster....

### Making your own iterable objects

It's possible to design your own iterable objects. When you're defining your type, you add a couple of methods to Julia's iterate function. Then you can use something like for .. end loop to work through the components of your object, and these iterate methods are called automatically as necessary.
The following example shows how you can create an iterable object that generates the sequence of strings combining an uppercase letter with a number from 1 to 9. So the first item in our sequence is "A1", followed by "A2", "A3", up to "A9", then "B1", "B2", and so on, finishing at "Z9".
First, we'll define a new type called SN (StringNumber):
Later we'll create an iterable object of this type using something like this:
and the iterator will yield all the strings up to "Z9".
We must now add two methods to the iterate function. This function already exists in Julia (that's why you can iterate over all the basic data objects), so the Base prefix is required: we're adding a new method to the existing iterate function, one which is designed to handle these special objects.
The first method takes no arguments, except for the type, and is for starting the iteration process off.
This returns a tuple: the first value, and the future value of the iterator, which we've calculated (just in case we ever want to start the iterator at a point other than "A1").
The second method of iterate takes two arguments: an iterable object and the current state. It again returns a tuple of two values, the next item and the next state. But first, if there are no more values available, the iterate function should return nothing.
Telling the iterator when it's finished is easy, because as soon as the incoming state contains a "[" we've finished, because the code for "[" (91) is immediately after the code for "Z" (90).
With these two methods added to handle the SN type, it's now possible to iterate through them. It's also useful to add methods for a few other Base functions, such as show and length. The length method works out how many more SN strings are available starting at sn.
The iterator is now ready for use:

### While loops

To repeat some expressions while a condition is true, use the while ... end construction.
If you're working outside a function, you'll need the global declaration of x before you can change its value. Inside a function, you don't need global.
If you want the condition to be tested after the statements, rather than before, producing a "do .. until" form, use the following construction:
Here we're using a Boolean switch rather than an if ... end statement.

#### Template for while loops

Here is a basic template for a while loop that will run the function find_value repeatedly until it returns a value that's no greater than 0.
For example, with small changes this code explores the famous Collatz_conjecture
main(12) takes 9 attempts, whereas main(27) takes 111 attempts.
Using Julia's macros, you can create your own control structures. See Metaprogramming.

### Exceptions

If you want to write code that checks for errors and handles them gracefully, use the try ... catch construction.
With a catch phrase, you can handle problems that occur in your code, possibly allowing the program to continue rather than grind to a halt.
In the next example, our code attempts to change the first character of a string directly (which isn't allowed, because strings in Julia can't be modified in place):
The error function raises an error exception with a given message.

### Do block

Finally, let's look at a do block, which is another syntax form that, like the list comprehension, looks at first sight to be a bit backwards (i.e. it can perhaps be better understood by starting at the end and working towards the beginning).
Remember the find example from earlier?
The anonymous function (x -> isequal(13, x)) is the first argument of find, and it operates on the second. But with a do block, you can lift the function out and put it in between a do ... end block construction:
You just lose the arrow and change the order, putting the find function and its target argument first, then adding the anonymous function's arguments and body after the do.
The idea is that it's easier to write a longer anonymous function on multiple lines at the end of the form, rather than wedged in as the first argument.

# Functions
## Functions

Functions are the building blocks of Julia code, acting as the subroutines, procedures, blocks, and similar structural concepts found in other programming languages.
A function is a collected group of instructions that can return one or more values, possibly based on the input arguments. If the arguments contain mutable values like arrays, the array can be modified inside the function. By convention, an exclamation mark (!) at the end of a function's name indicates that the function may modify its arguments.
There are various syntaxes for defining functions:
* when the function contains a single expression
* when the function contains multiple expressions
* when the function doesn't need a name

### Single expression functions

To define a simple function, all you need to do is provide the function name and any arguments in parentheses on the left and an expression on the right of an equals sign. These are just like mathematical functions:

### Functions with multiple expressions

The syntax for defining a function with more than one expression is like this:
Here's a typical function that calls two other functions and then ends.
Whatever the value returned by the final expression — here, the brewcoffee function — that value is also returned by the breakfast function.
You can use the return keyword to indicate a specific value to be returned:
Some consider it good style to always use a return statement, even if it's not strictly necessary. Later we'll see how to make sure that the function doesn't go adrift if you call it with the wrong type of argument.

#### Returning more than one value from a function

To return more than one value from a function, use a tuple (explored in more detail in a later chapter).
Here you could write 6, 6 without parentheses.

### Optional arguments and variable number of arguments

You can define functions with optional arguments, so that the function can use sensible defaults if specific values aren't supplied. You provide a default symbol and value in the argument list:
And when you call this function, if you don't provide a third value, the variable z defaults to 0 and uses that value inside the function.

### Keyword and positional arguments

When you write a function with a long list of arguments like this:
sooner or later, you will forget the order in which you have to supply the arguments. For instance, it can be:
or
You can avoid this problem by using keywords to label arguments. Use a semicolon after the function's unlabelled arguments, and follow it with one or more keyword=value pairs:
When called, this function expects two arguments, and also accepts a number and a string, labelled r and s. If you don't supply the keyword arguments, their default values are used:
If you supply a keyword argument, it can be anywhere in the argument list, not just at the end or in the matching place.
When defining a function with keyword arguments, remember to insert a semicolon before the keyword/value pairs.
Here's another example from the Julia manual. The rtol keyword can appear anywhere in the list of arguments or it can be omitted:
A function definition can combine all the different kinds of arguments. Here's one with normal, optional, and keyword arguments:

### Functions with variable number of arguments

Functions can be defined so that they can accept any number of arguments:
The three dots indicate the famous splat. Here it means 'any', including 'none'. You can call this function with any number of arguments:
and so on.
Here's another example. Suppose you define a function that accepts two arguments:
You can call this in the usual way:
If you have the two numbers, but in a tuple, then how can you supply a single tuple of numbers to this two argument function? Again, the answer is to use the ellipsis (splat).
The use of the ellipsis or 'splat' is also referred to as 'splicing' the arguments:
You can also do this:

### Local variables and changing the values of arguments

Any variable you define inside a function will be forgotten when the function finishes.
If you want to keep values around across function calls, then you can think about using global variables.
A function can't modify an existing variable passed to it as an argument, but it can change the contents of a container passed to it. For example, here is a function that changes its argument to 5:
Although the x inside the function is changed, the x outside the function isn't. Variable names in functions are local to the function.
But a function can modify the contents of a container, such as an array. This function uses the [:] syntax to access the contents of the container x, rather than change the value of the variable x:
You can change elements of the array, but you can't change the variable so that it points to a different array. In other words, your function isn't allowed to change the binding of the argument.

### Anonymous functions

Sometimes you don't want to worry about thinking up a cool name for a function. Anonymous functions — functions with no name — can be used in a number of places in Julia, such as with map, and in list comprehensions.
The syntax uses ->, like this:
which defines a nameless function that takes an argument, calls it x, and returns x^2 + 2x - 1.
For example, the first argument of the map function is a function, and you can define an one-off function that exists just for one particular map operation:
After the map finishes, both the function and the argument x have disappeared:
If you want an anonymous function that accepts more than one argument, provide the arguments as a tuple:
Notice that the results are 12, 15, 18, rather than 6, 15, and 24. The anonymous function takes the first value of each of the three arrays and adds them, followed by the second, then the third.
In addition, anonymous functions can have zero arguments, if you use an 'empty' tuple:

### Map

If you already have a function and an array, you can call the function for each element of the array by using map. This calls the function on each element in turn, collects the results, and returns them in an array. This process is called mapping:
map returns a new array but if you call map! , you modify the contents of the original array.
Often, you don't have to use map to apply a function like sin to every member of an array, because many functions automatically operate "element-wise". The timings of the two different versions are similar (sin. has the edge perhaps, depending on the number of elements):
map collects the result of each application in an array and returns the array. Sometimes you might want the 'mapping' action but you don't want the results returned as an array. For this job, use foreach:
and ans is nothing (ans == nothing is true).

#### Map with multiple arrays

You can use map with more than one array. The function is applied to the first element of each of the arrays, then to the second, and so on. The arrays must be of the same length (unlike the zip function, which is more tolerant).
Here's an example which generates an array of imperial (non-metric) spanner/socket sizes. The second array is just a bunch of repeated 32s to match the integers from 5 to 24 in the first array. Julia simplifies the rationals for us:
(In reality, an imperial spanner set won't contain some of these strange sizes - I've never seen an old 17/32" spanner, but you can buy them online.)

#### Applying functions using the dot syntax

As well as map, it's possible to apply functions directly to arguments that are arrays. See the section on Dot syntax for vectorizing functions.

### Reduce and folding

The map function collects the results of some function working on each and every element of an iterable object, such as an array of numbers. The reduce function does a similar job, but after every element has been seen and processed by the function, only one is left. The function should take two arguments and return one. The array is reduced by continual application, so that just one is left.
A simple example is the use of reduce to sum the numbers in an iterable object (which works like the built-in function sum):
Internally, this does something similar to this:
After each operation adding two numbers, a single number is carried over to the next iteration. This process reduces all the numbers to a single final result.
A more useful example is when you want to apply a function to work on each consecutive pair in an iterable object. For example, here's a function that compares the length of two strings and returns the longer one:
This can be used to find the longest word in a sentence by working through the string, pair by pair:
"This" lasts a few rounds, and is then beaten by "sentence", but finally "containing" takes the lead, and there are no other challengers after that. If you want to see the magic happen, redefine l like this:
You can use an anonymous function to process an array pairwise. The trick is to make the function leave behind a value that will be used for the next iteration. This code takes an array such as [1, 2, 3, 4, 5, 6...] and returns [1 * 2, 2 * 3, 3 * 4, 4 * 5...], multiplying adjacent elements.

#### Folding

Julia also offers two related functions, foldl and foldr. These offer the same basic functionality as reduce. The differences are concerned with the direction in which the traversal occurs. In the simple summation example above, our best guess at what happened inside the reduce operation assumed that the first pair of elements were added first, followed by the second pair, and so on. However, it's also possible that reduce started at the end and worked towards the front. If it's important, use foldl for left to right, and foldr for right to left. In many cases, the results are the same, but here's an example where you'll get different results depending on which version you'll use:
Julia offers other functions in this group: check out mapreduce, mapfoldl, and mapfoldr.
If you want to use reduce and the fold- functions for functions that take only one argument, use a dummy second argument:
which is equivalent to calling the sqrt function four times:

### Functions that return functions

You can treat Julia functions in the same way as any other Julia object, particularly when it comes to returning them as the result of other functions.
For example, let's create a function-making function. Inside this function, a function called newfunction is created, and this will raise its argument (y) to the number that was originally passed in as the argument x. This new function is returned as the value of the create_exponent_function function.
Now we can construct lots of exponent-making functions. First, let's build a squarer function:
and a cuber function:
While we're at it, let's do a "raise to the power of 4" function (called quader, although I'm starting to struggle with the Latin and Greek naming):
These are ordinary Julia functions:
The definition of the create_exponent_function above is perfectly valid Julia code, but it's not idiomatic. For one thing, the return value doesn't always need to be provided explicitly — the final evaluation is returned if return isn't used. Also, in this case, the full form of the function definition can be replaced with the shorter one-line version. This gives the concise version:
which acts in the same way.
Here's another example of making functions. To make it easier to see what the code is doing, here is the make_counter function written in a slightly different manner:

### Function chaining and composition

Functions in Julia can be used in combination with each other.
Function composition is when you apply two or more functions to arguments. You use the function composition operator (∘) to compose the functions. (You can type the composition operator at the REPL using \circ). For example, the sqrt and + functions can be composed like this:
which adds the numbers first, then finds the square root.
This example composes three functions.
Function chaining (sometimes called "piping" or "using a pipe to send data to a subsequent function") is when you apply a function to the previous function's output:
where the total produced by sum is passed to the sqrt function. The equivalent composition is:
Piping can send data to a function that accepts a single argument. If the function requires more than one argument, you may be able to use an anonymous function:

## Methods

A function can have one or more different methods of doing a similar job. Each method usually concentrates on doing the job for a particular type.
Here is a function to check a longitude when you type in a location:
The message ("generic function with 1 method") you see if you define this in the REPL tells you that there is currently one way you can call the check_longitude_1 function. If you call this function and supply a number, it works fine.
But what happens when you type in a longitude in, say, the format seen on Google Maps:
The error tells us that the function has stopped because the concept of less than (<), which we are using inside our function, makes no sense if one argument is a string and the other a number. Strings are not less than or greater than integers because they are two different things, so the function fails at that point.
Notice that the check_longitude_1 function did start executing, though. The argument loc could have been anything - a string, a floating point number, an integer, a symbol, or even an array. There are many ways for this function to fail. This is not the best way to write code!
To fix this problem, we might be tempted to add code that tests the incoming value, so that strings are handled differently. But Julia proposes a better alternative: methods and multiple dispatch.
In the case where the longitude is supplied as a numeric value, the loc argument is defined as 'being of type Real'. Let's start again, define a new function, and do it properly:
Now this check_longitude function doesn't even run if the value in loc isn't a real number. The problems of what to do when the value is a string is avoided. With a type Real, this particular method can be called with any argument provided that it is some kind of number.
We can use the applicable function to test this. applicable lets you know whether you can apply a function to an argument — i.e. whether there is an available method for the function for arguments with that type:
The false indicates that you can't pass a string value to the check_longitude function because there is no method for this function that accepts a string:
Now the body of the function isn't even looked at — Julia doesn't know a method for calling check_longitude function with a string argument.
The obvious next step is to add another method for the check_longitude function, only this time one that accepts a string argument. In this way, a function can be given a number of alternative methods: one for numeric arguments, one for string arguments, and so on. Julia selects and runs one of the available methods depending on the types of arguments you provide to a function.
This is multiple dispatch.
Now the check_longitude function has two methods. The code to run depends on the types of the arguments you provide to the function. And you can avoid testing the types of arguments at the start of this function, because Julia only dispatches the flow to the string-handling method if loc is a string.
You can use the built-in methods function to find out how many methods you have defined for a particular function.
An instructive example is to see how many different methods the + function has:
This is a long list of every method currently defined for the + function; there are many different types of thing that you can add together, including arrays, matrices, and dates. If you design your own types, you might well want to write a function that adds two of them together.
Julia chooses "the most specific method" to handle the types of arguments. In the case of check_longitude, we have two specific methods, but we could define a more general method:
This method of check_longitude is called when the loc argument is neither a Real number or a String. It is the most general method, and won't be called at all if a more specific method is available.

## Type parameters in method definitions

It's possible to work with type information in method definitions. Here's a simple example:
The test method automatically extracts the type of the single argument a passed to it and stores it in the 'variable' T. For this function, the definition of T was where T is a subtype of Real, so the type of T must be a subtype of the Real type (it can be any real number, but not a complex number). 'T' can be used like any other variable — in this method it's just printed out using string interpolation. (It doesn't have to be T, but it nearly always is!)
This mechanism is useful when you want to constrain the arguments of a particular method definition to be of a particular type. For example, the type of argument a must belong to the Real number supertype, so this test method doesn't apply when a isn't a number, because then the type of the argument isn't a subtype of Real:
Here's an example where you might want to write a method definition that applies to all one-dimensional integer arrays. It finds all the odd numbers in an array:
but can't be used for arrays of real numbers:
Note that, in this simple example, because you're not using the type information inside the method definition, you might be better off sticking to the simpler way of defining methods, by adding type information to the arguments:
But if you wanted to do things inside the method that depended on the types of the arguments, then the type parameters approach will be useful.

# Dictionaries and Sets
## Dictionaries

Many of the functions introduced so far have been shown working on arrays (and tuples). But arrays are just one type of collection. Julia has others.
A simple look-up table is a useful way of organizing many types of data: given a single piece of information, such as a number, string, or symbol, called the key, what is the corresponding data value? For this purpose, Julia provides the Dictionary object, called Dict for short. It's an "associative collection" because it associates keys with values.

### Creating dictionaries

You can create a simple dictionary using the following syntax:
dict is now a dictionary. The keys are "a", "b", and "c", the corresponding values are 1, 2, and 3. The => operator is called the Pair function. In a dictionary, keys are always unique – you can't have two keys with the same name.
If you know the types of the keys and values in advance, you can (and probably should) specify them after the Dict keyword, in curly braces:
You can also create dictionaries using the generator/comprehensions syntax:
Use the following syntax to create a typed empty dictionary:
or you can omit the types, and get an untyped dictionary:
It's sometimes useful to create dictionary entries using a for loop:
This is one way you could create a set of 'variables' stored in a dictionary:

### Looking things up

To get a value, if you have the key:
if the keys are strings. Or, if the keys are symbols:
Or if the keys are integers:
You can instead use the get function, and provide a fail-safe default value if there's no value for that particular key:
If you don't want get to provide a default value, use a try...catch block:
To change a value assigned to an existing key (or assign a value to a hitherto unseen key):

#### Keys

Keys must be unique for a dictionary. There's always only one key called a in this dictionary, so when you assign a value to a key that already exists, you're not creating a new one, just modifying an existing one.
To see if the dictionary contains a key, use haskey:
To check for the existence of a key/value pair:
To add a new key and value to a dictionary, use this:
You can delete a key from the dictionary, using delete!:
You'll notice that the dictionary doesn't seem to be sorted in any way — at least, the keys are in no particular order. This is due to the way they're stored, and you can't sort them in place. (But see Sorting, below.)
To get all keys, use the keys function:
The result is an iterator that has just one job: to iterate through a dictionary key by key:
This uses the list comprehension form ([ new-element for loop-variable in iterator ]) and each new element is collected into an array. An alternative would be:

#### Values

To retrieve all the values, use the values function:
If you want to go through a dictionary and process each key/value, you can make use the fact that dictionaries themselves are iterable objects:
where kv is a tuple containing each key/value pair in turn.
Or you could do:
Even better, you can use a key/value tuple to simplify the iteration even more:
Here's another example:
(Notice the string interpolation operator, $. This allows you to use a variable's name in a string and get the variable's value when the string is printed. You can include any Julia expression in a string using $.)

### Sorting a dictionary

Because dictionaries don't store the keys in any particular order, you might want to output the dictionary to a sorted array to obtain the items in order:
If you really need to have a dictionary that remains sorted all the time, you can use the SortedDict data type from the DataStructures.jl package (after having installed it).
Recent versions of Julia sort dictionaries for you:

### Simple example: counting words

A simple application of a dictionary is to count how many times each word appears in a piece of text. Each word is a key, and the value of the key is the number of times that word appears in the text.
Let's count the words in the Sherlock Holmes stories. I've downloaded the text from the excellent Project Gutenberg and stored them in a file "sherlock-holmes-canon.txt". To create a list of words from the loaded text in canon, we'll split the text using a regular expression, and convert every word to lowercase. (There are probably faster methods.)
wordlist is now an array of nearly 700,000 words:
To store the words and the word counts, we'll create a dictionary:
To build the dictionary, loop through the list of words, and use get to look up the current tally, if any. If the word has already been seen, the count can be increased. If the word hasn't been seen before, the fall-back third argument of get ensures that the absence doesn't cause an error, and 1 is stored instead.
Now you can look up words in the wordcounts dictionary and find out how many times they appear:
Dictionaries aren't sorted, but you can use the collect and keys functions on the dictionary to collect the keys and then sort them. In a loop you can work through the dictionary in alphabetical order:
But how do you find out the most common words? One way is to use collect to convert the dictionary to an array of tuples, and then to sort the array by looking at the last value of each tuple:
To see only the top 20 words:
In a similar way, you can use the filter function to find, for example, all words that start with "k" and occur less than four times:

### More complex structures

A dictionary can hold many different types of values. Here for example is a dictionary where the keys are strings and the values are arrays of arrays of points (assuming that the Point type has been defined already). For example, this could be used to store graphical shapes describing the letters of the alphabet (some of which have two or more loops):
Or create a dictionary with some already-known values:
Add another array to the first one:

## Sets

A set is a collection of elements, just like an array or dictionary, with no duplicated elements.
The two important differences between a set and other types of collection is that in a set you can have only one of each element, and, in a set, the order of elements isn't important (whereas an array can have multiple copies of an element and their order is remembered).
You can create an empty set using the Set constructor function:
As elsewhere in Julia, you can specify the type:
You can create and fill sets in one go:
or you can let Julia "guess the type":
Quite a few of the functions that work with arrays also work with sets. Adding elements to sets, for example, is a bit like adding elements to arrays. You can use push!:
But you can't use pushfirst!, because that works only for things that have a concept of "first", like arrays.
What happens if you try to add something to the set that's already there? Absolutely nothing. You don't get a copy added, because it's a set, not an array, and sets don't store repeated elements.
To see if something is in the set, you can use in:
There are some standard operations you can do with sets, namely find their union, intersection, and difference, with the functions, union, intersect, and setdiff:
The union of two sets is the set of everything that is in one or the other sets. The result is another set – so you can't have two "yellow"s here, even though we've got a "yellow" in each set:
The intersection of two sets is the set that contains every element that belongs to both sets:
The difference between two sets is the set of elements that are in the first set, but not in the second. This time, the order in which you supply the sets matters. The setdiff function finds the elements that are in the first set, colors, but not in the second set, rainbow:

## Other functions

Functions that work on arrays and sets sometimes work on dictionaries and other collections too. For example, some of the set operations can be applied to dictionaries, not just sets and arrays:
Notice that the results are returned as arrays of Pairs, rather than as Dictionaries.
Functions such as filter, map, and collect which we've already seen being used with arrays also work with dictionaries:
There's a merge function which can merge two dictionaries:
The findmin function can find the minimum value in a dictionary, and return the value, and its key.

# Strings and Characters
## Strings and characters
### Strings

A string is a sequence of one or more characters, usually found enclosed in double quotes:
There are two important things you need to know about strings.
One is, that they're immutable. You can't change them once they're created. But it's easy to make new strings from parts of existing ones.
The second is that you have to be careful when using two specific characters: double quotes ("), and dollar signs ($). If you want to include a double quote character in the string, it has to be preceded with a backslash, otherwise the rest of the string would be interpreted as Julia code, with potentially interesting results. And if you want to include a dollar sign ($) in a string, that should also be prefaced by a backslash, because it's used for string interpolation.
Strings can also be enclosed in triple double quotes. This is useful because you can use ordinary double quotes inside the string without having to put backslashes before them:
You'll encounter a few specialized types of string too, which consist of one or more characters immediately followed by the opening double quote:
* r" " indicates a regular expression
* v" " indicates a version string
* b" " indicates a byte literal
* raw" " indicates a raw string that doesn't do interpolation

### String interpolation

You often want to use the results of Julia expressions inside strings. For example, suppose you want to say:
where n is the current value of x. Any Julia expression can be inserted into a string with the $ construction:
You don't have to use the parentheses if you're just using the name of a variable:
To include the result of a Julia expression in a string, enclose the expression in parentheses first, then precede it with a dollar sign:

### Substrings

To extract a smaller string from a string, use getindex(s, range) or s[range] syntax. For basic ASCII strings, you can use the same techniques that you use to extract elements from arrays:
which is equivalent to:
You can easily iterate through a string:
Watch out if you take a single element from the string, rather than a string of length 1 (i.e. with the same start and end positions):
The second result isn't a string, but a character (inside single quotes).

#### Unicode strings

Not all strings are ASCII. To access individual characters in Unicode strings, you can't always use simple indexing, because some characters occupy more than one index position. Don't be fooled just because some of the index numbers appear to work:
Instead of length(str) to find the length of a string, use lastindex(str):
The isascii functions tests whether a string is ASCII or contains Unicode characters:
In this string, the 'second' character, é, has 2 bytes, the 'fourth' character, 𐅍, has 4 bytes.
The 'third' character, B, starts with the 4th element in the string.
You can also do this even more easily using the pairs function:
As an alternative, use the eachindex iterator:
There are other useful functions for working with strings like this, including collect, thisind, nextind, and prevind:

### Splitting and joining strings

You can stick strings together (a process often called concatenation) using the multiply (*) operator:
If you've used other programming languages, you might expect to use the addition (+) operator:
- so use *.
If you can 'multiply' strings, you can also raise them to a power:
You can also use string:
but if you want to do a lot of concatenation, inside a loop, perhaps, it might be better to use the string buffer approach (see below).
To split a string, use split function. Given this simple string:
a simple call to the split function divides the string at the spaces, returning a five-piece array:
Or you can specify the string of 1 or more characters to split at:
The characters you use to do the splitting don't appear in the final result:
If you want to split a string into separate single-character strings, use the empty string ("") which splits the string between the characters:
You can also split strings using a regular expression to define the splitting points. Use the special regex string construction r" ". Inside this, you can use regular expression characters with special meanings:
Here, the r"a|e|i|o|u" is a regular expression string, and — as you'll know if you love regular expressions — that this matches any of the vowels. So the resulting array consists of the string split at every vowel. Notice the empty strings in the results -— if you don't want those, add a false flag at the end:
If you wanted to keep the vowels, rather than use them for splitting work, you have to delve deeper into the world of regex literal strings. Read on.
You can join the elements of a split string in array form using join:

#### Splitting using a function

Many functions in Julia let you use functions as part of a function call. Anonymous functions are useful, because you can make function calls which have smart choices built-in. For example, split lets you provide a function in place of the delimiter character. In the next example, the delimiter is (bizarrely) specified to be any upper-case character whose ASCII code is a multiple of 8:

### Character objects

Above we extracted smaller strings from larger strings:
But when we extracted a single element from a string:
note the single quotes. In Julia, these are used to mark character objects, so 'a' is a character object, but "a" is a string with length 1. These are not equivalent.
You can convert character objects to strings easily enough:
or
It's easy to input 32 bits Unicode characters using \U escape sequence (the uppercase means 32 bits). The lowercase escape sequence \u can be used for 16 and 8 bit characters:
For strings, the \Uxxxxxxxx and \uxxxx syntax is more strict.

### Converting between numbers and strings

Turning integers into strings is the job of the string function. The keyword base lets you specify the number base for the conversion, which you can use to convert decimal digits to a binary, octal, or hexadecimal string:
To convert strings to numbers, use parse, and you can also specify the number base (such as binary or hex) if you want the string to be interpreted as using a number base:

### Converting characters to integers and back again

Int converts a character into an integer, and Char turns an integer into a character.
To go from a single character string to the code number (such as its ASCII or UTF code number), try this:
For a quick alphabet:

### printf formatting

If you're deeply attached to C-style printf functionality, you'll be able to use a Julia macro (you call macros by prefacing them with the @ sign). The macro is provided in the Printf package, which you'll need to load first:
or you can create another string using the sprintf macro, also to be found in the Printf package:

### Convert a string to an array

To read from a string into an array, you can use the IOBuffer function. This is available with a number of Julia functions (including printf). Here's a string of data (it could have been read from a file):
Now you can "read" this string using functions such as readdlm, the "read with delimiters" function. This can be found in the package DelimitedFiles.
You can add an optional type specification:
Sometimes you want to do things to strings that you can do better with arrays. Here's an example.
You can explode the pathname string into an array of character objects, using collect, which gathers the items in a collection or string into an array:
Similarly, you can use split to split the string and count the results:
To count the occurrences of a particular character object, you can use an anonymous function:
although here converting to an array is unnecessary and inefficient. Here's a better way:

### Finding and replacing things inside strings

If you want to know whether a string contains a specific character, use the general-purpose in function.
But the occursin function, which accepts two strings, is more generally useful, because you can use substrings with one or more characters. Notice that you place the search term first, then the string you're looking in — occursin(needle, haystack):
You can get the location of the first occurrence of a substring using findfirst(needle, haystack). The first argument can be a single character, a string, or a regular expression:
In each case, the result contains the indices of the characters, if present.

#### Replacing

The replace function returns a new string with a substring of characters replaced with something else:
You use the => operator to specify the pattern you're looking for, and its replacement. Usually the third argument is another string, as here. But you can also supply a function that processes the result:
where the function (here, the built-in uppercase function) is applied to the matching substring.
There's no replace! function, where the "!" indicates a function that changes its argument. That's because you can't change a string — they're immutable.

##### Replacing using functions

Many functions in Julia allow you to supply functions as part of the function call, and you can make good use of anonymous functions for this. Here, for example, is how to use a function to provide random replacements in a replace function.

### Regular expressions

You can use regular expressions to find matches for substrings. Some functions that accept a regular expression are:
* replace changes occurrences of regular expressions
* match returns the first match or nothing
* eachmatch returns an iterator that lets you search through all matches
* split splits a string at every match
Use replace to replace each consonant with an underscore:
and the following code replaces each vowel with the results of running a function on each match:
With replace you can access the matches if you provide a special substitution string s"", where \1 refers to the first match, \2 to the second, and so on. With this regex operation, each lowercase letter preceded by a space is repeated three times:
For more regular expression fun, there are the -match- functions.
Here I've loaded the complete text of "The Adventures of Sherlock Holmes" from a file into the string called text:
To use the possibility of a match as a Boolean condition, suitable for use in an if statement for example, use occursin.
That's odd. We were expecting to find evidence of the great detective's peculiar pharmacological recreations. In fact, the word "opium" does appear in the text, but only in lower-case, hence this false result—regular expressions are case-sensitive.
This is a case-insensitive search, set by the flag (?i)), and it returns true.
You could check every line for the word using a simple loop:
For more useable output (in the REPL), add enumerate and some highlighting:
There's an alternative syntax for adding regex modifiers, such as case-insensitive matches. Notice the "i" immediately following the regex string in the second example:
With the eachmatch function, you apply the regex to the string to produce an iterator. For example, to look for substrings in our text matching the letters "L", followed by some other characters, ending with "ed":
The result in lmatch is an iterable object containing all the matches, as RegexMatch objects:
We can step through the iterator and look at each match in turn. You can access a number of fields of a RegexMatch, to extract information about the match. These include captures, match, offset, offsets, and regex. For example, the match field contains the matched substring:
Other fields include captures, the captured substrings as an array of strings, offset, the offset into the string at which the whole match begins, and offsets, the offsets of the captured substrings.
To get an array of matching strings, use something like this:
The basic match function looks for the first match for your regex. Use the match field to extract the information from the RegexMatch object:
A more streamlined way of obtaining matching lines from a file is this:

#### Making a Regex

Sometimes you want to make a regular expression from within your code. You can do this by making a Regex object. Here is one way you could count the number of vowels in the text:

##### Making a substitution string

Sometimes you'll want to assemble a substitution string. To do this, you can use SubstitutionString instead of s"...".
For example, say you want to do some string interpolation in the replacement string. Perhaps you have a list of files, and you want to renumber them, so that "file2.png" becomes "file1.png":
Notice that you can't simply use \1 in the SubstitutionString to refer to the first captured expression, you have to escape it as \\1, and use \g (escaped as \\g) to refer to the named capture group.

### Testing and changing strings

There are lots of functions for testing and changing strings:
* length(str) length of string
* sizeof(str) length/size
* startswith(strA, strB) does strA start with strB?
* endswith(strA, strB) does strA end with strB?
* occursin(strA, strB) does strA occur in strB?
* all(isletter, str) is str entirely letters?
* all(isnumeric, str) is str entirely number characters?
* isascii(str) is str ASCII?
* all(iscntrl, str) is str entirely control characters?
* all(isdigit, str) is str 0-9?
* all(ispunct, str) does str consist of punctuation?
* all(isspace, str) is str whitespace characters?
* all(isuppercase, str) is str uppercase?
* all(islowercase, str) is str entirely lowercase?
* all(isxdigit, str) is str entirely hexadecimal digits?
* uppercase(str) return a copy of str converted to uppercase
* lowercase(str) return a copy of str converted to lowercase
* titlecase(str) return copy of str with the first character of each word converted to uppercase
* uppercasefirst(str) return copy of str with first character converted to uppercase
* lowercasefirst(str) return copy of str with first character converted to lowercase
* chop(str) return a copy with the last character removed
* chomp(str) return a copy with the last character removed only if it's a newline

### Streams

To write to a string, you can use a Julia stream. The sprint (String Print) function lets you use a function as the first argument, and uses the function and the rest of the arguments to send information to a stream, returning the result as a string.
For example, consider the following function, f. The body of the function maps an anonymous 'print' function over the arguments, enclosing them with angle brackets. When used by sprint, the function f processes the remaining arguments and sends them to the stream.
Functions like println can take an IOBuffer or stream as their first argument. This lets you print to streams instead of printing to the standard output device:
After this, the in-memory stream called iobuffer is full of numbers and newlines, even though nothing was printed on the terminal. To copy the contents of iobuffer from the stream to a string or array, you can use take!:

### Colored / Styled Output

The following prints out messages in their respective colors using printstyled:

### Printing a formatted Backtrace

In the middle of a try catch statement, the following will print the original backtrace that caused the exception:
If you are outside a try-catch and want to print a stacktrace without throwing stopping execution use this:

# Working with Text Files
## Reading from files

The standard approach for getting information from a text file is using the open, read, and close functions.

### Open

To read text from a file, first obtain a file handle:
f is now Julia's connection to the file on disk. When you've finished with the file, you should close the connection, using:
In general, the recommended way to work with a file in Julia is to wrap any file-processing functions inside a do block:
The open file is automatically closed when this block finishes. See Controlling the flow for more about do blocks.
Because of the scope of local variables in blocks, you might want to keep some of information that was processed:

### Slurp – reading a file all at once

You can read the entire contents of an open file at once with read:
This stores the contents of the file in s:
You can use readlines to read in the whole file as an array, with each line an element:
Now you can step through the lines:
There's a better way to do this – see enumerate, below.
You might find the chomp function useful – it removes the trailing newline from a string.

### Line by line

The eachline function turns a source into an iterator. This allows you to process a file a line at a time:
Another approach is to read until you reach the end of the file. You might want to keep track of which line you're on:
A better approach is to use enumerate on an iterable object – you'll get the line numbering 'for free':
If you have a specific function that you want to call on a file, you can use this alternative syntax:
This opens the file, runs the shout function on it, then closes it again, assigning the processed contents to the variable.
You can use the CSV.jl to read and write comma-separated-values (.csv) files, and it's recommended over (handles more corner cases and can be faster, especially for larger files) using DelimitedFiles.readdlm function to read lines delimited with certain characters, such as data files, arrays stored as text files, and tables. If you use the DataFrames package, there's also a readtable specifically designed to read data into a table.

## Working with paths and filenames

These functions will be useful for working with filenames:
* cd(path) changes the current directory.
* pwd gets the current working directory.
* readdir(path) returns a lists of the contents of a named directory, or the current directory.
* abspath(path) adds the current directory's path to a filename to make an absolute pathname.
* joinpath(str, str, ...) assembles a pathname from pieces.
* isdir(path) tells you whether the path is a directory.
* splitdir(path) – split a path into a tuple of the directory name and file name.
* splitdrive(path) – on Windows, split a path into the drive letter part and the path part. On Unix systems, the first component is always the empty string.
* splitext(path) – if the last component of a path contains a dot, split the path into everything before the dot and everything including and after the dot. Otherwise, return a tuple of the argument unmodified and the empty string.
* expanduser(path) – replaces a tilde character at the start of a path with the current user's home directory.
* normpath(path) – normalizes a path, removing "." and ".." entries.
* realpath(path) – canonicalizes a path by expanding symbolic links and removing "." and ".." entries.
* homedir – gets current user's home directory.
* dirname(path) – gets the directory part of a path.
* basename(path) – gets the file name part of a path.
To work on a restricted selection of files in a directory, use filter and an anonymous function to filter the file names and just keep the ones you want. (filter is more of a fishing net or sieve, rather than a coffee filter, in that it catches what you want to keep.)
If you want to match a group of files using a regular expression, then use occursin. Let's look for files with ".jpg" or ".png" suffixes (remembering to escape the "."):
To examine a file hierarchy, use walkdir, which lets you work through a directory, and examine the files in each directory in turn.

### File information

If you want information about a specific file, use stat("pathname"), and then use one of the fields to find out the information. Here's how to get all the information and the field names listed for a file "i":
You can access these fields via a 'stat' structure:
and you can also use some of them directly:
although not size:
To work on specific files that meet conditions – all Jupyter files (i.e. files with the extension "ipynb") modified after a certain date, for example – you could use something like this:

### Interacting with the file system

The cp, mv, rm, and touch functions have the same names and functions as their Unix shell counterparts.
To convert filenames to pathnames, use abspath. You can map this over a list of files in a directory:
To restrict the list to filenames that contain a particular substring, use an anonymous function inside filter – something like this:
To restrict the list to regular expression matches, try this:

## Writing to files

To write to a text file, open it using the "w" flag and make sure that you have permission to create the file in the specified directory:
Here's how to write 20 lines of 4 random numbers between 1 and 10, separated by commas:
A quicker alternative to this is to use the DelimitedFiles.writedlm function, described next:

### Writing and reading array to and from a file

In the DelimitedFiles package are two convenient functions, writedlm and readdlm. These let you read/write an array or collection from/to a file.
writedlm writes the contents of an object to a text file, and readdlm reads the data from a file into an array:
You can see the file using the shell (type a semicolon ";" to switch):
The elements are separated by tabs unless you specify another delimiter. Here, a colon is used to delimit the numbers:
To read in data from a text file, you can use readdlm.
There are also a number of Julia packages specifically designed for reading and writing data to files, including DataFrames.jl and CSV.jl. Search in JuliaHub or JuliaPackages for these and more. Many of these packages live at the home of the JuliaData organization.

# Working with Dates and Times
## Working with dates and times

Functions for working with dates and times are provided in the standard package Dates. To use any of the time and date functions, you must do one of the following:
* using Dates
* import Dates
If you use import Dates functions, you’ll need to prefix every function with an explicit Dates., e.g. Dates.dayofweek(dt), as shown in this chapter. However, if you add the line using Dates to your code, this brings all exported Dates functions into Main, and they can be used without the Dates. prefix.

#### Types

This diagram shows the relationship between the various types used to store Times, Dates, and DateTimes.

### Date, Time, and DateTimes

There are three main datatypes available:
* A Dates.Time object represents a precise moment of time in a day. It doesn't say anything about the day of the week, or the year, though. It's accurate to a nanosecond.
* A Dates.Date object represents just a date: no time zones, no daylight saving issues, etc... It's accurate to, well, a day.
* A Dates.DateTime object is a combination of a date and a time of day, and so it specifies an exact moment in time. It's accurate to a millisecond or so.
Use one of these constructors to make the type of object you want:
The Dates.today function returns a Date object for the current date:
The Dates.now function returns a DateTime object for the current instant in time:
(We used Dates.now earlier to define rightnow, then converted it to a Dates.Time using Dates.Time.)
Sometimes you want UTC (the reference time for the world, without local adjustments for daylight savings):
To create an object from a formatted string, use the DateTime function in Dates, and supply a suitable format string that matches the formatting:
See Date Formatting below for more examples.

### Date and time queries

Once you have a date/time or date object, you can extract information from it with the following functions. For both date and datetime objects, you can obtain the year, month, day, and so on:
and, for date/time objects:
There's also a bunch of other useful ones:
Two of those functions are very similarly named: the Dates.daysofweekinmonth (days of week in month) function tells you how many days there are in the month with the same day name as the specified day — there are five Tuesdays in the current month (at the time of writing). The last function, dayofweekofmonth(birthday) (day of week of month), tells us that the 15th of March, 1997, was the third Saturday of the month.
You can also find days relative to a date, such as the first day of the week containing that day, using the adjusting functions, described below.

### Date arithmetic

You can do arithmetic on dates and date/time objects. Subtracting two dates or datetimes to find the difference is the most obvious one:
which you can convert to Dates.Days or Dates.Milliseconds or some other unit:
To add and subtract periods of time to date and date/time objects, use the Dates. constructor functions to specify the period. For example, Dates.Year(20) defines a period of 20 years, and Dates.Month(6) defines a period of 6 months. So, to add 20 years and 6 months to the birthday date:
Here's 6 months ago from now:
and similarly for months, weeks:
and similarly for weeks and hours. Here's the date and time for two weeks and 12 hours from now:
and there are
or 148 (shopping) days till Christmas (at the time this was written).
To retrieve the value as a number, use the function Dates.value:
This works with different types of date/time objects too:

### Range of dates

You can make iterable range objects that define a range of dates:
This iterator yields the first day of every third month. To find out which of these fall on weekdays, you can provide an anonymous function to filter that tests the day name against the given day names:
104-element Array{Date,1}:
Similarly, here's a range of times 3 hours apart from now, for a year hence:
If you have to pay a bill every 30 days, starting on the 1st of January 2018, the following code shows how the due date creeps forward every month:

### Date formatting

To specify date formats, you use date formatting codes in a formatting string. Each character refers to a date/time element:
You can use these formatting strings with functions such as DateTime and Dates.format. For example, you create a DateTime object from a string by identifying the different elements in the incoming string:
Other characters are used literally. In the second example, the formatting characters matched up as follows:
You can supply a format string to Dates.format to format a date object. In the formatting string, you repeat the characters to control how years and days, for example, are output:
When you're creating a formatted date, you can double some of the components of the format string to produce a leading zero for single digit date elements:
To convert a date string from one format to another, you can use DateTime and a format string to convert the string to a DateTime object, then DateFormat to output the object in a different format:
If you're doing a lot of date formatting (you can apply date functions to an array of strings), it's a good idea to pre-define a DateFormat object and then use that for bulk conversions (this is quicker):
There are some built-in formats that you can use. For example, there's Dates.ISODateTimeFormat to give you the ISO8601 format:
and here's good old RFC1123:

### Date adjustments

Sometimes you want to find a date nearest to another - for example, the first day of that week, or the last day of the month that contains that date. You can do this with the functions like Dates.firstdayofweek and Dates.lastdayofmonth. So, if we're currently in the middle of the week:
the first day of the week is returned by this:
which you could also write using the function chain operator:
A more general solution is provided by the tofirst, tolast, tonext, and toprev methods.
With tonext and toprev, you can provide a (possibly anonymous) function that returns true when a date has been correctly adjusted. For example, the function:
returns true if the day d is a Tuesday. Use this with the tonext method:
Or you can find the next Sunday following the birthday date:
With tofirst and tolast, you can find the first Sunday, or Thursday, or whatever, of a month. Monday is 1, Tuesday 2, etc.
Supply the keyword argument of=Year to get the first matching weekday of the year.

#### Rounding dates and times

You can use round, floor, and ceil, usually used to round numbers up or down to the nearest preferred values, to adjust dates forward or backwards in time so that they have 'rounder' values.
The ceil adjusts dates or times forward in time:

### Recurring dates

It's useful to be able to find all dates in a range of dates that satisfy some particular criteria. For example, you can work out the second Sunday in a month by using the Dates.dayofweekofmonth and Dates.dayname functions.
For example, let's create a range of dates from the first of September 2014 until Christmas Day, 2014:
Now an anonymous function similar to the ones we used in tonext earlier finds a selection of those dates in that range that satisfy that function:
These are the dates of every Sunday between September 1st 2014 until Christmas Day, 2014.
By combining criteria in the anonymous function, you can build up more complicated recurring events. Here's a list of all the Tuesdays in that period which are on days that are odd numbered and greater than 20:
and here's every second Tuesday in 2016 between April and November:

### Unix time

You sometimes have to deal with another type of timekeeping: Unix time. Unix time is a count of the number of seconds that have elapsed since the beginning of the year 1970 (the birth of Unix). In Julia the count is stored in a 64 bit integer, and we'll never see the end of Unix time. (The universe will have ended long before 64 bit Unix time reaches the maximum possible value, which will be in approximately 292 billion years from now, at 15:30:08 on Sunday, 4 December 292,277,026,596.)
In Julia, the time function, used without arguments, returns the Unix time value of the current second:
The strftime ("string format time") function, which lives in the Libc module, converts a number of seconds in Unix time to a more readable form:
You can choose a different format by supplying a format string, with the different components of the date and time defined by '%' letter codes:
The strptime function takes a format string and a date string, and returns a TmStruct expression. This can then be converted to a Unix time value by passing it to time:
The Dates module also offers a unix2datetime function, which converts a Unix time value to a date/time object:

### Moments in time

DateTimes are stored as milliseconds, in the field instant. Use Dates.value to obtain the value.
If you use the more precise Dates.Time type, you can access nanoseconds.

## Timing and monitoring

The @elapsed macro returns the number of seconds an expression took to evaluate:
The @time macro tells you how long an expression took to evaluate, and how memory was allocated.

# Plotting
## Plotting

There are a number of different packages for plotting in Julia, and there's probably one to suit your needs and tastes. This section is a quick introduction to one of them, Plots.jl, which is interesting because it talks to many of the other plotting packages. Before making plots with Julia, download and install the first plotting package or any or all to choose from (to get the prompt press ]):
The first package, Plots, is a high-level plotting package that interfaces with other plotting packages, which here are referred to as 'back-ends'. They act as the graphics "engines" that produce the graphics. Each of these is also a stand-alone plotting package, and can be used separately, but the advantage of using Plots as the interface is, as you'll see, a simpler and consistent interface.
See also the powerful Makie.jl, which is unrelated to Plots.jl, and has its own backends, such as GLMakie.jl, and many extensions such as AlgebraOfGraphics.jl (these are not explained more in the article, except for this installation example):
You can start using the Plots.jl package in a Julia session in the usual way:
You usually want to plot one or more series, arrays of numerical values. Alternatively, you can provide one or more functions to generate numerical values.
In this example, we'll plot the phases (illuminated fractions) of the moon for the month of May, 2022.
We now have an array of Float64 values, one for each hour of the month, representing how much of the moon's disk is illuminated:
To plot these series, just pass them to Plots' plot function.
This has used the first available plotting engine (GR.jl). Plots has added other plotting "furniture" and then plotted everything for you.
If you want to switch to a different engine, use one of the provided functions: gr, unicodeplots, plotly, and so on. For example, to switch to using the Unicodeplots plotting package (which uses Unicode characters to make plots, and is ideal for use in the REPL/terminal), do this:

## Customizing plots

There is copious documentation for the Plots.jl package, and after studying it you'll be able to spend hours tweaking and customizing your plots to your heart's content. Here's just one example of a plot of the equation of time for every day in a year.
The ticks along the x-axis are the numbers from 1:365. It would be better to see the dates themselves. First, create the strings:
The supplied value for the xticks option is a tuple consisting of two arrays/ranges:
the first provides the numerical values, the second provides matching text labels for the ticks.
Extra labels and legends are easily added. You can access colors from the Colors.jl package:

## Other packages
### UnicodePlots

If you work in the REPL a lot, perhaps you want a quick and easy way to draw plots that use text rather than graphics for output? The UnicodePlots.jl package uses Unicode characters to draw various plots, avoiding the need to load various graphic libraries. It can produce:
* scatter plots
* line plots
* bar plots (horizontal)
* staircase plots
* histograms (horizontal)
* sparsity patterns
* density plots
Download and add it to your Julia installation, if you haven't already done so:
You have to do this just once. Now you load the module and import the functions:
Here is a quick example of a line plot:
And here's a density plot:
(Note that it needs the terminal environment for the displayed graphs to be 100% successful - when you copy and paste, some of the magic is lost.)

### VegaLite

allows you to create visualizations in a web browser window. VegaLite is a visualization grammar, a declarative format for creating and saving visualization designs. With VegaLite you can describe data visualizations in a JSON format, and generate interactive views using either HTML5 Canvas or SVG. You can produce:
* Area plots
* Bar plots/Histograms
* Line plots
* Scatter plots
* Pie/Donut charts
* Waterfall charts
* Wordclouds
To use VegaLite, first add the package to your Julia installation. You have to do this just once:
Here's how to create a stacked area plot.
A general feature of VegaLite is that you can modify a visualization after you've created it. So, let's change the color scheme using a function (notice the "!" to indicate that the arguments are modified):
You can create pie (and donut) charts easily by supplying two arrays. The x array provides the labels, the y array provides the quantities:

# Metaprogramming
## What is metaprogramming?

Meta-programming is when you write Julia code to process and modify Julia code. With the meta-programming tools, you can write Julia code that modifies other parts of your source files, and even control if and when the modified code runs.
In Julia, the execution of raw source code takes place in two stages. (In reality there are more stages than this, but at this point we'll focus on just these two.)
Stage 1 is when your raw Julia code is parsed — converted into a form that is suitable for evaluation. You'll be familiar with this phase, because this is when all your syntax mistakes are noticed... The result of this is an abstract syntax tree or AST (Abstract Syntax Tree), a structure that contains all your code, but in a format that is easier to manipulate than the human-friendly syntax normally used.
Stage 2 is when that parsed code is executed. Usually, when you type code into the REPL and press Return, or when you run a Julia file from the command line, you don't notice the two stages, because they happen so quickly. However, with Julia's metaprogramming facilities, you can access the code after it's been parsed but before it's evaluated.
This lets you do things that you can't normally do. For example, you can convert simple expressions to more complicated expressions, or examine code before it runs and change it so that it runs faster. Any code that you intercept and modify using these meta-programming tools will eventually be evaluated in the usual way, running as fast as ordinary Julia code.
You may have already used two existing examples of meta-programming in Julia:
- the @time macro:
The @time macro inserts a "start the stopwatch" command at the beginning of the code, and adds some code at the end to "stop the stopwatch", and calculate the elapsed time and memory usage. The modified code is then passed on for evaluation.
- the @which macro
This macro doesn't allow the expression 2 + 2 to be evaluated at all. Instead, it reports which method would be used for these particular arguments. And it also tells you the source file that contains the method's definition, and the line number.
Other uses for meta-programming include the automation of tedious coding jobs by writing short pieces of code that produce larger chunks of code, and the ability to improve the performance of 'standard' code by producing the sort of faster code that perhaps you wouldn't want to write by hand.

## Quoted expressions

For meta-programming to be possible, there has to be a way for Julia to store an unevaluated but parsed expression, as soon as the parsing phase has finished. This is the ':' (colon) prefix operator:
To Julia, the :x is an unevaluated or quoted symbol.
(If you're unfamiliar with the use of quoted symbols in computer programming, think of how quotes are sometimes used in writing to distinguish between ordinary use and special use. For example, in the sentence:
'Copper' contains six letters.
the quotes indicate that the word 'Copper' is not a reference to the metal, but to the word itself. In the same way, in :x, the colon before the symbol is to make you and Julia think of 'x' as an unevaluated symbol rather than as the value 3.)
To quote whole expressions rather than individual symbols, start with a colon and then enclose the Julia expression in parentheses:
There's an alternative form of the :( ) construction that uses the quote ... end keywords to enclose and quote an expression:
which returns:
And this expression:
returns:
The expression object is of type Expr:
It's parsed, primed, and ready to go.

## Evaluating expressions

There's also a function for evaluating an unevaluated expression. It's called eval:
With these tools, it's possible to create any expression and store it without having it evaluate:
returning:
and then to recall and evaluate it later:
More usefully, it's possible to modify the contents of the expression before it's evaluated.

## Inside Expressions

Once you have Julia code in an unevaluated expression, rather than as a piece of text in a string, you can do things with it.
Here's another expression:
which returns:
Notice the helpful line numbers that have been added to each line of the quoted expression. (The labels for each line are added on the end of the previous line.)
We can use the fieldnames function to see what's inside this expression:
The head field is :block. The args field is an array, containing expressions (including comments). We can examine these with the usual Julia techniques. For example, what's the second subexpression:
Print them out:
As you can see, the expression P contains a number of sub-expressions. We can modify this expression quite easily; for example, we can change the last line of the expression to use prod rather than sum, so that, when P is evaluated, it will return the product rather than the sum of the variables.
Alternatively, you can target the sum symbol directly by burrowing into the expression:

### The Abstract Syntax Tree

This way of representing your code once it's been parsed is referred to as the AST (Abstract Syntax Tree). It's a nested hierarchical structure that's designed to allow both you and Julia to easily process and modify the code.
The very useful dump function lets you easily visualise the hierarchical nature of an expression. For example, the expression :(1 * sin(pi/2)) is represented like this:
You can see that the AST consists entirely of Exprs and atoms (e.g. symbols and numbers).

## Expression interpolation

In a way, strings and expressions are similar — any Julia code they happen to contain is usually unevaluated, but you can have some of the code evaluated using interpolation. We've met the string interpolation operator, the dollar sign ($). When used inside a string, and possibly with parentheses to enclose the expression, this evaluates the Julia code and inserts the resulting value into the string at that point:
In just the same way, you can use the dollar sign to include the results of executing Julia code interpolated into an expression (which is otherwise unevaluated):
Even though this is a quoted expression and hence unevaluated, the value of sin(1) + cos(1) was calculated and inserted into the expression, replacing the original code. This operation is called "splicing".
As with string interpolation, the parentheses are needed only if you want to include the value of an expression — a single symbol can be interpolated using just a single dollar sign.

## Macros

Once you know how to create and handle unevaluated Julia expressions, you'll want to know how you can modify them. A macro is a way of generating a new output expression, given an unevaluated input expression. When your Julia program runs, it first parses and evaluates the macro, and the processed code produced by the macro is eventually evaluated like an ordinary expression.
Here's the definition of a simple macro that prints out the contents of the thing you pass to it, and then returns the expression to the calling environment (here, the REPL). The syntax is very similar to the way you define functions:
You run macros by preceding the name with the @ prefix. This macro is expecting a single argument. You're providing unevaluated Julia code, you don't have to enclose it with parentheses, like you do for function arguments.
First, let's call this with a single numeric argument:
Numbers aren't expressions, so the if condition inside the macro didn't apply. All the macro did was return n. But if you pass an expression, the code in the macro has the opportunity to inspect and/or process the expression's content before it is evaluated, using the .args field:
In this case, the if condition was triggered, and the arguments of the incoming expression were printed in unevaluated form. So you can see the arguments as an array of expressions after being parsed by Julia but before being evaluated. You can also see how the different precedence of arithmetic operators has been taken into account in the parsing operation. Notice how the top-level operators and subexpressions are quoted with a colon (:).
Also notice that the macro p returned the argument, which was then evaluated, hence the 2.7142857142857144. But it doesn't have to — it could return a quoted expression instead.
As an example, the built-in @time macro returns a quoted expression rather than using eval to evaluate the expression inside the macro. The quoted expression returned by @time is evaluated in the calling context when the macro has done its work. Here's the definition:
Notice the $(esc(ex)) expression. This is the way that you 'escape' the code you want to time, which is in ex, so that it isn't evaluated in the macro, but left intact until the entire quoted expression is returned to the calling context and executed there. If this just said $ex, then the expression would be interpolated and evaluated immediately.
If you want to pass a multi-line expression to a macro, use the begin ... end form:
(You can also call macros with parentheses similar to the way you do when calling functions, using the parentheses to enclose the arguments:
This would allow you to define macros that accepted more than one expression as arguments.)

### eval and @eval

There's an eval function, and an @eval macro. You might be wondering what's the difference between the two?
The function version (eval) expands the expression and evaluates it. The macro version doesn't expand the expression you supply to it automatically, but you can use the interpolation syntax to evaluate the expression and pass it to the macro.
In other words:
Here's an example where you might want to create some variables using some automation. We'll create the first ten squares and ten cubes, first using eval:
which creates a load of variables named var_squares_n, such as:
and then using @eval:
which similarly creates a load of variables named var_cubes_n, such as:
Once you feel confident, you might prefer to write like this:

## Scope and context

When you use macros, you have to keep an eye out for scoping issues. In the previous example, the $(esc(ex)) syntax was used to prevent the expression from being evaluated in the wrong context. Here's another contrived example to illustrate this point.
This macro declares a variable s, and returns a quoted expression containing s and an escaped version of s.
Now, outside the macro, declare a symbol s:
Run the macro:
You can see that the macro returned different values for the symbol s: the first was the value inside the macro's context, 4, the second was an escaped version of s, that was evaluated in the calling context, where s has the value 0. In a sense, esc has protected the value of s as it passes unharmed through the macro. For the more realistic @time example, it's important that the expression you want to time isn't modified in any way by the macro.

## Expanding macros

To see what the macro expands to just before it's finally executed, use the macroexpand function. It expects a quoted expression containing one or more macro calls, which are then expanded into proper Julia code for you so that you can see what the macro would do when called.
(The #none, line 1: is a filename and line number reference that's more useful when used inside a source file than when you're using the REPL.)
Here's another example. This macro adds a dotimes construction to the language.
This is used as follows:
Or, less likely, like this:
If you use macroexpand on this, you can see what happens to the symbol names:
with the following output:
The i local to the macro itself has been renamed to #101#i, so as not to clash with the original i in the code we passed to it.

## A more useful example: @until

Here's how to define a macro that is more likely to be useful in your code.
Julia doesn't have an until condition ... do some stuff ... end statement. Perhaps you'd like to type something like this:
You'll be able to write your code using the new until macro like this:
but, behind the scenes, the work will be done by actual code with the following structure:
This forms the body of the new macro, and it will be enclosed in a quote ... end block, like this, so that it executes when evaluated, but not before:
So the nearly-finished macro code is like this:
All that remains to be done is to work out how to pass in our code for the <block_of_stuff> and the <condition> parts of the macro. Recall that $(esc(...)) allows code to pass through 'escaped' (i.e. unevaluated). We'll protect the condition and block code from being evaluated before the macro code runs.
The final macro definition is therefore:
The new macro is used like this:
or

## Under the hood

If you want a more complete explanation of the compilation process than that provided here, visit the links shown in Further Reading, below.
Julia performs multiple 'passes' to transform your code to native assembly code. As described above, the first pass parses the Julia code and builds the 'surface-syntax' AST, suitable for manipulation by macros. A second pass lowers this high-level AST into an intermediate representation, which is used by type inference and code generation. In this intermediate AST format all macros have been expanded and all control flow has been converted to explicit branches and sequences of statements. At this stage the Julia compiler attempts to determine the types of all variables so that the most suitable method of a generic function (which can have many methods) is selected.

## Further reading

* https://docs.julialang.org/en/v1/devdocs/reflection/ more about Abstract Syntax Trees in the official Julia documentation
* http://blog.leahhanson.us/post/julia/julia-introspects.html Julia Introspects, Leah Hanson's useful article from 2013