Às vezes, o gerador de código de bloco precisa referenciar o código do próprio bloco várias vezes.
Por exemplo, se você tem um bloco que imprime o último elemento de uma lista, precisa acessar o código da lista várias vezes:
// 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`;
}
Mas isso pode causar problemas se o valor resultante do código do bloco interno for inconsistentes ou têm efeitos colaterais. Por exemplo, se o código interno for uma chamada de função, esse código específico pode acabar com uma condição fora do intervalo:
print(randomList()[randomList().length - 1]);
A atribuição a variáveis temporárias permite que você se certifique de que o código do bloco interno seja avaliado apenas uma vez.
Variáveis temporárias
Uma variável temporária armazena o valor da string de código de um bloco interno para que o código é avaliado apenas uma vez e, em seguida, o valor pode ser referenciado várias vezes.
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`;
}
A chamada getDistinctName
usa o nome da variável que você quer e retorna uma
que não entre em conflito com nenhuma variável definida pelo usuário.
Reduzir o código redundante
A desvantagem das variáveis temporárias é que, se o código do bloco interno for um valor e não uma função ou expressão, você recebe um código redundante:
// Assigning to temp_list is unnecessary.
var temp_list = foo;
print(temp_list[temp_list.length - 1]);
Para produzir um código mais limpo, você pode verificar se o código do bloco interno é um valor e inclua a variável temporária apenas se não for.
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`;
}