Variables

Las variables son un concepto de programación importante. Blockly admite lenguajes con escritura dinámica, como Python y JavaScript, y, con un poco de trabajo adicional, puedes agregar información para admitir lenguajes con escritura sólida (o lenguajes con escritura estática), como Java o C.

Para obtener más información sobre los lenguajes con escritura dinámica y estática, consulta Introducción a los tipos de datos: estáticos, dinámicos, sólidos y débiles.

Blockly proporciona campos de variables que son cuadros desplegables dinámicos que muestran los nombres de las variables que proporcionó el usuario. A continuación, se muestra un ejemplo.

Un campo de variable con un menú desplegable para elegir una variable, cambiar el nombre de la variable actual o borrar la variable actual.

De forma predeterminada, Blockly permite que se asigne cualquier tipo a una variable, y todos los generadores proporcionados por Blockly son para lenguajes con escritura dinámica. Si usas un lenguaje con escritura, puedes configurar Blockly para que lo admita de la siguiente manera:

Bloques de variables sin tipo

Los bloques más básicos para acceder a una variable y manipularla son los bloques getter y setter. Veamos los bloques getter y setter que proporciona Blockly.

JSON

// Block for variable getter.
{
  "type": "variables_get",
  "message0": "%1",
  "args0": [
    {    // Beginning of the field variable dropdown
      "type": "field_variable",
      "name": "VAR",    // Static name of the field
      "variable": "%{BKY_VARIABLES_DEFAULT_NAME}"    // Given at runtime
    }    // End of the field variable dropdown
  ],
  "output": null,    // Null means the return value can be of any type
  ...
},

// Block for variable setter.
{
  "type": "variables_set",
  "message0": "%{BKY_VARIABLES_SET}",
  "args0": [
    {
      "type": "field_variable",
      "name": "VAR",
      "variable": "%{BKY_VARIABLES_DEFAULT_NAME}"
    },
    {
      "type": "input_value",    // This expects an input of any type
      "name": "VALUE"
    }
  ],
  ...
}

JavaScript

// Block for variable getter.
Blockly.Blocks['variables_get'] = {
  init: function() {
    this.appendDummyInput()
      .appendField(new Blockly.FieldVariable("VAR_NAME"), "FIELD_NAME");
    this.setOutput(true, null);
    ...
  }
};

// Block for variable setter.
Blockly.Blocks['variables_set'] = {
  init: function() {
    this.appendValueInput("NAME")
        .setCheck(null)
        .appendField("set")
        .appendField(new Blockly.FieldVariable("VAR_NAME"), "FIELD_NAME")
        .appendField("to");
    this.setOutput(true, null);
    ...
  }
};

Esto crea los siguientes dos bloques:

Bloques de getter y setter para la variable "foo".

Un detalle importante que se debe tener en cuenta es que, si se establece el "resultado" del getter de la variable como nulo, el valor de devolución puede ser de cualquier tipo. Además, observa que la entrada del establecedor de variables no especifica ninguna verificación. Como resultado, la variable se puede establecer en cualquier tipo de valor.

Bloques de variables con tipo

Puedes agregar métodos getter y setter que apliquen la verificación de tipos. Por ejemplo, si creaste una variable de tipo "Panda", las siguientes definiciones crean un getter y un setter con los tipos adecuados.

JSON

// Block for Panda variable getter.
{
  "type": "variables_get_panda",
  "message0": "%1",
  "args0": [
    {
      "type": "field_variable",
      "name": "VAR",
      "variable": "%{BKY_VARIABLES_DEFAULT_NAME}",
      "variableTypes": ["Panda"],    // Specifies what types to put in the dropdown
      "defaultType": "Panda"
    }
  ],
  "output": "Panda",    // Returns a value of "Panda"
  ...
},

 // Block for Panda variable setter.
{
  "type": "variables_set_panda",
  "message0": "%{BKY_VARIABLES_SET}",
  "args0": [
    {
      "type": "field_variable",
      "name": "VAR",
      "variable": "%{BKY_VARIABLES_DEFAULT_NAME}",
      "variableTypes": ["Panda"],
      "defaultType": "Panda"
    },
    {
      "type": "input_value",
      "name": "VALUE",
      "check": "Panda"    // Checks that the input value is of type "Panda"
    }
  ],
  "previousStatement": null,
  "nextStatement": null,
  ...
}

JavaScript

// Block for Panda variable getter.
Blockly.Blocks['variables_get_panda'] = {
  init: function() {
    this.appendDummyInput()
      .appendField(new Blockly.FieldVariable(
          "VAR_NAME", ['Panda'], 'Panda'), "FIELD_NAME");
    this.setOutput(true, 'Panda');
    ...
  }
};

// Block for Panda variable setter.
Blockly.Blocks['variables_set_panda'] = {
  init: function() {
    this.appendValueInput("NAME")
        .setCheck('Panda')
        .appendField("set")
        .appendField(new Blockly.FieldVariable(
            "VAR_NAME", null, ['Panda'], 'Panda'), "FIELD_NAME")
        .appendField("to");
        this.setPreviousStatement(true, null);
        this.setNextStatement(true, null);
    ...
  }
};

Esto crea dos tipos de bloques: un getter y un setter. Sus menús desplegables solo muestran variables de tipo "Panda". Sus entradas y salidas solo aceptan conexiones de tipo "Panda". El defaultType del campo debe establecerse en uno de los valores del array variableTypes. Si no se configura defaultType cuando se proporciona un array variableTypes, se generará un error.

De forma predeterminada, no hay ningún indicador visual que le indique al usuario qué tipo se está usando. Una forma sencilla de diferenciar los tipos de variables es por color.

Cómo agregar variables a la caja de herramientas

Para que este nuevo tipo de variable sea útil para los usuarios, debes agregar una forma de crear y usar las variables nuevas.

Crea una nueva categoría dinámica para las variables si aún no tienes una.

Una categoría abierta llamada "Variables" que contiene un botón "Crear variable".

Agrega los nuevos métodos get y set a la categoría.

La misma categoría después de que se crearon las variables "foo" y "bar". Contiene un botón "Crear variable", bloques establecer variable en y cambiar variable en, y bloques getter.

Botón Crear variable

A continuación, tu usuario necesita una forma de crear variables. La forma más sencilla es con un botón "Crear variable".

Cuando crees el botón, haz la llamada de devolución de llamada

Blockly.Variables.createVariableButtonHandler(button.getTargetWorkspace(), null, 'panda');

y se creará una variable con tipo "Panda".

La forma más sencilla de permitir que los usuarios creen variables de varios tipos es tener un botón "Crear" por tipo (p.ej., Crear variable de cadena, Crear variable numérica, Crear variable de Panda).

Si tienes más de dos o tres tipos de variables, puedes terminar rápidamente con demasiados botones. En ese caso, considera usar @blockly/plugin-typed-variable-modal para mostrar una ventana emergente desde la que los usuarios puedan seleccionar el tipo de variable que deseen.

Cómo definir generadores

Por último, deberás definir generadores de código en bloque para tus nuevos bloques de variables. También puedes acceder a la lista de variables directamente con Workspace.getVariableMap().getAllVariables() para obtener todas las variables de todos los tipos o Workspace.getVariableMap().getVariablesOfType() para obtener todas las variables de un tipo específico.