Content from Introduction


Last updated on 2025-07-30 | Edit this page

Overview

Questions

  • “What is Julia?”
  • “Why use Julia?”

Objectives

  • “Explain the difference between interpreted and compiled programming languages”
  • “Compare how composing works in Julia and some common programming languages”

What is a programming language?


A programming language mediates between the natural language of humans and the machine instructions of a computer. The human specifies what the computer should compute on a high level using the programming language. This specification will be translated to machine instructions, the so called assembly code, which will be executed by the processor (CPU, GPU, …).

Interpreting and compiling

This translation happens differently depending on the programming language you use. There are mainly two different techniques: compiling and interpreting. Interpreted languages such as Python and R translate instructions one at a time, while compiled languages like C and Fortran take whole documents, analyze the structure of the code, and perform optimizations before translating it to machine code.

This leads to more efficient machine instructions of the compiled code at the cost of less flexibility and more verbose code. Most prominently, compiled languages need an explicit type declaration for each variable.

Why Julia?


Julia is a programming language that superficially looks like an interpreted language and mostly behaves like one. But before each function is executed it will be compiled just in time.

Thus you get the flexibility of an interpreted language and the execution speed of a compiled language at the cost of waiting a bit longer for the first execution of any function.

There is another aspect of Julia that makes it interesting and that is the way packages compose. This is captured the best by an analogy from Sam Urmy:

Say you want a toy truck.

The Python/R solution is to look for the appropriate package–like buying a Playmobil truck. It comes pre-manufactured, well-engineered and tested, and does 95% of what you would ever want a toy truck to do.

The Fortran/C solution is to build the truck from scratch. This allows total customization and you can optimize the features and performance however you want. The downside is that it takes more time, you need woodworking skills, and might hurt yourself with the power tools.

The Julia solution is like Legos. You can get the truck kit if you want–which will require a bit more assembly than the Playmobil, but way less than building it from scratch. Or, you can get the component pieces and assemble the truck to your own specs. There’s no limit to what you can put together, and because the pieces all have the same system of bumps, everything snaps together quickly and easily.

OK, sure. Toy trucks are like linear algebra, though, a common request, and every “toy system” will have an implementation that works basically fine. But what if you want a time-traveling sailing/space ship with lasers AND dragon wings? And it should be as easy to build and use as a basic dump truck?

There’s a reason that only Lego ever made anything like Dr. Cyber’s Flying Time Vessel!

Originally posted on Discourse.

Key Points

Keypoints

  • “Julia is a just-in-time compiled language”
  • “Julia packages compose well”

Content from Using the REPL


Last updated on 2025-08-12 | Edit this page

Overview

Questions

  • “How to use the REPL?”

Objectives

  • “Explore basic functionality of input.”
  • “Learn how to declare variables.”
  • “Learn about REPL modes.”

Entering the REPL


Melissa and her classmates open a terminal and launch julia:

BASH

julia

JULIA

               _
   _       _ _(_)_     |  Documentation: https://docs.julialang.org
  (_)     | (_) (_)    |
   _ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 1.7.2 (2022-02-06)
 _/ |\__'_|_|_|\__'_|  |  Official https://julialang.org/ release
|__/                   |
julia>

This is the so-called REPL, which stands for read-evaluate-print-loop. The interactive command-line REPL allows quick and easy execution of Julia statements.

Like the terminal, the Julia REPL has a prompt, where it awaits input:

JULIA

julia>
Callout

implicit prompt

Most of the code boxes that follow do not show the julia> prompt, even though it’s there in the REPL. Why?

It’s important to delineate input (what you type) and output (how the machine responds). The prompt can be confusing, so it is excluded. You may assume that any Julia box prepends the prompt on each line of input.

Callout

Visual Studio Code

An alternative to using the REPL through a terminal is to work with Visual Studio Code or its open source altenative VSCodium. VSC is a source code editor for which a julia extension is available. After installing the application, simply click on the “Extension” symbol on the left side and search for julia. Once installt julia remains usable and can be selected as a programming language in new documents.

For further guidance and visual aid, check out the provided video!

Variables


The first thing they try is to perform basic arithmetic operations:

JULIA

