Aula 19 Julia

https://julialang.org

https://julialang.org/learning/tryjulia/ julia online

https://en.wikibooks.org/wiki/Introducing_Julia livro online

ocupa o nicho de linguagens para aplicaçoes numericas (Fortran, Python+Numpy, Mathlab)

scope de variaveis no loop

https://en.wikibooks.org/wiki/Introducing_Julia/Controlling_the_flow

vairaveis de controle do for e variaveis setadas dentro do loop nao sobrevivem ao fim do loop

for i = 1:10
       z1 = 99+i
       print(i)
       end
12345678910
i
z1

mas se z1 for definida (usada) fora ela sobrevive. Ou declarada no loop como global z1 no loop

Dicionários

2 tipos de dicionário

julia> Dict("A"=>1, "B"=>2)
Dict{String, Int64} with 2 entries:
  "B" => 2
  "A" => 1
julia> Dict(true => "yes", 1 => "no", 1.0 => "maybe")
Dict{Real, String} with 1 entry:
  1.0 => "maybe"

julia> IdDict(true => "yes", 1 => "no", 1.0 => "maybe")
IdDict{Any, String} with 3 entries:
  true => "yes"
  1.0  => "maybe"
  1    => "no"

O tipo Any é um supertipo para qq coisa

mesma sintaxe para acessar e colocar um par no dic

c = Dict{String,Any}()
c["f"] = (1,2,3)
c["qwerty"] = 99.0
c["qwerty"]+10

Não há listas só Arrays (tipados)

https://en.wikibooks.org/wiki/Introducing_Julia/Arrays_and_tuples

julia> a = [1,2,3,4]
4-element Vector{Int64}:
 1
 2
 3
 4

tem uma formatação extra para arrays 2D (branco -> na mesma linha, ; -> muda de linha)

julia> [1 2 3 4 ; 5 6 7 8]
2x4 Array{Int64,2}:
1  2  3  4
5  6  7  8

note

julia> [1, 2, 3, 4, 5]
5-element Array{Int64,1}:
1
2
3
4
5

julia> [1 2 3 4 5]
1x5 Array{Int64,2}:
1  2  3  4  5

Array comprehention

julia> [n^2 for n in 1:5]
5-element Vector{Int64}:
  1
  4
  9
 16
 25

julia> [r * c for r in 1:5, c in 1:5]
5×5 Matrix{Int64}:
 1   2   3   4   5
 2   4   6   8  10
 3   6   9  12  15
 4   8  12  16  20
 5  10  15  20  25

Acesso e indexacao

a = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100];

; inibe a saida

a[1]
a[end]
a[end-2]

a[[2,1,2]]

a[1:4]

vetorização (versão simples)

vetoriozacao (automática) de funções e operadores

f(a,b) = a+2*b

f(4,5)

f([1 2 3; 4 5 6], [10 11 12; 13 14 15])

[1,2,3] - [6,7,8]
[1,2,3] * [6,7,8]

vetorizacao explicita (usando o .)

[1,2,3] .* [6,7,8]

existe broadcast mas não vou cobrir os detalhes

julia> [1 2 3 ; 4 5 6] ./ [1 2 3]
2×3 Matrix{Float64}:
 1.0  1.0  1.0
 4.0  2.5  2.0
 
julia> [1 2 3 ; 4 5 6] / [1, 2 ,3]
ERROR: DimensionMismatch: Both inputs should have the same number of columns
Stacktrace:

metaprogramming

referencia https://docs.julialang.org/en/v1/manual/metaprogramming/

outra fonte https://en.wikibooks.org/wiki/Introducing_Julia/Metaprogramming

uso:

@time [sin(cos(i)) for i in 1:100000];
x = 78 + @show sum([sin(cos(i)) for i in 1:100000])

define novos tipos de dados para isso

um blog sobre escrever uma macro simples https://giordano.github.io/blog/2022-06-18-first-macro/

garbage collector (automatic memory management)

wikipedia https://en.wikipedia.org/wiki/Garbage_collection_(computer_science)

outra fonte https://www.infoworld.com/article/2337816/what-is-garbage-collection-automated-memory-management-for-your-programs.html

video https://www.youtube.com/watch?v=lEYtWcuVylc

Problemas de genrenciamento manual (malloc e free do C)

tipos de garbage collector

um thread em paralelo que marca todas as posicoes de memoria que podem ser alcançadas a partir de uma raiz (lista de variavies, lista de simbolos). Ha varias variacoes: Por exemplo generational GC

Aloca dados na area (generation) 0. Quando a area 0 enche, os dados sao coletados. Os que nao forem coletados vao para a area 1. Quando a area 1 enche, a mesma coisa usando a area 2.

Tracing CG tem um custo em tempo medio - o GC tem que rodar de vez em quando e interromper o programa

cada dado mantem um contador do numeros de caminhos que podem alcançar os dados. Quando o contador chega a 0, o dado é coletado. Usado no Python

a = [1,2,3]  --> a lista tem contador 1
b = a        --> contador = 1
a = 3        --> decrementa o contador antes de a apontar para o novo valor
b = "qwerty" --> contador chega a 0

Reference counter tem um custo no tempo de execuçao. cada nova atribuicao tem que decrementar o contado do dado velho.

o compilador analisa o codigo e verifica que o dado nao é usado apos o fim de uma funcao. Entao vc pode alocar o dado no stack da funcao e nao no heap!