Introduction to the Julia Programming Language

Matthew Balch

HackRVA

September 17, 2016

Why Program in Julia?

▶ Speed ▶ Familiar syntax ▶ A growing library of packages ▶ Excellent integration with C and Fortran binaries ▶ Metaprogramming ▶ Parallel programming

You all installed Julia, right?

▶ If you’re on Linux, use your package manager ▶ If you’re on Windows, go to the downloads page at

julialang.org ▶ If you’re on Mac, you’re on your own ▶ If you don’t have your computer, you’ve got bigger problems.

Start Julia

▶ In Linux, from the command line type ”julia”. ▶ In Windows, use the start menu to open the REPL. ▶ In Mac, open programs however you usually do in Mac. ▶ A desktop launcher should work in whatever operating system

you use.

Quick Ways to Learn More

▶ Type ”?” then the function name to see documentation ▶ Go to docs.julialang.org ▶ Say something if I’m going to fast

Lets Get Started

Pkg.clone("https://github.com/Matt5sean3/HackRvaJulia.jl.git")
using HackRvaJulia
start_intro()

1. Installs the HackRvaJulia package

2. Loads the HackRvaJulia package into the environment

3. Calls the start intro function

4. Follow the instructions in the GUI

Hello World!

function hello(name::AbstractString = "World")
  println("Hello $name!")
end
hello(name::Symbol) =
  hello(string(name))
hello(name, times::Integer) =
  [hello(name) for i in 1:times]
hello()
hello("HackRVA")
hello("HackRVA", 5)

Hello World! (cont.)

These lines alone show us quite a lot. Type Annotation

name::AbstractString
name::Symbol

Dollar-sign substitution in strings Semi-colons not needed, newlines mean something

"Hello $name!"

long form function definition

function hello(name::AbstractString = "World")
  println("Hello $name!")
end

short form function definition

hello(name::Symbol) =
  hello(string(name))

begin-end style code blocks

Return Values

Every function and code block will has a return value. If no return statement is used then the last statement is the return value. This allows for surprisingly compact code quite often.

point1 = (3, 3)
point2 = (6, 7)
function distance(p1, p2)
  (p1[1] - p2[1])^2
end
distance(point1, point2) == 5

Type System

Types are either concrete or abstract. A sort of type tree can be generated using abstract types. A concrete type cannot be have a sub-type.

abstract AnAbstractType <: ASuperType
type AConcreteType <: AnAbstractType
  unannotated_member
  annotated_member::SomeType
end

Multiple Dispatch

Rather than objects having methods, functions have methods. When a function is called the types of the input arguments are used to decide which method of the function is used.

Method Ambiguity

When there is ambiguity as to which method would be used, the julia interpreter will tell you at definition time. When this happens, adding another method to resolve the ambiguity should fix everything.

# This causes an ambiguity warning
f(x::Float64, y) = println("First argument is a float")
f(x, y::Float64) = println("Second argument is a float")
# This won't cause an ambiguity warning
f(x::Float64, y::Float64) = println("Both arguments are floats")
f(x::Float64, y) = println("Only first argument is a float")
f(x, y::Float64) = println("Only second argument is a float")

Control Flow

Essentially the same as most other languages If statements only handle the boolean type. Any other type will throw an error.

if condition
  # happens if condition is true
end
if 1 # Will throw a type error
  # something-something
end
if value == 0
  # do something for the value being 0
elseif value < 0
  # do something for the value being below 0
else
  # do something for the value being over 0
end
# if statements can return values too
x = if value == 0
  0
elseif value < 0
  -1
else
  1
end

Control Flow (cont.)

# if statements can return values too
x = if value == 0
  0
elseif value < 0
  -1
else
  1
end

Control Flow (cont.)

For and while loops are also an option

# while loops are available
while keep
  # hopefully the condition changes
end
# while blocks always return "nothing"
x = while condition
  # hopefully this loop exits somehow
end
# for blocks also return nothing
x = for i in 1:5
  # happens 5 times
  # return value of the block doesn't go anywhere
  not_returned_value
end

Control Flow (cont.)

# However, comprehensions return an array
x = [2 for i in 1:5]
# Comprehensions allows simulating for blocks that return lists
x = [begin
  # do something to compute the element
  list_element
end for i in iterable]

Let’s Make Sure We Know the Basics

You should all now know enough to implement FizzBuzz ▶ Print the numbers 1 through 100 ▶ for multiples of 3 print Fizz instead of the number ▶ for multiples of 5 print Buzz instead of the number ▶ for multiples of both 3 and 5 print FizzBuzz instead of the

number ▶ for extra credit implement it as one line ▶ to prove you’re a badass do it without repetition

Iterables

Iterables are very useful To use something as an iterable the start, next, and done methods must be defined

# returns the initial state for iteration
start(iter) = initial_state
# returns a tuple containing the item in the iterator and the next
# iteration state
next(iter, state) = (item, next_state)
# returns whether iteration has completed
done(iter, state) = is_finished
# A length method is necessary to use the iterable in a comprehension
length(iter) = number_of_times_iterating

Packages

Julia’s package system is built around git. If you don’t know git this could get confusing. There are a few basic package commands for retrieving packages.

Pkg.init() # Initial configuration of the package manager
Pkg.add("package_name") # Install the named package
Pkg.rm("package_name") # Uninstall the named package
Pkg.generate("package_name", "license") # Create a new package with that name

Using Packages

Like most languages, to do much beyond the basics using just what’s built-in would be ridiculous.

use JSON
import Base: start, next, done, length

One important thing to know is that more methods can be added to imported functions but not to functions brought into scope via ”use”. The Core and Base packages are always implicitly used.

Let’s Make a Package

1. If you don’t have a Github account, make one now

2. Think about what the package should do

3. Create a new Julia package named accordingly If you have questions about using Julia, git, or anything else now is the time to ask.

Generate a Package

Pkg.generate("PackageName", "License")

▶ A few initial files will be created and a git repository will be

initialized. ▶ A few license strings are recognized: MIT, BSD, and ASL ▶ The package’s location is found with

Pkg.dir(”PackageName”)

Basics of a Package

▶ The REQUIRE file lists the dependencies of the package ▶ README.md and LICENSE.md are automatically added ▶ A test directory and src directory with basic templates are

created ▶ Continuous Integration files for Travis-CI (.travis.yml) and

Appveyor (appveyor.yml) are made

Making a Github Account

1. Go to github.com

2. Click on Sign Up

3. Go through the account creation process 4. Add an SSL certificate

Configuring Git

1. Use the semi-colon to use a shell command in Julia 2. git config –global user.name ”Your Name”

3. git config –global user.email ”youremail@example.com”

4. Connect using SSL keys

Ongoing Problems in Julia Land

▶ Backwards compatibility breaking changes are still happening ▶ There are still mistakes in even some fundamental packages

Julia is an open source project and the package system included in the installation is well designed to make contributing a solution to these problems frictionless.

Documentation Generation

1. documentation is important (if you didn’t already know)

2. In-code documentation keeps things simple

3. Julia, like most languages, has a documentation generation package

4. Install Documenter.jl