1 + 4 * 7.3

OUTPUT

30.2

That works as expected. It is also possible to bind a name to a value via the assignment operator =, which makes it easier to refer to the value later on. These names are called variables.

JULIA

distance = 30.2
distance_x_2 = 2 * distance

OUTPUT

60.4

Melissa notices that assignment also returns the value. She can also check which variables are defined in the current session by running

JULIA

varinfo()

OUTPUT

 name                    size summary
 –––––––––––––––– ––––––––––– –––––––
 Base                         Module
 Core                         Module
 InteractiveUtils 270.164 KiB Module
 Main                         Module
 ans                  8 bytes Float64
 distance             8 bytes Float64
 distance_x_2         8 bytes Float64

Unicode

In Julia, Unicode characters are also allowed as variables like α = 2. Unicode characters can be entered by a backslash followed by their LaTeX name and then pressing tab (in this case \alphatab).

REPL-modes


Unfortunately Melissa can’t remember the LaTeX name of ∂ so she copies the character , presses ? for help mode,

JULIA

?

pastes the ∂ character, then presses enter:

JULIA

help?>

OUTPUT

"∂" can be typed by \partial<tab>

Great! This way she can easily look up the names she needs. She gets back to normal mode by pressing backspace.

Challenge

Exploring Julia’s Help Mode

Help mode can also be used to look up the documentation for Julia functions. Use Julia’s help mode to read the documentation for the varinfo() function.

If you are not already in help mode, type ? to enter it. Then write varinfo and press enter.

JULIA

?varinfo

Another useful mode is the shell mode that can be entered by pressing ;. The prompt has now changed:

JULIA

shell>

Shell mode can be used to issue commands to the underlying shell, but don’t confuse it with an actual shell: special shell syntax like piping won’t work. Like before, hit backspace to get back to the Julia prompt.

Challenge

Hello, shell> (pwd and cd) !

Two commonly used shell commands are pwd (print working directory) and cd (change directory).

  1. Use pwd to find out what is your current working directory.
  2. Type the command cd in shell mode, which by default will bring you to your “home directory”.
  3. Use pwd again. Did you get a different result from before? Why or why not?

JULIA

shell> pwd

JULIA

shell> cd

JULIA

shell> pwd

The working directory is the location from which you launched Julia. To navigate to a different directory, you can use the cd command by entering: cd <directory>. By default, this command will return you to your home directory if a specific directory is not given. If you initially launched Julia from your home directory, the working directory remains unchanged, so the output of the second pwd command will be identical to the first. Conversely, if you were in a different directory when you started Julia, the results of the two pwd commands will differ. You can use cd - to go back to your previous location.

Challenge

Hello, shell> (ls)!

Another useful shell command is ls (list files). Use it to show the contents of your home directory.

JULIA

shell> cd

JULIA

shell> ls

The first cd command will bring you to your home directory. ls will print a list of the files and directorys in your current location.

Challenge

Hello, shell> (nano and cat)!

Use the shell mode to create a file called hello.jl with the nano terminal text editor. Inside that file write the simple hello world program print("Hello World!").

Check the content of the file using cat hello.jl and then run the program using julia hello.jl.

JULIA

;

JULIA

shell> nano hello.jl
shell> cat hello.jl

OUTPUT

print("Hello World!")

JULIA

shell> julia hello.jl

OUTPUT

Hello World!

backspace

Finally there is package mode that is entered with ] which is used for package management, which will be covered later on:

JULIA

]

JULIA

pkg>

To exit shell, help or pkg mode, hit backspace.

Key Points

Keypoints

  • “The REPL reads the given input, evaluates the given expression and prints the resulting output to the user.”
  • “Pressing ? enters help mode.”
  • “Pressing ; enters shell mode.”
  • “Pressing ] enters pkg mode.”

Content from The Julia Type System


Last updated on 2025-08-12 | Edit this page

Overview

Questions

  • “What is the use of types?”
  • “How are types organized in Julia?”

Objectives

  • “Understand the structure of the type tree.”
  • “Know how to traverse the type tree.”
  • “Know how to build mutable and immutable types.”

Structuring variables


