Menu Close

Articles

Julia: Introduction

Julia: Looks like Python, feels like Lisp, runs like Fortran. The syntax is minimalist and is based on English keywords. Therefore Julia is very readable compared to C++ and Java languages. You can learn Julia to proficient level in less then one week as your first computer language.

Features

What makes Julia the language that deserve popularity? Why one will chose Julia over Python, Swing or Go. Here we present the most appreciated features. These features makes programming with Julia productive and rewarding. These features makes Julia code is easy to read and understand. I have started with the most valuable on top.

PerformanceApproaching that of statically-compiled languages like C and Fortran
Co-routinesLightweight  threading designed for parallelism  and distributed computation
Multiple dispatchAbility to define function behavior across many combinations of argument types
Dynamic type systemDefine advanced types for documentation, optimization, and dispatch
User-defined typesThese types are as fast and compact as built-in types
Type inferenceType is created determined automatically from literals
Meta-programmingLisp-like macros and other meta-programming facilities
Call PythonCan be used to call python functions using PyCall package
Call C functionsDirect C call with no wrappers or special APIs
InterpreterPowerful shell-like capabilities for managing other processes
Unicode StringsEfficient support for Unicode including but not limited to UTF-8
Unicode OperatorsWe can use Unicode symbols as operators
Julia hoistingThe ability to use a type or a function before it is defined

Execution

Julia implements LLVM-based just-in-time (JIT) compiler. Combined with the language’s design allow it to approach and often match the performance of C. That means we have a dynamic language, that uses native computer types to create a fast and optimized program fro different platforms. Brilliant !!!

Syntax Style

Julia language has a very polished syntax. It eliminate annoying elements found in  other languages while implementing most of the important features. Having a simplified syntax matter. This is one of the simplistic language out there that have significant performance and power. This is one of the reason we recommend Julia to beginners.
  • Full English names for keywords;
  • Optional “;” at the end of statement;
  • Long expressions can span multiple lines;
  • Block of code is terminated using “end”;
  • Type inference makes declarations unnecessary;
  • The indentation and the end of line are irrelevant;
  • Julia has support Unicode operators like:  ≤ ≥ ≠;
  • Strings are enclosed in double quotes “string”;
  • Julia operators are functions;

Example of program:

Comments

A line comment is starting with symbol “#” exactly like in Python. Nested comments are possible in Julia. To create a multi-line comment in Julia we use two symbols: #= …. =#. That is unconventional but has a logic behind. We can create a separator line like this:

Variables

When you wish to declare a variable in Julia you use Duck typing. For this you use a type literal to provide enough information to the compiler to derive the type. Once the type is established you can use the variable in expressions. In Julia evening is an expression.

The message is a string variable having value “Hello World”. Observe that we do not use keyword “var” like in JavaScript or other languages.  Also in Julia a variable can be re-purpose. The type can be changed when the variable is assigned using “=” symbol. A new value of a different type can be assigned.

Constants

In Julia we use global constants to improve performance and protect them against change. So the constant values are declared using keyword constant to make the program faster. In local scope the constant is not faster than a simple variable.

Numeric type

Julia uses native numeric types. This is one of the key elements to make fast Julia programs. When we assign a variable the type is automatically assigned using an assumption. If we wish to assign a specific type to a variable we use a “type annotation” this start with “::” symbol.

  • Integer types: Int32, Int64
  • Floating-point types: Float32, Float64

To write a floating point number we use dot (.) after the number or before the number if the number is <0.

Boolean type

Boolean is a native type having two values: false < true. Boolean variables can be used to create conditions. To create a Boolean variable we can use assign operator with a literal “true” or literal “false”, or we can use a logical expression to assign the result to a variable. In next example we use Boolean operators: && for “and”, || for “or” and ! for “not”. These are the basic operators for Boolean algebra.

Array type

In Julia array represents a collection of elements all having the same type. This collection is indexed starting with index 1 until the last element end. We use square brackets [ … ] and elements are separated by comma or semicolon.

Tuple type

Tuples are immutable collection of elements. We use notation (,) to create tuples. The tuple collection is indexed.

Dictionary type

A dictionary is a collection of pairs. Each pair is (key, value).

Functions

We declare a function in Julia using keyword [function]. We end the function using simple keyword “end”. In other languages like Level 123 we use: “end function”. Therefore Julia is more like Pascal. In Ada and PL/SQL we use “end <function_name>”.  In Python we do not use “end” but we reduce indentation level. So what you think is best?

Example:

