8 Programar en Julia
8.1 jl-files
Los jl-files son Scripts (archivos de texto) donde guardamos una secuencia de comandos. Son útiles para automatizar un bloque de comandos. Los Scripts operan sobre datos existentes y crean nuevos datos a partir de las operaciones contenidas (y guardados en el espacio de trabajo). Los Scripts pueden contener también funciones que ejecutan tareas específicas. Estos archivos son guardados con extensión .jl
.
Los jl−files puede llevar comentarios, esto es bloques de texto que son ignorados por el compilador. Toda línea que empieza con signo de porcentaje (#
) es considerada comentarios.
Para ejecutar un jl-file en el REPL (read–eval–print-loop) de Julia en la terminal usamos:
El jl-file debe estar guardado en el directorio de trabajo.
8.2 Funciones de Usuario
Es una buena práctica dividir la tarea que queremos realizar con julia en tareas simples y asignar una función para cada tarea simple.
Son muy útiles para procedimiento repetidos.
La sintaxis de una función en Julia es:
"""
Documentación de la función
"""
function nombre_funcion(input1, input2,...)
comandos
return output1, output2, ...
end
Ejemplo 1: Crear una función de nombre fx
que evalúa un polinomio de grado 2.
"""
**fx** Evalúa un polinomio de segundo grado. Función aplica sólo a escalares.
Uso:
val = fx(x)
"""
function fx(x)
return 2*x^2 + 3*x - 5
end
39
Esta misma función puede usarse sobre vectores, matrices o arreglos de mayor dimensión usando la notación funcion.()
(aplica la función a cada elemento).
4×1 Array{Float64,2}:
-3.30007741621653
-1.2607592332029083
-1.1012791244536677
-2.772979772220121
Ejemplo 2: Crear una función de nombre stat
, que calcula la media y la desviación estándar de un vector, y guardarla en el directorio de trabajo.
"""
**stat** Calcula la media y la desviación estándar de un vector x.
Uso:
mean, stdev = stat(x)
"""
function stat(x)
n = length(x)
mean = sum(x)/n
stdev = sqrt(sum(x.^2)/n - mean^2) # Nota: elevamos al cuadrado cada elemento del vector (.^)
return mean, stdev
end
(50.14366440248996, 3.659923232929554)
50.14366440248996
Funciones simples pueden crearse usando las dos siguientes opciones:
- Usando notación matemática:
60
- Usando el formato
input ->
:
60
Nota Importante!!
- Las funciones creadas Julia cuentan con la información provista como
input
y todas las variables del espacio de memoria (cómo variables globales). Por esto, y para tener un mejor control de los argumentos que está usando una función, es una buena práctica pasar como argumento explícito todo lo que la función requiera. - Todas las variables creadas al interior de la función son variables locales, esto es, sólo existen dentro de la función. Así, la función dejará en el espacio de trabajo sólo las variables que fueron pasadas por el
return
de la función. - Los argumentos (inputs) de una función pueden contener strings, matrices, vectores, escalares, y funciones.
- Es posible además declarar funciones (varias) en un jl-file separado y llamarlo con
include("misfunciones.jl")
para que las funciones estén disponible en el espacio de trabajo.
Ejemplo 3: Crear una función de nombre fxalt
que evalúa un polinomio de grado 2 tomando dos argumentos: \(x\) y los parámetros del polinomio:
"""
**fx* Evalúa un polinomio de segundo grado.
Uso:
val = fxalt(x,params)
params: vector 3 x 1 de parámetros.
"""
function fxalt(x,param)
a = param[1]
b = param[2]
c = param[3]
return a*x^2 + b*x + c
end
55.0
Una forma de transformar la función fxalt
para que sólo dependa del argumento x
es usar una función anónima.
pa = 2.0
pb = 3.0
pc = -5.0
p = [pa, pb, pc]
fx4 = x -> fxalt(x,p) # fijamos p = [2, 3, -5]
fx4(4.0)
39.0
8.3 Loops
Los Loops son bucles que sirven para realizar operaciones de manera repetida. En Julia existen dos tipos de Loops:
- For Loop: Realiza la misma acción un número determinado de veces. Su sintaxis es como sigue:
Ejemplo 1: Calcular la suma acumulada de un vector:
n = 8
x = rand(n)
sumx = zeros(n)
sumx[1]= x[1]
for i = 2:n
sumx[i] = sumx[i-1]+x[i]
end
println(sumx)
[0.946697, 1.87125, 2.33302, 3.19241, 3.57936, 4.38677, 5.00578, 5.07728]
Comentarios:
- Al igual que en el caso de las funciones, en Julia todas las variables que se crean al interior de un For Loop tienen un ambito local, es decir sólo existen dentro del loop. Para guardar los resultados del loop debemos declarar la función fuera del loop (inicializarla, como es el caso del vector
sumx
) para que está exista en memoria una vez concluido el loop. - Los loops operan repetidas veces con elementos iterables. Las secuencias creadas como
inicio:incremento:fin
o con la funciónrange()
son iterables. No obstante lo anterior, en general, cualquier arreglo en Julia es iterable.
2:8
UndefVarError: interable not defined
Stacktrace:
[1] top-level scope at In[16]:1
Un Arreglo formado de texto puede ser iterado (para ello se utiliza la opción in
en el For Loop):
La Materia es: Macro
La Materia es: Micro
La Materia es: Econometría
Existen una forma muy útil de construir Arreglos sobre la base de iterables de una manera sencilla. Es herramienta se llama list comprehension y utiliza el formato [función for var_iterable in objeto_iterable]
. Por ejemplo, para calcular el cuadrado de cada elemento de un vector podemos usar (demás de la notación .ˆ
):
5-element Array{Float64,1}:
9.0
36.0
81.0
64.0
9.0
Alternativamente es posible usa la función map(función, x)
para pasar una función escalar anónima por cada elemento de un arreglo:
5-element Array{Float64,1}:
9.0
36.0
81.0
64.0
9.0
o definiendo una función de forma anónima directamente en map()
:
5-element Array{Float64,1}:
9.0
36.0
81.0
64.0
9.0
- While Loop: Realiza la misma acción hasta que una condición se cumpla.
Ejemplo 2: Calcular la secuencia de número en la que cada numero precedente es la mitad del anterior. La secuencia termina cuando el número final sea menor que 0.05.
1
0.5
0.25
0.125
0.0625
0.03125
Comentarios:
- Julia es eficiente al utilizar loops.
- Un for loop puede comportarse de forma descendente:
for i=10:-1:1
. - Podemos anidar varios loops. Por ejemplo:
3×2 Array{Float64,2}:
1.0 0.5
0.5 0.333333
0.333333 0.25
Para loops anidados, Julia tiene una notación más compacta que consta de un For Loop y varios iterables separados por coma, por ejemplo:
3×2 Array{Float64,2}:
1.0 0.5
0.5 0.333333
0.333333 0.25
y también puede usar una list comprehension y escribir el el loop anterior de manera aún más compacta:
3×2 Array{Float64,2}:
1.0 0.5
0.5 0.333333
0.333333 0.25
- Podemos utilizar un while loop como un for loop, sólo se necesita definir un contador. Por ejemplo:
1
2
3
4
8.4 Condicionales y Operadores Lógicos
Los condicionales sirven para ejecutar un comando si se cumple cierta condición. La sintaxis para condicionales es:
if condicion 1
comando
elseif condicion 2
comando
elseif condicion 3
comando
else
comando
end
donde condicion 1
, condicion 2
, etc son variable boolenada: true
o false
. Para construir variables boolianas utilizamos los siguientes operadores lógicos:
<
menor a>
mayor a<=
menor o igual a>=
mayor o igual a==
igual a!=
no es igual a|
o: verdadero si al menos una es verdadera||
o: verdadero si al menos una es verdadera (no evalúa la segunda si la primera condición es verdadera)&
y: verdadero si todas son verdaderas&&
y: verdadero si todas son verdaderas (no evalúa la segunda condición si la primera es falsa)!
negativoany
verdadero si algún elemento de un Arreglo booleano estrue
all
verdadero si todos los elementos de un Arreglo booleano sontrue
isnan
detecta valores NaN en una matrizisempty
detecta si es una matriz vacía.
Ejemplo 3:
A = randn()
println(A)
if A>0
println("A es positivo")
elseif A==0
println("A es cero")
else
println("A es negativo")
end
2.202312539016582
A es positivo
Las condiciones son verificadas de manera secuencial. En cuando se cumple una condición, el comando if
ya no continúa con las demás condiciones. Por ejemplo:
3
Comentarios:
- Matrices lógicas:
dummy = (condición)
genera una matriz de dummies si se cumple la condición. - Referenciación:
A(condición)
genera una matriz con los elementos deA
que cumplen la condición. - Si se comparan elemento por elemento dos vectores o matrices, se utiliza la notación
.operador
. - Los condicionales
if
pueden estar anidados entre si y anidados dentro Loops.
Ejemplo del uso de matrices lógicas:
9-element BitArray{1}:
false
false
true
false
false
true
false
true
true
Ejemplo de referenciación:
4×2 Array{Int64,2}:
7 1
5 0
7 4
9 3
4×2 Array{Int64,2}:
7 1
5 0
7 4
9 3