This is a simple cheatsheet and some performance comparison for scientific programmers who are interested in discover Julia. It is not an exhaustive list. This page is inspired from A Cheatsheet for Fortran 2008 Syntax: Comparison with Python 3.
Fortran | Julia | |
Top-level constructs | ||
the main program |
program my_program
...
end program
|
function my_program()
...
end
my_program()
Not required but it is recommended to use a function for your main program |
modules |
module my_module
...
end module my_module
|
module MyModule
...
end
|
subroutines |
subroutine my_subroutine
...
end subroutine my_subroutine
|
function my_subroutine!
...
end
The bang in the function name is a convention if a function mutates one or more of its arguments. The convention is that the modified arguments should (if possible) come first.
|
functions |
function f(x) result(res)
res = ...
end function f
|
function my_function(x)
...
return res
end
|
Generic interface |
module cube_root_functions
interface cube_root
function s_cube_root(x)
real :: s_cube_root
real, intent(in) :: x
end function s_cube_root
function d_cube_root(x)
double precision :: d_cube_root
double precision, intent(in) :: x
end function d_cube_root
end interface
end module cube_root_functions
function s_cube_root(x)
real :: s_cube_root
real, intent(in) :: x
s_cube_root = x ** (1.0/3.0)
end function s_cube_root
function d_cube_root(x)
double precision :: d_cube_root
double precision, intent(in) :: x
d_cube_root = x ** (1.0d0/3.0d0)
end function d_cube_root
|
cube_root( x :: Float32 ) :: Float32 = x^(1/3)
cube_root( x :: Float64 ) :: Float64 = x^(1/3)
|
submodules |
module main_module
...
contains
<submodule statements>
end module main_module
|
module MainModule
...
module SubModule
...
end
end
|
import statement |
use my_module
use my_module, only : fun1, var1
|
using MyModule
import MyModule: fun1, var1
|
call subroutines and functions |
call my_subroutine(args)
my_function(args)
|
my_function(args)
|
abort a program |
stop
|
exit()
|
inline comments |
! This is a comment
|
# This is a comment
|
include external source files |
include 'source_file_name'
|
include("source_file_name")
|
Control flow patterns | ||
if construct |
if <logical expr> then
...
else if <logical expr> then
...
else
...
end if
|
if <logical expr>
...
elseif <logical expr>
...
else
...
end
|
case construct |
select case <expr>
case <value>
...
case <value>
...
case default
...
end select
|
Not supported. Possible alternative is to use the ternary ? :syntax:
function case(x)
x == 1 ? println(1) :
x + 1 == 3 ? println(2) :
x == 3 ? println(3) :
println("greater than 3")
end
|
do construct |
do i = start_value, end_value, step
...
end do
|
for i in start:step:end
...
end
|
do while construct |
do while <logical expr>
...
end do
|
while <logical expr>
...
end
|
break from a loop |
exit
|
break
|
leave this iteration and continue to the next iteration |
cycle
|
continue
|
Data types | ||
declaration |
integer(kind=8) :: n = 0
real(kind=8) :: x = 0.
|
n = 0
n :: Int64 = 0
x = 0.
x :: Float64 = 0.
|
named constants |
integer, parameter :: answer = 42
real(8), parameter :: pi = 4d0 * atan(1d0)
|
const answer = 42
pi is a named constant in Julia standard.
|
complex number |
complex :: z = (1., -1.)
|
z = 1 - 1im
z = complex(1, -1)
|
string |
character(len=10) :: str_fixed_length
character(len=:), allocatable :: str_var_length
|
string = "this is a string"
|
pointer |
real, pointer :: p
real, target :: r
p => r
|
p = Ref(r)
|
boolean |
.true.
.false.
|
true
false
|
logical operators |
.not.
.and.
.or.
.eqv.
.neqv.
|
!
&&
||
Other logical operators do not have built-in support.
|
equal to |
==, .eq.
|
==
|
not equal to |
/=, .ne.
|
!==
|
greater than |
>, .gt.
|
>
|
less than |
<, .lt.
|
<
|
greater than or equal to |
>=, .ge.
|
>=
|
less than or equal to |
<=, .ge.
|
<=
|
array declaration |
real(8), dimension(3) :: a = [1., 2., 3.]
|
a = [1., 2., 3.]
|
string array declaration |
character(len=20), dimension(3, 4) :: char_arr
|
char_arr = String[]
push!(char_arr, new_string)
There is no easy way to preallocate space for strings.
|
elementwise array operations |
a op b
op can be +, -, *, /, **, =, == , etc.This is supported since the Fortran 90 standard. |
Supported by using the broadcast operator `.`and the `f.(x)` syntax |
first element |
a(1)
|
a[1] (or a[begin] for general indexing)
|
slicing |
a(1:5)
This slice includes a(5) .
|
a[1:5] (or @view(a[1:5]) for non-allocating slicing)
This slice includes a[5] .
|
slicing with steps |
a(1:100:2)
|
a[1:2:100]
|
size |
size(a)
|
length(a)
|
shape |
shape(a)
|
size(a)
|
shape along a dimension |
size(a, dim)
|
size(a, dim)
|
Type conversion | ||
to integer by truncation |
int(x)
|
trunc(Int, x )
|
to integer by rounding |
nint()
|
round()
|
integer to float |
real(a[, kind])
|
float()
|
complex to real |
real(z[, kind])
|
real()
|
to complex |
cmplx(x [, y [, kind]])
|
complex()
|
to boolean |
logical()
|
Bool()
|
Derived data types | ||
definition |
type Point
real(8) :: x, y
end type Point
|
struct Point
x :: Float64
y :: Float64
end
|
instantiation |
type(Point) :: point1 = Point(-1., 1.)
|
point1 = Point(-1., 1.)
|
get attributes |
point1%x
point1%y
|
point1.x
point1.y
|
array of derived type |
type(Point), dimension(:), allocatable :: point_arr
|
point_arr = Vector{Point}
|
type bound procedures (aka class method) | Assume that Circle has a type bound procedure (subroutine) print_area .
type(Circle) :: c
call c%print_area
|
Assume that Circle has a method print_area(c :: Circle) .
c = Circle()
print_area(c)
|
Built-in mathematical functions | ||
functions with the same names |
abs(), cos(), cosh(), exp(), floor(), log(),
log10(), max(), min(), sin(), sinh(), sqrt(),
sum(), tan(), tanh(), acos(), asin(), atan()
|
Have the same name in Julia. |
functions with different names |
aimag()
atan2(x, y)
ceiling()
conjg(z)
modulo()
call random_number()
|
imag()
atan(x, y)
ceil()
conj()
mod(), %
Random.rand()
|
Built-in string functions | ||
string length |
len()
|
length()
|
string to ASCII code |
iachar()
|
Int()
|
ASCII code to string |
achar()
|
String()
|
string slicing | Same as 1D array slicing. | Same as 1D array slicing. |
find the position of a substring |
index(string, substring)
|
findfirst(substring, string)
|
string concatenation |
"hello" // "world"
|
"hello" * "world"
string("hello", "world")
|
Array constructs | ||
where construct |
where a > 0
b = 0
elsewhere
b = 1
end where
|
b[a .> 0] .= 0
b[a .<= 0] .= 1
or (faster - does not allocate an intermediate array):
for i in eachindex(a)
a[i] > 0 ? b[i] = 0 : b[i] = 1
end
|
Comprehension |
integer, parameter :: n = 20
integer, parameter :: m = n*(n+1)/2
integer :: i, j
complex, dimension(m) :: a
a = [ ( ( cmplx(i,j), i=j,n), j=1,n) ]
|
a = [ complex(i,j) for j=1:n for i=j:n]
|
forall construct |
real, dimension(10, 10) :: a = 0
int :: i, j
...
forall (i = 1:10, j = 1:10, i <= j)
a(i, j) = i + j
end forall
|
a = zeros(Float32, 10, 10)
for i in 1:10, j in 1:10
if i <= j
a[i, j] = i + j
end
end
|
CPU time |
call cpu_time()
|
time = @elapsed begin
...
end
|
command line arguments |
call command_argument_count()
call get_command()
call get_command_argument()
|
For basic parsing, use ARGS |
Input/output | ||
print fmt, <output list>
|
println()
|
|
read from the command prompt |
read fmt, <input list>
|
readline()
|
open a file |
open(unit, file, ...)
|
f = open(file, 'r')
|
read from a file |
read(unit, fmt, ...) <input list>
|
read(f)
readlines(f)
|
write to a file |
write(unit, fmt, ...) <output list>
|
write(f, ...)
|
close a file |
close(unit, ...)
|
close(f)
|
file inquiry |
inquire(unit, ...)
|
isfile("my_file.txt")
|
backspace in a file |
backspace(unit, ...)
|
skip(f, -1)
|
end of file (EOF) |
endfile(unit, ...)
|
seekend(f)
|
return to the start of a file |
rewind(unit, ...)
|
seekstart(f)
|
Here an example of a Fortran to Julia translation. We use the Yee numerical scheme FDTD: Finite-Difference Time-Domain method and MPI topology. You can find a serial version and a parallel version using MPI library.
Test your MPI.jl installation with
$ mpirun -np 4 julia --project hello_mpi.jl
Hello world, I am 0 of 4
Hello world, I am 3 of 4
Hello world, I am 1 of 4
Hello world, I am 2 of 4
On small program like this in Julia is really fast.
julia -O3 --check-bounds=no maxwell_serial.jl
: 14 secondsmake && time ./maxwell_serial_fortran
: 31 secondsmake && time mpirun -np 9 ./maxwell_mpi_fortran
: 7 secondsmpirun -np 9 julia --project -O3 --check-bounds=no
: 5 secondsUncomment the plot_fields call in Julia programs or change idiag value in input_data for fortran.
gnuplot bz.gnu