In [1]:
importall Base

Criando tipos

Em Julia, tipos são como classes em python, com a diferença de que não possuem métodos internos. São então muito mais parecidos com os structs de C.

Vetor 2D

Podemos definir um tipo imutável (que não pode mudar depois de criado) para representar um vetor em duas dimensões:


In [2]:
immutable Vector2D
    x::Float64
    y::Float64
end

Temos dois campos, representando as coordenadas em x e y. Podemos criar um "objeto" deste tipo, fazendo:


In [3]:
w = Vector2D(2.0, 1.0)


Out[3]:
Vector2D(2.0,1.0)

Podemos acessar os campos de w


In [4]:
w.x


Out[4]:
2.0

Criamos outro vetor fazendo:


In [5]:
v = Vector2D(5.0, 10.0)


Out[5]:
Vector2D(5.0,10.0)

Impressão

Note que o vetor v foi impresso na célula acima, mas sua impressão é muito feia. Podemos mudar isto, criando um método show para nosso novo tipo. Similarmente, temos métodos de show para quase todos os tipos padrão de Julia.


In [6]:
show(io::IO, v::Vector2D) = print(io, "[$(v.x), $(v.y)]")


Out[6]:
show (generic function with 85 methods)

In [7]:
v


Out[7]:
[5.0, 10.0]

In [8]:
w


Out[8]:
[2.0, 1.0]

Operações

Vetores se somam e podem ser multiplicados por escalares. No entanto, isto ainda não é possível:


In [9]:
v + w


`+` has no method matching +(::Vector2D, ::Vector2D)
while loading In[9], in expression starting on line 1

Não existe um método + que espere dois vetores. Podemos definir este método fazendo:


In [10]:
+(a::Vector2D, b::Vector2D) = Vector2D(a.x + b.x, a.y + b.y)


Out[10]:
+ (generic function with 118 methods)

In [11]:
v + w


Out[11]:
[7.0, 11.0]

A multiplicação é definida de forma similar:


In [12]:
*(v::Vector2D, α::Number) = Vector2D(α * v.x, α * v.y)
*(α::Number, v::Vector2D) = v * α


Out[12]:
* (generic function with 117 methods)

In [13]:
2v


Out[13]:
[10.0, 20.0]

Partícula

Podemos definir uma partícula por sua posição e velocidade:


In [14]:
type Particle
    position::Vector2D
    velocity::Vector2D
end

# Ensinando Julia a imprimir uma partícula
show(io::IO, p::Particle) = print(io, "pos: $(p.position); vel: $(p.velocity)")


Out[14]:
show (generic function with 86 methods)

Criamos uma partícula fazendo:


In [15]:
p = Particle(v, w)


Out[15]:
pos: [5.0, 10.0]; vel: [2.0, 1.0]
Podemos fazer a partícula se mover com a ajuda de uma função:

In [16]:
# A partícula se move em um tempo δt
function move!(p::Particle, δt::Real)
    p.position += p.velocity * δt
end

move!(p, 0.1)


Out[16]:
[5.2, 10.1]

Gás

Um gás é apenas uma coleção de partículas:


In [17]:
type Gas
    particles::Vector{Particle}
end

# Novo método para criar um gás
function Gas(N::Int)
    parts = [Particle(Vector2D(rand(2)...), Vector2D(rand(2)...)) for i in 1:N]
    return Gas(parts)
end

# Imprimindo um gás
function show(io::IO, g::Gas)
    for particle in g.particles
        println(particle)
    end
end


Out[17]:
show (generic function with 87 methods)

In [18]:
bottle = Gas(10)


pos: [0.6475861372986156, 0.3147382153890981]; vel: [0.24192206340045397, 0.1755011196354952]
Out[18]:

pos: [0.9717735811092119, 0.2640577433648994]; vel: [0.6594893973155316, 0.7384719711746939]
pos: [0.412214654620205, 0.7245371761146113]; vel: [0.3653152859848565, 0.28546428771940957]
pos: [0.6392208446467909, 0.752450963424901]; vel: [0.6892703361065791, 0.15695833898775535]
pos: [0.4764739994784506, 0.4051585282691068]; vel: [0.9551016440740174, 0.5287974167647327]
pos: [0.7647504486051031, 0.5625997460741781]; vel: [0.9404085757090326, 0.022902302953403897]
pos: [0.2319802165924736, 0.8477233449392945]; vel: [0.6791863065902095, 0.10947462760277982]
pos: [0.9739836930265529, 0.6840385563395994]; vel: [0.7993417337938677, 0.44789471081967425]
pos: [0.5528693246374528, 0.8247830294474252]; vel: [0.3366629106248227, 0.8612073955191981]
pos: [0.665710610596195, 0.28309242881613517]; vel: [0.6287107002220265, 0.4628247536421728]

Podemos fazer todas as partículas do gás se moverem, adicionando mais um método move:


In [19]:
function move!(g::Gas, δt::Real)
    for particle in g.particles
        move!(particle, δt)
    end
end

move!(bottle, 0.1)

In [20]:
bottle


Out[20]:

pos: [0.671778343638661, 0.3322883273526476]; vel: [0.24192206340045397, 0.1755011196354952]
pos: [1.037722520840765, 0.3379049404823688]; vel: [0.6594893973155316, 0.7384719711746939]
pos: [0.44874618321869064, 0.7530836048865522]; vel: [0.3653152859848565, 0.28546428771940957]
pos: [0.7081478782574487, 0.7681467973236765]; vel: [0.6892703361065791, 0.15695833898775535]
pos: [0.5719841638858524, 0.45803826994558006]; vel: [0.9551016440740174, 0.5287974167647327]
pos: [0.8587913061760064, 0.5648899763695184]; vel: [0.9404085757090326, 0.022902302953403897]
pos: [0.2998988472514945, 0.8586708076995725]; vel: [0.6791863065902095, 0.10947462760277982]
pos: [1.0539178664059397, 0.7288280274215668]; vel: [0.7993417337938677, 0.44789471081967425]
pos: [0.5865356156999351, 0.910903768999345]; vel: [0.3366629106248227, 0.8612073955191981]
pos: [0.7285816806183976, 0.3293749041803524]; vel: [0.6287107002220265, 0.4628247536421728]