L'istruzione blocca gli argomenti nella cache

A volte il generatore di codici a blocchi deve fare riferimento più volte al codice del suo blocco interno.

Ad esempio, se hai un blocco che stampa l'ultimo elemento di un elenco, devi accedere più volte al codice dell'elenco:

// 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`;
}

Tuttavia, questo può causare problemi se il valore risultante del codice del blocco interno non è coerente o ha effetti collaterali. Ad esempio, se il codice interno è in realtà una chiamata di funzione, questo particolare codice può finire con una condizione fuori intervallo:

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

L'assegnazione a variabili temporanee ti consente di assicurarti che il codice del blocco interno venga valutato una sola volta.

Variabili temporanee

Una variabile temporanea memorizza il valore della stringa di codice di un blocco interno in modo che il codice venga valutato una sola volta e che sia possibile fare riferimento al valore più volte.

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`;
}

La chiamata a getDistinctName prende il nome della variabile che preferisci e restituisce un nome che non è in conflitto con le variabili definite dall'utente.

Riduci il codice ridondante

Lo svantaggio delle variabili temporanee è che se il codice del blocco interno è un valore e non una funzione o un'espressione, si ottiene un codice ridondante:

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

Per generare un codice più chiaro, puoi verificare se il codice del blocco interno è un valore e includere la variabile temporanea solo in caso contrario.

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`;
}