Variables y constantes
Crea un fichero llamado hello_user.zig con el siguiente contenido:
hello_user.zig |
|
const std = @import("std"); pub fn main() void { std.debug.print("\nHola, usuario.\n", .{}); } |
¿Te acuerdas que en el ejemplo anterior para escribir una línea de texto hicimos:
|
@import("std").debug.print("¡Hola mundo!\n", .{}); |
Ese comando @import importa la librería estándar de Zig en nuestro programa. En el primer ejemplo importamos y usamos la librería en la misma línea. En el segundo ejemplo importamos la librería en la primera línea del programa, fuera de la función main.
|
const std = @import("std"); |
Y además, como ves, al importar la librería, en vez de usar inmediatamente debug.print, asignamos la librería a un identificador (nombre simbólico), en este caso std.
El identificador podría ser diferente. Podríamos poner algo como:
|
const my_fav_lib = @import("std"); |
Pero eso no tendría mucho sentido. La librería estándar se suele asignar al identificador std. Los identificadores que usamos para denominar las cosas deberían ser autoexplicativos.
El uso de la palabra reservada const, delante del identificador, implica que estamos declarando una constante.
Declarar una constante en Zig significa asignar un valor a un identificador (como std o my_fav_lib), y que ese valor ya no se podrá cambiar mientras se ejecuta el programa.
Por ejemplo, podemos asignar otro tipo de valores a las constantes:
|
const n_a = 1; |
En este caso estamos asignando al identificador n_a el valor 1 y ese valor ya no se puede cambiar durante la ejecución del programa.
Vamos a intentar cambiar la constante n_a al valor 2.
const.zig |
|
const std = @import("std"); pub fn main() void { const n_a = 1; n_a = 2; } |
Si Intentamos ejecutar este programa veremos un error:
|
$ zig run constants.zig |
|
constants.zig:6:5: error: cannot assign to constant n_a = 2; ^~~ |
El compilador de Zig nos avisa que no puede (re)asignar un valor a una constante.
Pero ¿y si queremos poder cambiar ese valor?
Es muy sencillo, lo único que tenemos que hacer es poner la palabra clave var en vez de const delante del identificador.
Poner la palabra var delante del nombre simbólico quiere decir que estamos declarando una variable. El valor que contiene una variable puede ser cambiado durante la ejecución del programa.
vars.zig |
|
const std = @import("std"); pub fn main() void { var n_a = 1; n_a = 2; } |
Si intentamos ejecutar vars.zig veremos… ¡Un momento! El compilador tiene una objeción:
|
$ zig run vars.zig |
|
vars.zig:4:9: error: variable of type 'comptime_int' must be const or comptime var n_a = 1; ^~~ vars:5:7: note: to modify this variable at runtime, it must be given an explicit fixed-size number type |
¿Qué significa esto? El compilador necesita saber de forma clara qué tipo de datos va a almacenar la variable. No basta con poner var n_a = 1;, porque Zig aquí necesita saber exactamente qué tipo de número vamos a usar.
Ahora mismo, esto del tipo de dato y el tipo de número puede sonar un poco confuso. No pasa nada. En seguida vamos a ver qué significa todo esto de los tipos de datos en Zig, pero de momento vamos a añadir un tipo explícito a la variable para poder ejecutar el programa.
vars_2.zig |
|
const std = @import("std"); pub fn main() void { var n_a: u8 = 1; // asignamos el tipo u8 n_a = 2; } |
|
$ zig run vars_2.zig |
No tenemos ninguna salida ya que no hemos impreso nada, pero tampoco hay ningún error. Esto quiere decir que hemos conseguido cambiar el valor de la variable n_a con éxito. Intenta jugar un poco con el playground de zenofzig.com con lo aprendido hasta ahora para imprimir esta variable.
Comprendemos que en Zig tenemos:
- Constantes:
Se declaran usando la palabra const delante del identificador y NO pueden cambiar su valor durante la ejecución del programa.
- Variables:
Se declara con var y sí pueden cambiar su valor durante la ejecución del programa, pero necesitamos poner el tipo de dato (u8, i32 etc)
Cuando usar variables y cuando las constantes
Imagina que en un juego comienzas con 3 vidas. Eso es una regla fija - ideal para usar una constante. No cambia mientras se ejecuta el programa, y cada vez que se inicia una nueva partida volvemos a tener esas vidas iniciales. Así podríamos tener:
|
const N_START_LIVES = 3; |
Sin embargo, las vidas actuales que nos quedan en la partida no son un número fijo: pueden ir desde 0 (si perdemos todas) hasta lo máximo que logremos sumar encontrando vidas extra. Esto claramente es una variable ya que va cambiando durante cada partida.
|
var n_lives = N_START_LIVES; |
lives.zig |
|
const std = @import("std"); // vidas al inicio del juego const N_START_LIVES: u8 = 3; pub fn main() void { // vidas al inicio del juego var n_lives = N_START_LIVES; std.debug.print("Tienes {d} vidas\n", .{n_lives}); std.debug.print("¡Oh no! Te acaban de matar.\n", .{}); // el jugador pierde una vida n_lives -= 1; std.debug.print("Ahora tienes {d} vidas\n", .{n_lives}); std.debug.print("Has encontrado una vida extra.\n", .{}); // el jugador recoge una vida extra n_lives += 1; std.debug.print("Ahora tienes {d} vidas\n", .{n_lives}); } |
|
$ zig run lives.zig |
|
Tienes 3 vidas ¡Oh no! Te acaban de matar. Ahora tienes 2 vidas Has encontrado una vida extra. Ahora tienes 3 vidas |
Siguiendo este ejemplo hay que intentar usar:
- const para lo que no cambia
- var para lo que evoluciona durante la ejecución.