Tracks
/
jq
jq
/
Ejercicios
/
Auto de control remoto
Auto de control remoto

Auto de control remoto

Ejercicio de aprendizaje

Introducción

Funciones

Puedes definir tus propias funciones personalizadas en jq para encapsular la lógica que necesites. Las funciones se comportan igual que las integradas: reciben una entrada y emiten cero, una o más salidas.

Definir una función

Puedes definir una función de jq con la siguiente sintaxis:

# no arguments
def funcname: expression;

# or with arguments
def funcname(args): expression;
  • empieza con la palabra clave def,
  • dos puntos antes del cuerpo de la función,
  • el cuerpo consiste en una sola expresión,
  • termina con un punto y coma,
  • como en el resto de la sintaxis de jq, puedes usar espacios en blanco arbitrarios para que se lea mejor.

Dónde colocar las funciones

Las funciones deben definirse antes de usarse: esto es un error:

def A: B(10);
def B(n): n + 1;
A
# => error: B/1 is not defined

Esto implica que debes colocar las funciones al inicio de tu código de jq, antes de la expresión «principal».

Funciones anidadas

Las funciones se pueden anidar:

def A:
    def B(n): n + 1;
    B(10)
    ;
A
# => 11

Aquí, la función B solo es visible en el cuerpo de A.

Ámbito

Una función introduce un nuevo ámbito para las variables y las funciones anidadas.

Argumentos

Los argumentos de una función se separan con punto y coma, no con comas. Por ejemplo, una función que recibe un número y luego suma un número y multiplica por un número:

def add_mul(adder; multiplier): (. + adder) * multiplier;

10 | add_mul(5; 4)    # => 60
Note

Se necesitan los puntos y coma porque la coma ya tiene un propósito en jq: es un operador que une flujos.

Usar una coma en lugar de un punto y coma intentará hacer dos llamadas a una función add_mul de 1 argumento, que no existe y por lo tanto fallará en la primera llamada:

10 | add_mul(5, 4)
# error: add_mul/1 is not defined
Los argumentos son expresiones

Los argumentos de una función son filtros, no valores. En este sentido, actúan como lo que otros lenguajes describen como callbacks:

Usando la función add_mul como ejemplo:

10 | add_mul(. + 5; . - 2)    # => 200

¿Qué está pasando aquí?

  • el argumento adder recibe la expresión . + 5
    • cuando la función hace . + adder, eso se convierte en . + . + 5
    • eso se evalúa como 25, ya que . == 10
  • de manera similar, el argumento multiplier es la expresión . - 2
    • eso se evalúa como 8
    • entonces el resultado es 25 * 8 == 200
Argumentos como valores

A veces vas a querer «materializar» un argumento en una variable:

def my_func(arg):
    arg as $arg
    | other stuff ...
;

Hay una forma abreviada de hacer esto:

def my_func($arg):
    other stuff ...
;

Ten en cuenta que esto es solo «azúcar sintáctico»: el nombre arg sin $ sigue estando en el ámbito de la función.

Aridad

Las funciones tienen una aridad: la cantidad de argumentos que reciben.

Las funciones pueden usar el mismo nombre con distintas aridades. La función integrada range lo demuestra: range/1, range/2 y range/3 coexisten.

Esto puede ser útil para definir funciones recursivas que llevan estado a través de los argumentos. Por ejemplo, map podría implementarse así:

def my_map($accumulator; func):
    if length == 0
        then $accumulator
        else first as $elem | .[1:] | my_map($accumulator + [$elem | func]; func)
    end
    ;

def my_map(func):
    my_map([]; func)
    ;

[1, 2, 3, 4] | my_map(. * 10)   # => [10, 20, 30, 40]

Recursión

jq realiza optimización de llamadas de cola, pero solo para funciones de aridad 0.

Módulos

Un módulo de jq es un archivo que contiene solo funciones. Los módulos se incluyen en un programa de jq con los comandos include o import.

Instrucciones

En este ejercicio vas a jugar con un auto a control remoto, para el que por fin ahorraste suficiente dinero para comprarlo.

Los autos empiezan con la batería llena (100%). Cada vez que conduces el auto con el control remoto, recorre 20 metros y consume uno por ciento de la batería. El apodo del auto no se conoce hasta que se crea.

El auto a control remoto tiene una pantalla LED muy elegante que muestra dos datos:

  • La distancia total que ha recorrido, la cual se muestra así: "<METERS> meters".
  • La carga restante de la batería, la cual se muestra así: "Battery at <PERCENTAGE>%".

Si la batería está al 0%, ya no puedes conducir el auto y la pantalla de la batería mostrará "Battery empty".

1. Crea un auto a control remoto completamente nuevo

Implementa la función new_remote_control_car/0 para que devuelva un objeto de auto a control remoto completamente nuevo:

new_remote_control_car
# => {
#      "battery_percentage": 100,
#      "distance_driven_in_meters": 0,
#      "nickname": null
#    }

2. Crea un auto a control remoto completamente nuevo con un apodo

Implementa la función new_remote_control_car/1 para que devuelva un objeto de auto a control remoto completamente nuevo con un apodo proporcionado:

new_remote_control_car("Blue")
# => {
#      "battery_percentage": 100,
#      "distance_driven_in_meters": 0,
#      "nickname": "Blue"
#    }

3. Muestra la distancia

Implementa la función display_distance/0, que recibe como argumento un objeto de auto y devuelve el string de la distancia tal como se muestra en la pantalla LED:

new_remote_control_car | display_distance
# => "0 meters"

4. Muestra el porcentaje de batería

Implementa la función display_battery/0, que recibe como argumento un objeto de auto y devuelve el string del porcentaje de batería tal como se muestra en la pantalla LED:

new_remote_control_car | display_battery
# => "Battery at 100%"

Si la batería está al 0%, la pantalla de la batería mostrará «Battery empty».

5. Conducir cambia la batería y la distancia recorrida

Implementa la función drive/0, que:

  • recibe como argumento un objeto de auto
  • incrementa en 20 la cantidad de metros recorridos
  • consume un 1% de la batería
  • devuelve el objeto de auto modificado
new_remote_control_car("Red") | drive
# => {
#      "battery_percentage": 99,
#      "distance_driven_in_meters": 20,
#      "nickname": "Red"
#    }

6. Ten en cuenta cómo conducir con la batería agotada

Modifica la función drive/0 para que no aumente la distancia recorrida ni disminuya el porcentaje de batería cuando la batería está agotada (al 0%):

{
  battery_percentage: 0,
  distance_driven_in_meters: 2000,
  nickname: "Red"
} | drive
# => {
#      "battery_percentage": 0,
#      "distance_driven_in_meters": 2000,
#      "nickname": "Red"
#    }
Editar en GitHub El enlace se abre en una ventana o una pestaña nuevas
jq Exercism

¿Todo listo para empezar Auto de control remoto?

Regístrate en Exercism para aprender y dominar jq con 12 conceptos75 ejercicios y mentoría humana real, todo gratis.