Variables

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

Para obtener más información sobre los lenguajes con tipos dinámicos en comparación con los lenguajes con tipos estáticos, consulta Introducción a los tipos de datos: estáticos, dinámicos, estrictos 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 tipos dinámicos. Si, en cambio, usas un lenguaje con tipos, 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 debes tener en cuenta es que, si configuras la "salida" del método get de la variable como nula, el valor que se muestra puede ser de cualquier tipo. Además, observa que la entrada del setter de la variable no especifica ninguna verificación. Como resultado, la variable se puede configurar en cualquier tipo de valor.

Bloques de variables con tipo

Puedes agregar getters y setters 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 listas desplegables solo muestran variables de tipo "Panda". Sus entradas y salidas solo aceptan conexiones con el tipo "Panda". El defaultType del campo debe establecerse en uno de los valores del array variableTypes. Si no se establece el defaultType mientras se proporciona un array variableTypes, se generará un error.

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

Agrega variables a la caja de herramientas

Para que este nuevo tipo de variable sea útil para tus 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 tus nuevos getters y setters 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, el usuario necesita una forma de crear variables. La forma más sencilla es con un "Crear variable" botón.

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

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.

Define generadores

Por último, deberás definir generadores de código de 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.