L'istruzione blocca gli argomenti nella cache

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

Ad esempio, se hai un blocco che stampa l'ultimo elemento di un elenco, è necessario accedere più volte al codice 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`;
}

ma ciò può causare problemi se il valore risultante del codice del blocco interno non coerenti o presentano effetti collaterali. Ad esempio, se il codice interno è effettivamente una chiamata di funzione, questo particolare codice può risultare con una condizione fuori intervallo:

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

L'assegnazione a variabili temporanee assicura che il codice del blocco interno valutata una sola volta.

Variabili temporanee

Una variabile temporanea memorizza il valore della stringa di codice di un blocco interno in modo che il codice viene valutato una sola volta e al valore può essere fatto riferimento in 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 getDistinctName accetta il nome della variabile desiderato e restituisce un che non entri 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 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 includi la variabile temporanea solo se non lo è.

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