# Some useful functions/tricks in Julia’s REPL console

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:
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