場合によっては、ブロックコード ジェネレータは内部のコードを参照し、 複数回ブロックされます。
たとえば、リストの最後の要素を取得するブロックがある場合、 リストコードに複数回アクセスするには:
// 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
に変更されました。