As you can see in the previous example we do not use any symbol after parameter list. In Python and Level 123 we use “:”. In Ada and PL/SQL we use “is”. But Julia simplify the syntax to minimum. Also this function do not return any result but has a side-effect.

To execute a function we use function name followed by (). For example we can cal “say_hello” function using notation: say_hello(“Julia”). This function will print to console “Hi Julia, it’s great to see you!” the $name place-holder is replaced by “Julia” value.

The return

The last expression value in a function is the result of the function. So easy to use and elegant no? What if the things are more complex. Can we create multiple exit points? Yes we can using the return keyword. This will skip all other statements and create an exit point before the end. We can use many return statements.

Example:

The decision

In the previous example we show a “if” statement also known as conditional statement.  Easy to to use and simplified syntax. Julia do not use “then” keyword or “:” symbol after the condition like in other languages. Again Julia show an elegant and simple approach. It is used for one condition or multiple conditions using “elseif” compound keyword. In python this keyword is “elsif”.

Syntax:

The if statement can have many condition and for each condition a block of code. The else statement is the alternative (optional) block that is executed when no condition is true. For each block we can also have nested if statements. This is somesing we wish to avoid if possible. It’s a good practice to not get too far from left side.

While loop

While statement is used to repeat a block of code multiple times as long as one condition is true. If the condition is always true then we have an infinite loop. We can use a control variable that we increment inside the loop. In the next example we also learn two operators:  “<=” and “+=” to check the value of the control variable “i”. After the loop this control variable is available.

For loop

This is a repetitive statement that execute a finite number of times using a control variable.  Next example is more compact:

Loop control

We can early terminate a loop by using break. We can also skip execution of statements and jump back to beginning using  continue keyword. Unlike while loop the control variable “i” is local inside the for loop and not available after the loop is ending.

Modules

Julia is modular. A module is like a package that encapsulate several members. A module can import other modules and can export members. One module is stored in one or many files. One file can contain one or more modules. So the module is a supra-structure used to group together members. Each member exported or not.

Syntax:

In the previous example a module can have two optional keywords: import and export. The module is using hoisting technique. We can export a member before we declare the member. So the export is above the declaration region. Julia has 3 standard modules that we do not have to import: Main, Core, and Base.

When we import a module all it’s export members can be used directly in the global namespace of the module. The private members of the module can be used with dot “.” punctuation: ModuleName.member_name. Remember the module name is usually with capital letters. Member name is usually lower-case except types that start with upper-case letter.

Variable Scope

A variable can have a global scope or local scope. A variable that is defined outside of any function is a global variable. A local scope is defined for every function. If the functions are nested, the local function can see the variables in the parent scope. Also a function can have internal loops and other blocks that can have a nested soft local scope.

We can force local scope or global scope variables using keyword: “local” or “global” similar to Python. So in the next example the x is local and the y is global inside the function fix.

Note: Julia is using hoisting technique. That means the location of declaration: local or global has no importance.

Exceptions

When something goes wrong the execution of the program can be stopped. This is called an exception. We can create exceptions on purpose to show to the user that something has gone wrong and we can print a message to explain the situation. In Julia there are pre-define exceptions that have a name and are automatically created by the system in certain situations.

We have two situations. One is when we wish to “catch” the exception and continue the program. Another is we wish to execute something important before the program stop execution. We use a try block with two keywords: catch and finally. We can use both clauses or only one depending on the case.

Example:

Example:

In the previous example we catch the error and copy the error in variable err. Then we use function isa() to analyze the error type. We can create errors using error() function and throw() function. Most of the type we do not catch errors and we do not create error handlers in programs.

Operators

The following arithmetic operators are supported on all primitive numeric types:

ExpressionNameDescription
+xunary plusthe identity operation
-xunary minusmaps values to their additive inverses
x + ybinary plusperforms addition
x – ybinary minusperforms subtraction
x * ytimesperforms multiplication
x / ydivideperforms division
x \ yinverse divideequivalent to y / x
x ^ ypowerraises x to the y power
x % yremainderequivalent to rem(x,y)

Bitwise

These operators are performing fast low-level operations on bits on native integer types.

ExpressionName
~xbitwise not
x & ybitwise and
x | ybitwise or
x $ ybitwise xor exclusive or: (deprecated)
x >>> ylogical shift right
x >> yarithmetic shift right
x << ylogical/arithmetic shift left

Modifiers

Every binary arithmetic and bitwise operator also has an updating version that assigns the result of the operation back into its left operand. The updating version of the binary operator is formed by placing equal symbol “=” immediately after the operator like this:

Note: The update operator is not in-place. What it means is the variable on the left side can change its type. So these operators are actually version of assign operator.

