Welcome to the third part in the article series – ‘Getting started with Julia language’. Julia language is growing in popularity among data scientists, many surveys has listed it as one in top 5 programming languages for data scientists. Mostly due to the factors such as the faster execution time and speedier development process facilitated by the language. In this article, we’ll discuss variables and types in Julia language. In case you missed it, we’ve already covered how to set up Julia and Julia REPL and packages.
Variables in Julia
Like in every other programming language, variables are locations in the computer memory named by the user to hold some data related to the program.
In Julia, variable names are case-sensitive and a wide range of unicode characters (of UTF-8 encoding) are also supported. Variables can be assigned/created by using the conventional assignment operator “=”.
test_string = "Julia variable" pi_val = 3.14 count = 35 ❄ = -12
In the above examples, 3 variables namely “test_string”, “pi_val” and “count” are created/assigned with some values(data types).
[contact_sales title=”Getting started with Julia language” desc=”Getting started with Julia language- Part 2, REPL and Packages” btn_text=”Read More” url=”https://blog.accubits.com/julia-programming-language-packages-and-repl/“]
Variable to Variable Assignment
Value in one variable can be assigned to another by simply following the n be equal to m convention
m = 10 n = m # value of m will be copied to n
Naming convention for variables
Though there aren’t many restrictions in naming variables, some styling conventions are recommended.
- Lower cased names are preferred.
- Variable names may not start with a number nor an exclamation mark.
- Though the use of “_” in names is less preferred, “snake_cases” can be used for improving readability of long function and variable names.
- CamelCase is preferred for naming Types and Modules.
- Provide leading and trailing white space for the assignment operator. “=”
Types in Julia
A type constrains the values that an expression, such as a variable or a function, might take.
Types can be broadly classified into 2:
- Static Types – Every executable program expression is defined with a type prior to its execution.
- Dynamic Types – Compiler has to decide the type of the values at the time of code compilation.
Julia’s type system is primarily dynamic and is augmented by the ability to specify types where needed, meaning that there is no need to tell Julia what type a particular value is unless you want to.
Based on Julia’s type hierarchy, types can be abstract or concrete.
- Abstract Types – A type that is intended solely to act as super-types of other types, rather than types of particular objects. i.e, abstract types can be divided into sub-types. Some examples are: Number , String , Bool , Rational , etc.
- Concrete Types – These are the types of actual objects. They are always sub-types of abstract types and they are not allowed to have any sub-types.
Concrete Types can be again divided into two, primitive and composite.
Primitive Types – Primitive Types in Julia are the concrete types whose value is in the form of bits. Some examples of primitive types are: Int8 , Int16 , Int64 , Float16 , Float32 , String , etc…
Unlike most languages, with Julia you can declare your own primitive types.
Standard primitive types are defined as:
primitive type Float64 <: AbstractFloat 64 end primitive type Bool <: Integer 8 end primitive type Char <: AbstractChar 32 end primitive type Int64 <: Signed 64 end
Similarly we can define our own primitives with the following syntax:
primitive type Byte 8 end # Define the primitive Byte Byte(val::UInt8) = reinterpret(Byte, val) b = Byte(0x02) # Assign a byte value to b
Here, reinterpret is used to assign an unsigned integer with 8 bits (UInt8) into the Byte.
Note: You may be wondering what :: operator is for, don’t worry it will be explained in the follow-up tutorial
Composite Types – Composite types in Julia are a collection of named fields which can be individually treated as single values of specific types. Composite types can be declared with the use of struct keyword.
Syntax:
struct Foo
Field1::Type
Field2::Type
end
Example:
# Define the struct
struct Greet
x
y::String
end
# Creating object with constructor
greet1 = Greet("Hello", "World")
The values of a composite object can be accessed using the dot notation,
greet1.x
Output -> "Hello"
One interesting thing about composite types is that they are immutable in nature, i.e, we cannot change the value after instantiating the object. Fortunately, Julia also provides mutable types that have a similar syntax like the immutable composite types, the only difference is the usage of the mutable keyword in front of struct .
Syntax:
mutable struct Foo Field1::Type Field2::Type end Example: # Define the mutable struct mutable struct Num x::Float64 y::Float64 end # Creating object with constructor greet1 = Num(1, 5.3) # Update a value greet1.x = 4.5
You can change the values after instantiation. However, these values must comply with the type’s definition in that they must be convertible to the specified type (in our case Float64). For example, an Int64 input would be acceptable because you can easily convert an Int64 to a Float64. On the other hand, a string wouldn’t work because you can’t convert it to Float64 .
Julia’s built-in operators, literals and unions
The :: operator has different functionalities in different contexts, let’s see what they are:
Declaring a (sub)type
In the context of a statement, such as a function, :: can be used to restrict the type of a variable.
Example:
# Declare the function function restrict_this_integer() x::Int8 = 32 x end # Call the function p = restrict_this_integer() typeof(p) # Output will be Int8
Note: Don’t worry about the function definition, it will be discussed in a follow up tutorial.
Asserting a type
In every other context, :: means ‘I assert this value is of this particular type’. This is a great way to check a value for both abstract and concrete type.
Example:
integer_value = 10 # Assert integer_value if of type Int64 integer_value::Int64 # Assert integer_value if of type Char integer_value::Char
The assertion for Int64 will return the value stored in “integer_value” and the assertion for Char will result in a TypeError — ERROR: TypeError: in typeassert, expected Char, got Int64 .
Specifying acceptable function inputs
While we haven’t really discussed function inputs, you should be familiar with the general idea of a function — mapping a couple of arguments using some expression to a return value. Julia can ensure that a function only accepts values that we want.
Let’s define a function which takes 2 integers as input and provides their sum as output.
function add(x::Int64, y::Int64) x + y end # Call the function on 2 integers result = add(16, 14) Outputs -> 30 # Call the function on 2 floats result = add(2.0, 3.5) Outputs -> ERROR: MethodError: no method matching add(::Float64, ::Float64)
As you can see from the above examples, any types other than the specified one ( Int64 ) results in an error.

