L'instruction bloque la mise en cache des arguments

Parfois, votre générateur de code en bloc doit référencer plusieurs fois le code de son bloc interne.

Par exemple, si vous disposez d'un bloc qui imprime le dernier élément d'une liste, vous devez accéder au code de la liste plusieurs fois:

// Incorrect block-code generator.
javascriptGenerator.forBlock['print_last_element'] = function(block, generator) {
  const listCode = generator.valueToCode(block, 'LIST', Order.MEMBER);

  // listCode gets referenced twice.
  return `print(${listCode}[${listCode}.length - 1]);\n`;
}

Toutefois, cela peut entraîner des problèmes si la valeur résultante du code du bloc interne est incohérente ou si elle a des effets secondaires. Par exemple, si le code interne est en réalité un appel de fonction, ce code peut se retrouver avec une condition hors plage:

print(randomList()[randomList().length - 1]);

L'attribution à des variables temporaires vous permet de vous assurer que le code du bloc interne n'est évalué qu'une seule fois.

Variables temporaires

Une variable temporaire stocke la valeur de la chaîne de code d'un bloc interne de sorte que le code n'est évalué qu'une seule fois, puis que la valeur puisse être référencée plusieurs fois.

import {javascriptGenerator, Order} from 'blockly/javascript';

// Correct block-code generator.
javascriptGenerator.forBlock['print_last_element'] = function(block, generator) {
  const listCode = generator.valueToCode(block, 'LIST', Order.MEMBER);
  const listVar = generator.nameDB_.getDistinctName(
      'temp_list', Blockly.names.NameType.VARIABLE);

  // listCode only gets evaluated once.
  const code = `var ${listVar} = ${listCode};\n`;
  return `print(${listVar}[${listVar}.length - 1]);\n`;
}

L'appel getDistinctName utilise le nom de variable souhaité et renvoie un nom qui n'entre pas en conflit avec les variables définies par l'utilisateur.

Réduire le code redondant

L'inconvénient des variables temporaires est que si le code du bloc interne est une valeur et non une fonction ou une expression, vous obtenez un code redondant:

// Assigning to temp_list is unnecessary.
var temp_list = foo;
print(temp_list[temp_list.length - 1]);

Pour générer un code plus propre, vous pouvez vérifier si le code du bloc interne est une valeur et n'inclure la variable temporaire que si ce n'est pas le cas.

if (listCode.match(/^\w+$/)) {
  const code = `print(${listCode}[${listCode}.length - 1]);\n`;
} else {
  const listVar = generator.nameDB_.getDistinctName(
      'temp_list', Blockly.names.NameType.VARIABLE);
  const code = `var ${listVar} = ${listCode};\n`;
  code += `print(${listVar}[${listVar}.length - 1]);\n`;
}