### Control de flujo
### Por Arturo Erdely basado en https://docs.julialang.org/en/v1/


## Expresiones compuestas
#  begin

z = begin
    x = 1
    y = 2
    x + y
end
println(z, "\t", typeof(z))

z = (x = 4 ; y = 5 ; x + y)
println(z, "\t", typeof(z))

begin x = 1 ; y = 2 ; println(x + y) end


## EvaluaciÃ³n condicional
#  if  elseif  else  ifelse

function compara(x, y)
    if x < y
        println("$x < $y")
    elseif x > y
        println("$x > $y")
    else
        println("$x = $y")
    end
    return nothing
end

compara(2, 3)
compara(7, 1)
compara(3, 3)

compara2(x, y) = println(x < y ? "$x < $y" : x > y ? "$x > $y" : "$x = $y")
compara2(2, 3)
compara2(7, 1)
compara2(3, 3)

esmayor(x, y) = ifelse(x > y, "sÃ­", "no")
esmayor(5, 4)
esmayor(2.3, 3.2)


## EvaluaciÃ³n de corto circuito 
#  &&  ||  &  |

t(x) = (println(x) ; true)
f(x) = (println(x) ; false)

println(t(1) & t(2))
println(t(1) & f(2))
println(f(1) & t(2))
println(f(1) & f(2))

println(t(1) && t(2))
println(t(1) && f(2))
println(f(1) && t(2))
println(f(1) && f(2))

println(t(1) | t(2))
println(t(1) | f(2))
println(f(1) | t(2))
println(f(1) | f(2))

println(t(1) || t(2))
println(t(1) || f(2))
println(f(1) || t(2))
println(f(1) || f(2))

println(true && 1000)
println(false && 1000)

println(true || 1000)
println(false || 1000)


## Ciclos
#  while  for  in  âˆˆ  continue  break  foreach

letra = 'a'
while letra â‰¤ 'z'
    print(letra, " ")
    global letra += 1
end
println(letra)

letra = 'a'
while letra â‰¤ 'z'
    if letra == 'w'
        print("perro ")
        global letra += 1
        continue
    end
    if letra == 'y'
        break
    end
    print(letra, " ")
    global letra += 1
end
println(letra)

for ðŸ�· âˆˆ 'Î±':'Ï‰'  # en lugar de âˆˆ puede usarse `in` o bien `=`
    print(ðŸ�·, " ")
end

for ðŸ�‰ âˆˆ ['â™Œ', 'Q', '3', 'â�Œ']
    print(ðŸ�‰, "\t")
end

for â„˜ âˆˆ "La vida es lucha"
    print(â„˜, " â—� ")
end

for ðŸ�‰ âˆˆ 'Î±':'Î´', ðŸ�¼ âˆˆ 3:5
    println((ðŸ�‰ , ðŸ�¼))
end

for i âˆˆ 1:2, j âˆˆ 3:4
    println((i, j))
    i = 0
end
for i âˆˆ 1:2
    for j âˆˆ 3:4
        println((i, j))
        i = 0
    end
end

vf = [x -> x + 1, x -> x^2, x -> x/2]
vx = [1, 10]
Afx = [f(x) for f âˆˆ vf, x âˆˆ vx]
display(Afx)


# Pkg.add("BenchmarkTools")
using BenchmarkTools

n = 100
Î” = zeros(Int64, n, n, n) # arreglo 3D

@btime begin
    for i âˆˆ 1:n , j âˆˆ 1:n, k âˆˆ 1:n
        Î”[i, j, k] = i + j + k
    end
end
# en lugar de:
@btime begin
    for i âˆˆ 1:n
        for j âˆˆ 1:n
            for k âˆˆ 1:n
                Î”[i, j, k] = i + j + k
            end
        end
    end
end

function âˆ (Î¸)
    for k âˆˆ 1:length(Î¸)
        Î¸[k] = sin(Î¸[k])
    end
    Î¸
end;
println(round.(âˆ ([0, Ï€/2, Ï€, 3Ï€/2, 2Ï€])))
Î¸ = rand(100_000_000);
@btime lista = [sin(Î²) for Î² âˆˆ Î¸]; # lista comprensiva
@btime vecto = sin.(Î¸); # vectorizado
@btime ciclo = âˆ (Î¸); # con ciclo <for> puro

A = zeros(Int, 100, 100, 100);
@btime for i âˆˆ 1:100, j âˆˆ 1:100, k âˆˆ 1:100
           A[i, j, k] = i + j + k
end
B = zeros(Int, 100, 100, 100);
@btime for i âˆˆ 1:100, j âˆˆ 1:100, k âˆˆ 1:100
           B[k, j, i] = i + j + k
end # mÃ¡s rÃ¡pido
B == A


# foreach

foreach(println, 'Î±':'Ï‰')


## Manejo de excepciones
#  throw  error  try/catch  finally

# Solo mensajes (texto)
error("Â¡Cometiste un error muy grave!")

# Mensaje de error por medio de un objeto no necesarimente de texto
a = 0/0
throw(a)
throw("Â¡No hagas eso!")

function dameTexto(texto)
    if typeof(texto) == String
        println("Bien hecho")
    else
        throw(println("Requiere que su argumento `texto` sea tipo String y no " * string(typeof(texto))))
    end
    println("Fin")
end
dameTexto("Hola perro")
dameTexto(3)

function damePositivo1(x)
    if x > 0
        println("bien hecho")
    else
        throw(DomainError(x, "Â¿no entendiste que positivo ðŸ˜¢?"))
    end
    println("fin")
end
damePositivo1(3)
damePositivo1(-2)

function damePositivo2(x)
    if x > 0
        println("bien hecho")
    else
        error("Â¿no entendiste que positivo ðŸ˜¢?")
    end
    println("fin")
end
damePositivo2(3)
damePositivo2(-2)

function damePositivo(x)
    try
        return sqrt(x) # si x < 0 -> ERROR
    catch # atrapar/administrar el ERROR
        println("dije positivo, tonto")
        return 0
    end
    println("fin") # nunca se ejecuta
end
damePositivo(3)
damePositivo(-2)
sqrt(-2)

function damePositivo3(x)
    try
        return sqrt(x)
    catch
        println("dije positivo, tonto")
        return 0
    finally
        println("fin") # siempre se ejecuta al margen de try / catch
    end
end
damePositivo3(3)
damePositivo3(-2)
