When writing code in Julia, I use REPL console frequently, mainly to understand how some functions or some expressions works in Julia. I usually create something like dummy matrices and vectors, and test the function/expression using that dummies. Fortunately, Julia’s REPL console provides many useful tricks for exploring how it works.

### ?Help

Getting help on a function in Julia is easy, just type ? followed by the name of the function to show the manual. Here’s an example

help?> eig Base.eig(A,[irange,][vl,][vu,][permute=true,][scale=true]) -> D, V Computes eigenvalues and eigenvectors of "A". See "eigfact()" for details on the "balance" keyword argument. julia> eig([1.0 0.0 0.0; 0.0 3.0 0.0; 0.0 0.0 18.0]) ([1.0,3.0,18.0], 3x3 Array{Float64,2}: 1.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0) "eig" is a wrapper around "eigfact()", extracting all parts of the factorization to a tuple; where possible, using "eigfact()" is recommended. Base.eig(A, B) -> D, V Computes generalized eigenvalues and vectors of "A" with respect to "B". "eig" is a wrapper around "eigfact()", extracting all parts of the factorization to a tuple; where possible, using "eigfact()" is recommended.

### Who’s there?

Julia’s REPL provides the function `whos()`

to display all the variables (and functions) in the environment. Take a look on this example:

julia> a = [1, 2, 3] 3-element Array{Int64,1}: 1 2 3 julia> f(x) = x^2 f (generic function with 1 method) julia> whos() Base Module Core Module Main Module a 3-element Array{Int64,1} ans Function f Function

If we want to see all functions inside a module, we can use `whos(ModuleName)`

. Executing `whos(Core)`

will show all functions/variables inside the Core module.

julia> whos(Core) === Function ANY TypeVar ASCIIString DataType AbstractArray DataType Any DataType Array DataType Bool DataType ........

We can search for functions using Regex, for example if we want to see all function in Base containing the word with “inv”:

julia> whos(Base, r"inv"i) erfcinv Function erfinv Function inv Function invdigamma Function invmod Function invperm Function pinv Function

### Methods

In Julia, function is a collection of methods. Similar with the concept of *polymorphism* in Object Oriented Programming, in Julia, there can be many functions (methods) with the same name, but with different *signature*. The choice of which method to execute when we call a function is called *dispatch*. In Julia, the choice is based on the number of arguments passed to the function, and on the type of all arguments. If there are more than one methods satisfy the requirement, the one with the more specific types will be called. Here’s an example:

julia> f(x) = println("General method is called") f (generic function with 1 method) julia> f(x::Number) = println("Method for handling number") f (generic function with 2 methods) julia> f(x::Float64) = println("Method for handling floating point") f (generic function with 3 methods) julia> f(1) Method for handling number julia> f(1.0) Method for handling floating point julia> f([1, 2]) General method is called

Note that `f(1.0)`

satisfy both `f(x::Number)`

and `f(x::Float64)`

, but the more specific method is called.

Julia provides `methods()`

function to show all methods in a function.

julia> methods(eye) # 7 methods for generic function "eye": eye{T}(::Type{Diagonal{T}},n::Int64) at linalg/diagonal.jl:95 eye(T::Type{T<:Top},m::Integer,n::Integer) at array.jl:176 eye(m::Integer,n::Integer) at array.jl:182 eye(T::Type{T<:Top},n::Integer) at array.jl:183 eye(n::Integer) at array.jl:184 eye(S::SparseMatrixCSC{Tv,Ti<:Integer}) at sparse/sparsematrix.jl:414 eye{T}(x::AbstractArray{T,2}) at array.jl:185

We can also show all methods that are applicable to a variable using `methodwith()`

function. For example to show all methods that accept a `Matrix`

variable:

julia> methodswith(Matrix) 67-element Array{Method,1}: size(a::Array{T,2}) at array.jl:20 -(A::Array{T,2},B::Diagonal{T}) at linalg/special.jl:90 -(A::Array{T,2},B::Bidiagonal{T}) at linalg/special.jl:90 -(A::Array{T,2},B::Tridiagonal{T}) at linalg/special.jl:90 -(A::Array{T,2},B::Triangular{T,S<:AbstractArray{T,2},UpLo,IsUnit}) at linalg/special.jl:90 -(A::Array{T,2},B::SymTridiagonal{T}) at linalg/special.jl:99 ..............

### Which one?

In order to see which method will be chosen when we execute a function or expression, we can use `@which`

macro.

julia> @which f(4.0) f(x::Float64) at none:1 julia> @which 1 + 2 +(x::Int64,y::Int64) at int.jl:33 julia> @which 1.0 + 2 +(x::Number,y::Number) at promotion.jl:158 julia> @which rand(1, 2) rand(dims::Int64...) at random.jl:123

### Types-hierarchy

Since understanding Types-hierarchy is very important in Julia (it’s a key to master methods), we might want to know functions related to Type. Some basic type functions are `subtypes()`

, `super()`

`typeof()`

, `isa()`

, and `issubtype()`

. Below are the examples:

julia> typeof(1.0) Float64 julia> super(Float64) FloatingPoint julia> subtypes(Number) 2-element Array{Any,1}: Complex{T<:Real} Real julia> subtypes(Real) 5-element Array{Any,1}: FixedPoint FloatingPoint Integer MathConst{sym} Rational{T<:Integer} julia> isa(1.0, Real) true julia> isa(1.0, Integer) false julia> isa(1.0, Number) true julia> issubtype(Integer, FloatingPoint) false julia> issubtype(Integer, Number) true

Note that some types has alias, for example `Array`

data type which contains `Vector`

(1-d array), `Matrix`

(2-d array) and higher dimension Array.

julia> Vector Array{T,1} julia> Matrix Array{T,2}

### Compiler’s mind

Julia has built-in functions to see how the compiler parse the source code and translate it to lower representations of the code. Four macros `@code_lowered`

, `@code_typed`

, `@code_llvm`

, and `@code_native`

can be used to show four different levels of representation of the code from the highest to the lowest level.

julia> @code_lowered 1.0 + 2.0 + 3 1-element Array{Any,1}: :($(Expr(:lambda, {:a,:b,:c}, {{},{{:a,:Any,0},{:b,:Any,0},{:c,:Any,0}},{}}, :(begin # operators.jl, line 82: return (a + b) + c end)))) julia> @code_lowered 3 * 2.0 + 1 1-element Array{Any,1}: :($(Expr(:lambda, {:x,:y}, {{},{{:x,:Any,0},{:y,:Any,0}},{}}, :(begin # promotion.jl, line 158: return (top(apply))(+,promote(x,y)) end)))) julia> @code_typed 3 * 2.0 + 1 1-element Array{Any,1}: :($(Expr(:lambda, {:x,:y}, {{},{{:x,Float64,0},{:y,Int64,0}},{}}, :(begin # promotion.jl, line 158: return box(Float64,add_float(x::Float64,box(Float64,sitofp(Float64,y::Int64))::Float64))::Float64 end::Float64)))) julia> @code_llvm 3 * 2.0 + 1 define double @"julia_+_3232"(double, i64) { top: %2 = sitofp i64 %1 to double, !dbg !9747 %3 = fadd double %2, %0, !dbg !9747 ret double %3, !dbg !9747 } julia> @code_native 3 * 2.0 + 1 .text Filename: promotion.jl Source line: 158 push RBP mov RBP, RSP Source line: 158 vcvtsi2sd XMM1, XMM0, RDX vaddsd XMM0, XMM1, XMM0 pop RBP ret