Melissa wants to keep the variables corresponding to the trebuchet (counterweight, release_angle) separate from the variables coming from the environment (wind, target_distance). That is why she chooses to group them together using structures. There are two structure types:

  • immutable structures, whose fields can not be changed after creation
  • keyword: struct
  • mutable structures, whose fields can change after creation
  • keyword: mutable struct

Since Melissa wants to change the parameters of the trebuchet, she uses a mutable struct for it. But she cannot influence the environment and thus uses a struct for those values.

JULIA

mutable struct Trebuchet
  counterweight::Float64
  release_angle::Float64
end

struct Environment
  wind::Float64
  target_distance::Float64
end

Types and hierarchy


Here ::Float64 is a type specification, indicating that this variable should be a 64-bit floating point number, and :: is an operator that is read “is an instance of.” If Melissa hadn’t specified the type, the variables would have the type Any by default.

In Julia every type can have only one supertype, so let’s count how many types are between Float64 and Any:

1.

JULIA

supertype(Float64)

OUTPUT

AbstractFloat

2.

JULIA

supertype(AbstractFloat)

OUTPUT

Real

3.

JULIA

supertype(Real)

OUTPUT

Number

4.

JULIA

supertype(Number)

OUTPUT

Any

So we have the relationship Float64 <: AbstractFloat <: Real <: Number <: Any where <: is the subtype operator, used here to mean the item on the left “is a subtype of” the item on the right.

Float64 is a concrete type, which means that you can actually create objects of this type. For example 1.0 is an object of type Float64. We can check this at the REPL using either (or both) the typeof function or the isa operator:

JULIA

typeof(1.0)

OUTPUT

Float64

or

JULIA

1.0 isa Float64

OUTPUT

true

All the other types are abstract types that are used to address groups of types. For example, if we declare a variable as a::Real then it can be bound to any value that is a subtype of Real.

Let’s quickly check what are all the subtypes of Real:

JULIA

subtypes(Real)

OUTPUT

4-element Vector{Any}:
 AbstractFloat
 AbstractIrrational
 Integer
 Rational

This way the types form a tree with abstract types on the nodes and concrete types as leaves. Have a look at this visualization of all subtypes of Number:

Challenge

Is it Real?

For which of the following types T would the following return false?

JULIA

1.0 isa T
  1. Real
  2. Number
  3. Float64
  4. Integer

The correct answer is 4: while 1 is an integer, 1.0 is a floating-point value.

Instances


So far Melissa only defined the layout of her new types Trebuchet and Environment. To actually create a value of this type she has to call the so called constructor, which is a function with the same name as the corresponding type and as many arguments as there are fields.

JULIA

trebuchet = Trebuchet(500, 0.25pi)

OUTPUT

Trebuchet(500.0, 0.7853981633974483)

Note, how the values will get converted to the specified field type.

JULIA

environment = Environment(5, 100)

OUTPUT

Environment(5.0, 100.0)

trebuchet is being called an instance or object of the type Trebuchet. There can only ever be one definition of the type Trebuchet but you can create many instances of that type with different values for its fields.

Creating a subtype


A concrete type can be made a subtype of an abstract type with the subtype operator <:. Since Trebuchet contains several fields that are mutable Melissa thinks it is a good idea to make it a subtype of AbstractVector.

Callout

Caveat: Redefining Structs

JULIA

mutable struct Trebuchet <: AbstractVector{Float64}
  counterweight::Float64
  release_angle::Float64
end

ERROR

ERROR: invalid redefinition of constant Trebuchet
Stacktrace:
[1] top-level scope
   @ REPL[9]:1

This error message is clear: you’re not allowed to define a struct using a name that’s already in use.

Restart the REPL

In Julia it is not very easy to redefine structs. It is necessary to restart the REPL to define the new definition of Trebuchet, or take a different name instead.

Melissa decides to keep going and come back to this later.

Key Points

Keypoints

  • “In Julia types have only one direct supertype.”

Content from Using the Package Manager


Last updated on 2025-08-12 | Edit this page

Overview

Questions

  • “Where do I find packages?”
  • “How do I add packages?”
  • “How can I use packages?”

