Month: March 2015

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

Setting up Julia environment in Windows

Installing Julia

The binary for installing Julia can be downloaded from: http://julialang.org/downloads/.
The installation will give us access to an interactive console session, known as REPL (read-eval-print-loop). The console is very similar to Matlab console where we can type any code in it and get the result right away. To get help on any function in Julia, press “?” and the function name. We can also execute shell command by typing “;” first followed by the shell command.

Untitled

Console replacement

The default Julia REPL console run on the standard Windows command prompt which lacks of features (like copying). There are several console alternatives that we can use. My favorite is ConEmu which can be downloaded from http://sourceforge.net/projects/conemu/.

Untitled

Code editor

There are several editor softwares which provide syntax highlighting for Julia code. Sublime Text (http://www.sublimetext.com/) is one of the most popular. Since Sublime Text isn’t really free, my choice goes to GitHub Atom (https://atom.io/). In both softwares we can install package for Julia syntax highlighting.

IDE

Juno http://junolab.org/ is the IDE that is recommended in Julia website. It support syntax highlighting, code completion, real-time feedback and variable browser. We can run the code step by step or choose some part of code to run and then get the feedback. The Matlab-like variable browser feature can also help us debugging the code.

Untitled

My preference

While Juno provides useful features for programmer, I personally prefer the REPL version since I use the console a lot for testing some function, exploring available functions and getting help. I usually type the code in Atom and then run in REPL console using include("file_name.jl") command. Here’s a screenshot of my Julia environment:

Untitled

Why I prefer Julia’s language design more than Matlab’s and R’s

Why I prefer Julia‘s language design more than Matlab’s and R’s

  1. Unlike Matlab, it uses [i] for array/vector/matrix indexing. | Matlab uses (i)
  2. Unlike R, it uses = as the assignment operator. |  R uses <-
  3. Unlike in R, . has a real meaning in Julia.
  4. Unlike in Matlab, we don’t need to put ; in the end of statement.  |  In Matlab, we have to put ; to suppress printing values.
  5. Unlike in R, matrix declaration is simple and convenient.
  6. Unlike in R, matrix operation is simpler in Julia.
  7. Unlike in Matlab, we can easily write inline function (without creating new file) in Julia
  8. Unlike Matlab and R, array values are passed by reference.
  9. Unlike Matlab and R, function arguments can be type-assigned.

As a programmer who has written code in a dozen programming languages, it’s good to have consistency across different languages. 1) , 2) , and 3) are mainly to get the consistency. I often made mistakes when writing R or Matlab code  because of the inconsistencies.

4) 5) and 6) are mainly for convenience. Consider these examples:

R :

A <- matrix(c(1,2,3,4,5,6,7,8,9), nrow=3, byrow = TRUE)
sol <- eigen(A)
AA <- sol$vec %*% diag(sol$val) %*% t(sol$vec)

Matlab :

A = [1, 2, 3; 4, 5, 6; 7, 8, 9];
[V, L] = eig(A);
AA = V * L * V';

Julia:

A = [1 2 3; 4 5 6; 7 8 9]
l, V = eig(A)
AA = V * diagm(l) * V'

Lastly, covering 7) 8) and 9), let’s write an example of function definition in Julia

distance(x::Number, y::Number) = abs(x - y)
distance(x::Vector, y::Vector) = sqrt( sum((x - y).^2) )
a = distance(1, 2)    # call distance(x::Number, y::Number) method
b = distance([1,2,3], [1,2,4])    # call distance(x::Vector, y::Vector) method