Comparison

A numeric comparison can be used into a conditional expression. It has a result of type Boolean that is true or false.

OperatorName
==equality
!=, ≠inequality (disjunctive)
<less than
<=, ≤less than or equal to
>greater than
>=, ≥greater than or equal to

Logical

Logical operators and comparison operators can be combined to create logical expressions that evaluate to true or false.

OperatorName
&&AND
||OR
!NOT

Boolean table of truth

In Julia Boolean values are: true, false. We cant use 1 and 0 like in other languages. Next is a combination of possible values for A, B and the result of several basic expressions. A&&B meaning A and B, A||B meaning A or B then !A meaning negation of A an then !B meaning negation of B. If you are not familiar with these expressions then you need to look into Boolean algebra.

ABA&&BA||B!A!B
falsefalsefalsefalsetruetrue
falsetruefalsetruetrue0
truefalsefalsetruefalsetrue
truetruetruetruefalsefalse

Punctuation

In the next table we present a mingle of symbols used by Julia for different purposes. Some are operators but some are just conventions.

symbolmeaning
@minvoke macro m; followed by space-separated expressions
!prefix “not” operator
a!( )at the end of a function name, ! indicates that a function modifies its argument(s)
#begin single line comment
#=begin multi-line comment (these are nestable)
=#end multi-line comment
$string and expression interpolation
%remainder operator
^exponent operator
&bitwise and
&&short-circuiting Boolean “and”
|bitwise or
||short-circuiting Boolean “or”
bitwise xor operator (use to be $ but I think it was changed)
*number multiplication, matrix multiplication, string concatenation
()the empty tuple
~bitwise “not” operator
\backslash operator
complex transpose operator Aᴴ
a[]array indexing
[,]vertical concatenation
[;]also vertical concatenation
[   ]with space-separated expressions, horizontal concatenation
T{ }parametric type instantiation
;statement separator
,separate function arguments or tuple components
?3-argument conditional operator (conditional ? if_true : if_false)
“”delimit string literals
delimit character literals
` `delimit external process (command) specifications
splice arguments into a function call or declare a varargs function or type
.access named fields in objects/modules, also prefixes elementwise operator/function calls
a:brange a, a+1, a+2, …, b
a:s:brange a, a+s, a+2s, …, b
:index an entire dimension (1:end)
::type annotation, depending on context
: ( )quoted expression
:asymbol a
<:sub-type operator
>:supertype operator (reverse of subtype operator)
===egal comparison operator

Keywords

Next I will list several Julia keywords in logical order but not all of them. You may encounter other keywords in practice. I will try to add more keywords here when I fully understand them. Remember this article is just an introduction tutorial not a reference document.

#KeywordDescription
 trueThe constant true is a Boolean value
 falseThe constant false is a Boolean value
 maybeNot a keyword 🙂 just teasing you
 constantDefine a constant usually a global
 globalUsed in local scope to show that a variable is not local
 localUsed in local scope to force a variable to be local and hide a global variable
 beginMark the beginning of a compound expression block “begin … end”
 letMark the beginning of a let block: “let … end”
 endMark the end of a block, function or module
  function Create a function
 moduleCreate a module
 returnCreate an exit point from a function and return a result
 importImport into a module public members from another module
 exportExport module public members to be imported into another module
 ifDecision statement
 elseAlternative block for false condition
 elseifAlternative block for second condition
 whileStart a while loop  “while … end”
 forStart a for loop: “for … in … end”
 inUsed with for to iterate over a range or collection
 breakStop a while or a for loop
 continueShortcut a loop and continue with next iteration
 printPrint a message to console
 printlnPrint a message to console and add end of line
 tryStart a block of code that may rise exceptions
 catchStart exception handling block
 finallyIs the final part that execute not matter what for a try block
 throw()This is a standard function to create an exception
 error()Also create an exception of type ErrorException
 abstractDefine an abstract type
 primitiveUsed to create a primitive type
 typeUsed with abstract or primitive keyword to create a type
 structCreate a structure like a record (immutable)
 mutableUsed with struct to create a mutable struct
 unionUsed to create a union type
 typeof()This is a function used to display type information about a variable
 isa()A function that return true or false about type of a variable
 supertype()Extract the supe-type information for a type
 Nullable{}Create a null-able type
 isnull()Check if a null-able type is null
 macroblock of code execute when code is parsed (used to generate code), invoke macro with @ operator.
 quoteexpression that span multiple lines used as alternative to quote operator “:”
 eval()used in meta-programming to evaluate a string expression