Objectives

  • “Learn to add packages using pkg-mode”
  • “Learn to resolve name conflicts”
  • “Learn to activate environments”

The package manager


Callout

The package Manager

This chapter focuses on the package mode available within the REPL.

A different aproach would be using the Pkg notation.

JULIA

using Pkg
Pkg.add("Example")

If you prefer to use that method and want to know more, remember how to get help.

(for exp. ?Pkg.add)

Now it is time for Melissa and their mates to simulate the launch of the trebuchet. The necessary equations are really complicated, but an investigation on JuliaHub revealed that someone already implemented these and published it as the Julia package Trebuchet.jl. That saves some real work.

Melissa enters package mode by pressing ]:

JULIA

]

The julia> prompt becomes a blue pkg> prompt that shows the Julia version that Melissa is running.

After consulting the documentation she knows that the prompt is showing the currently activated environment and that this is the global environment that is activated by default.

However, she doesn’t want to clutter the global environment when working on her project. The default global environment is indicated with (@v1.x) before the pkg> prompt, where x is the minor version number of julia, so on julia 1.7 it will look like (@v1.7). To create a new environment she uses the activate function of the package manager:

JULIA

(@v1.x) pkg> activate projects/trebuchet
  Activating project at `~/projects/trebuchet`

In this environment she adds the Trebuchet package from its open source code repository on GitHub by typing

JULIA

(trebuchet) pkg> add Trebuchet

Melissa quickly recognizes that far more packages are being installed than just Trebuchet. These are the dependencies of Trebuchet. From the output

OUTPUT

[...]
Updating `[...]/projects/trebuchet/Project.toml`
  [98b73d46] + Trebuchet v0.2.1
  Updating `[...]/projects/trebuchet/Manifest.toml`
  [1520ce14] + AbstractTrees v0.3.3
  [79e6a3ab] + Adapt v1.1.0
  [...]

she sees that two files were created: Project.toml and Manifest.toml.

The project file Project.toml only contains the packages needed for her project, while the manifest file Manifest.toml records the direct and indirect dependencies as well as their current version, thus providing a fully reproducible record of the code that is actually executed. “That is really handy when I want to share my work with the others,” thinks Melissa.

After the installation finished she can check the packages present in her environment.

JULIA

(trebuchet) pkg> status
Status `~/projects/trebuchet/Project.toml`
  [f6369f11] ForwardDiff v0.10.38
  [295af30f] Revise v3.6.3
  [98b73d46] Trebuchet v0.2.2
Callout

Why use GitHub?

Melissa could have added the GitHub version of Trebuchet.jl by typing

JULIA

(trebuchet) pkg> add Trebuchet#master

In this case the JuliaHub version is the same as the GitHub version, so Melissa does not need to specify the installation.

If you know a package is stable, go ahead and install the default version registered on JuliaHub. Otherwise, it’s good to check how different that version is from the current state of the software project. Click through the link under “Repository” on the JuliaHub package page.

deactivate does not exist, instead …

Melissa can get back to the global environment using activate without any parameters. Note, that any packages that were loaded in the old environment are still loaded in the new environment.

JULIA

(trebuchet) pkg> activate

Environments stack

What is installed in the default environment can also be loaded in other environments. That is useful for development time convenience packages like BenchmarkTools or JuliaFormatter.

Melissa now returns to her project environment.

JULIA

(trebuchet) pkg> activate projects/trebuchet

Using and importing packages


Now that Melissa added the package to her environment, she needs to load it. Julia provides two keywords for loading packages: using and import.

The difference is that import brings only the name of the package into the namespace and then all functions in that package need the name in front (prefixed). But packages can define a list of function names to export, which means the functions should be brought into the user’s namespace when he loads the package with using. This makes working at the REPL more convenient.

Name conflicts

It may happen that name conflicts arise. For example Melissa defined a structure named Trebuchet, but the package she added to the environment is also named Trebuchet. Now she would get an error if she tried to import/using it directly. One solution is to assign a nickname or alias to the package upon import using the keyword as:

JULIA

import Trebuchet as Trebuchets
Key Points

Keypoints

  • “Find packages on JuliaHub”
  • “add packages using pkg> add
  • “use many small environments rather than one big environment”