값 블록 인수 캐싱

블록 코드 생성기가 내부 블록의 코드를 여러 번 참조해야 하는 경우가 있습니다.

예를 들어 목록의 마지막 요소를 가져오는 블록이 있다면 목록 코드에 여러 번 액세스해야 합니다.

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

유틸리티 함수를 사용하면 내부 블록의 코드가 한 번만 평가되도록 할 수 있습니다.

유틸리티 함수

유틸리티 함수는 생성된 코드 문자열의 일부로 포함된 개발자 정의 함수입니다. 이를 사용하여 내부 블록 코드가 한 번만 평가된 후 값을 여러 번 참조하도록 할 수 있습니다.

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로, 반환 튜플이 Order.FUNCTION_CALL로 변경되었습니다.