À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 recebe o último elemento de uma lista, você precisa para acessar o código da lista várias vezes:
// Incorrect block-code generator.
javascriptGenerator.forBlock['last_element'] = function(block, generator) {
const listCode = generator.valueToCode(block, 'LIST', Order.MEMBER);
// listCode gets referenced twice.
const code = `${listCode}[${listCode}.length - 1]`;
return [code, Order.MEMBER];
}
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:
randomList()[randomList().length - 1]
O uso de funções utilitárias permite que os blocos internos o código é apenas avaliado uma vez.
Funções do utilitário
Uma função utilitária é uma função definida pelo desenvolvedor, incluída como parte do string de código gerada. Você pode usá-los para garantir que o código de bloco interno seja somente avaliado uma vez, e o valor pode ser referenciado várias vezes.
import {javascriptGenerator, Order} from 'blockly/javascript';
// Correct block-code generator.
javascriptGenerator.forBlock['last_element'] = function(block, generator) {
const listCode = generator.valueToCode(block, 'LIST', Order.NONE);
const functionName = generator.provideFunction_(
'list_lastElement',
[
`function ${generator.FUNCTION_NAME_PLACEHOLDER_}(list) {`,
` return list[list.length - 1];`,
`}`
]
);
// listCode only gets evaluated once.
const code = `${functionName}(${listCode})`;
return [code, Order.FUNCTION_CALL];
}
Forneça a função
É possível definir funções utilitárias dentro de geradores de código de bloco usando
provideFunction_
: Ele usa o nome que você quer para sua função utilitária e
uma matriz de strings de código que definem o que a função faz. Ela retorna
nome resultante da sua função de utilitário, depois de (possivelmente) modificá-la para não
em conflito com as funções definidas pelo usuário.
provideFunction_
também elimina as definições de função utilitária, de modo que cada
a função utilitária só existe uma vez, mesmo que exista o tipo de bloco que a define.
várias vezes.
Atualizar precedências
Ao definir uma função de utilitário, também é preciso atualizar as precedências (que definem como os parênteses são inseridos) incluídos no de código de bloco.
A precedência é sempre baseada na string de código retornada pelo bloco
gerador. Ela não se importa com operadores dentro de funções utilitárias. Então, no
no exemplo anterior, a chamada valueToCode
foi alterada para Order.NONE
, e o
tupla de retorno alterada para Order.FUNCTION_CALL
.