値ブロックの引数のキャッシュ

場合によっては、ブロックコード ジェネレータは内部のコードを参照し、 複数回ブロックされます。

たとえば、リストの最後の要素を取得するブロックがある場合、 リストコードに複数回アクセスするには:

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

ただし、内部ブロックのコードの結果値が 副作用が生じますたとえば、内部コードが実際に 関数呼び出しを行うと、この特定のコードは範囲外の条件になる可能性があります。

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

ユーティリティ関数を使用すると、内部ブロックのコードが 評価は 1 回だけです。

ユーティリティ関数

ユーティリティ関数は、Terraform Registry の一部として含まれる コード文字列を生成します。これを使用して、内部ブロックのコードが確実に 評価は 1 回だけで、値は複数回参照できます。

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

関数を指定する

ブロックコード ジェネレータ内でユーティリティ関数を定義するには、 provideFunction_。ユーティリティ関数に付ける名前を指定します。 関数の機能を定義するコード文字列の配列。このメソッドは、 ユーティリティ関数の結果の名前。 ユーザー定義関数と競合します。

また、provideFunction_ はユーティリティ関数の定義を重複除去するため、 ユーティリティ関数を定義するブロックタイプが存在しても、ユーティリティ関数は一度しか存在しません。 複数回失敗します。

優先度を更新する

ユーティリティ関数を定義するときは、優先順位を付けて (かっこの挿入方法を定義する)を ブロックコード ジェネレータ。

優先順位は常に、ブロックコードによって返されるコード文字列に基づきます。 生成します。ユーティリティ関数内の演算子については考慮しません。したがって、 前の例では、valueToCode 呼び出しが Order.NONE に変更され、 return タプルが Order.FUNCTION_CALL に変更されました。