Buforowanie argumentów bloku wartości

Czasami generator kodów blokowych musi wielokrotnie odwoływać się do kodu swojego wewnętrznego bloku.

Jeśli np. masz blok, który pobiera ostatni element listy, musisz wielokrotnie przechodzić do kodu listy:

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

Może to jednak powodować problemy, jeśli wynikowa wartość kodu bloku wewnętrznego jest niespójna lub ma to skutki uboczne. Jeśli np. kod wewnętrzny jest w rzeczywistości wywołaniem funkcji, ten konkretny kod może zawierać warunek „poza zakresem”:

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

Dzięki funkcjom użytkowym kod wewnętrznych bloków jest oceniana tylko raz.

Funkcje użytkowe

Funkcja narzędziowa to zdefiniowana przez dewelopera funkcja dołączona jako część wygenerowanego ciągu kodu. Dzięki nim możesz mieć pewność, że kod bloku wewnętrznego będzie oceniany tylko raz, a potem będzie można się do niego odwoływać wiele razy.

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

Podaj funkcję

Funkcje narzędziowe możesz definiować w generatorach kodu blokowego za pomocą polecenia provideFunction_. Funkcja ta przyjmuje nadana przez Ciebie nazwę oraz jest tablicę ciągów znaków określających jej działanie. Zwraca on wynikową nazwę funkcji narzędziowej po zmodyfikowaniu (prawdopodobnie) jej zmodyfikowaniu w taki sposób, aby nie kolidowała z funkcjami zdefiniowanymi przez użytkownika.

provideFunction_ powiela też definicje funkcji narzędziowych, dzięki czemu każda funkcja narzędzia istnieje tylko raz, nawet jeśli typ bloku, który ją definiuje, istnieje wiele razy.

Pierwszeństwa aktualizacji

Gdy definiujesz funkcję narzędzia, musisz też zaktualizować pierwszeństwo (określające sposób wstawiania nawiasów) w generatorze kodów bloków.

Pierwszeństwo opiera się zawsze na ciągu znaków z kodem zwróconym przez generator kodów blokowych. Operatory wewnątrz funkcji narzędziowych nie mają znaczenia. W poprzednim przykładzie wywołanie valueToCode zostało zmienione na Order.NONE, a kropka zwrotna – na Order.FUNCTION_CALL.