接続チェック

接続チェックは、相互に接続できる接続(およびブロック)を制限します。

接続チェックはタイプのモデリングに役立ちます。たとえば、次の 3 つのブロックは、異なるタイプを返すコードを表すため、ビジネスが接続されていません。

空のリストブロック。平方根ブロックに接続し、大文字ブロックに接続しています。

接続チェックを使用すると、これらのブロックの接続を防ぐことができます。これにより、ユーザーは即座にフィードバックを得ることができ、多くの簡単な間違いを防止できます。

仕組み

すべての接続は、null 値許容の文字列配列である「接続チェック」に関連付けることができます。

次の場合は 2 つの接続が接続できます。

  1. これらは互換性のあるです(入力に接続する出力など)。
  2. 接続チェックに共通の文字列が 1 つ以上あります。

たとえば、次の 2 つのチェックは 'apple' 文字列を共有しているため、接続できます。

['apple', 'ball', 'cat']
['apple', 'bear', 'caterpillar']

しかし、次の 2 つのチェックは文字列を共有していないため接続できませんでした。

['apple', 'ball', 'cat']
['ape', 'bear', 'caterpillar']

もう 1 つの特殊なケースがあります。いずれかの配列が null の場合は、2 つの接続も接続できます。これにより、何に対しても接続できる接続を定義できます。

null
['ape', 'bear', 'caterpillar]

チェックを設定

デフォルトでは、すべての接続に null 接続チェックがあります。つまり、何にも接続できます。接続チェックは手動で割り当てる必要があります。

接続チェックを接続に割り当てる方法は、JSON ブロック定義と JavaScript ブロック定義のどちらを使用するかによって異なります。

JSON

トップレベル接続の場合、接続を定義するプロパティにチェックを直接割り当てます。割り当てる値は、null、文字列(接続チェックで唯一のエントリになります)、文字列の配列です。

{
  'type': 'custom_block',

  'output': null,
  'nextStatement': 'a connection check entry',
  'previousStatement': ['four', 'connection', 'check', 'entries']
}

入力の場合、入力定義の check プロパティにチェックを割り当てることができます。check プロパティが存在しない場合、チェックは null とみなされます。割り当てる値は、文字列または文字列の配列です。

{
  'type': 'custom_block',
  'message0': '%1 %2',

  'args0': [
    {
      'type': 'input_value',
      'check': 'a connection check entry'
    },
    {
      'type': 'input_statement',
      'check': ['four', 'connection', 'check', 'entries']
    }
  ]
}

JavaScript

トップレベル接続の場合、接続を定義するメソッドにチェックを直接渡すことができます。値を渡さない場合、チェックは null と見なされます。渡す値は、文字列(接続チェックで唯一のエントリ)または文字列の配列です。

Blockly.Blocks['custom_block'] = {
  init: function() {
    this.setOutput(true); // null check
    this.setNextStatement(true, 'a connection check entry');
    this.setPreviousStatement(true, ['four', 'connection', 'check', 'entries']);
  }
}

入力の場合は、入力を定義した後で、setCheck メソッドにチェックを渡すことができます。setCheck メソッドが呼び出されない場合、チェックは null とみなされます。渡す値は、文字列または文字列の配列です。

Blockly.Blocks['custom_block'] = {
  init: function() {
    this.appendValueInput('NAME')
        .setCheck('a connection check entry');
    this.appendStatementInput('NAME')
        .setCheck(['four', 'connection', 'check', 'entries']);
  }
}

組み込みのチェック文字列

組み込みブロックには、値 'Array''Boolean''Colour''Number''String' による接続チェックがあります。ブロックを組み込みブロックと相互運用する場合は、これらの値を使用して互換性を維持できます。

価値の例

入力と出力の接続チェックを定義する場合、通常はチェックをタイプを表すものと考えてください。

入力のチェックには受け入れる「型」をすべて含める必要があり、出力のチェックには「返される」ものを正確に含める必要があります。

単一のタイプを受け入れる

1 つのタイプを「受け入れる」または「返す」ブロックを作成する最も基本的なケースでは、そのタイプを接続の接続チェックに含める必要があります。

1 つの value ブロックで

複数のタイプを受け入れる

複数のタイプを受け入れるブロックを作成するには、受け入れられるタイプをすべて入力の接続チェックに含める必要があります。

複数の型を受け入れる value ブロック

慣例として、出力を複数の状況で受け入れることができる場合(数値を文字列として使用できるようにする場合など)、出力をより制限し、入力の許容度を上げます。この規則により、出力がサポートされていない場所に接続されないようになっています。

任意のタイプを許可

あらゆる型を受け入れるブロックを作成するには、入力の接続チェックを null に設定する必要があります。

任意の型を受け入れる value ブロック

戻り値のサブタイプ

サブタイプを「返す」ブロックを作成するには、出力の接続チェックにタイプとスーパータイプの両方を含める必要があります。

型とそのスーパータイプを返す value ブロック

サブタイプの場合、ブロックは常に両方のタイプを「返す」ため、出力チェックに複数のチェックを含めることができます。

パラメータ化された型を返す

パラメータ化された型を「返す」ブロックを作成するには、パラメータ化されたバージョンとパラメータ化されていないバージョンの両方を出力の接続チェックに含める必要があります。

ブロック言語にどの程度の厳格さを適用するかによっては、型の variance(s) も含められます。

パラメータ化された型とパラメータ化されていない型を返す値ブロック

サブタイプと同様に、ブロックは常に両方のタイプを「返す」ため、この場合は出力チェックに複数のチェックを含めることができます。

スタックまたはステートメントの例

デベロッパーが前後の接続のチェックを定義する一般的な方法はいくつかあります。通常、これらはブロックの順序を制限するものと考えることができます。

次の接続には、現在のブロックの後に表示するブロックが含まれ、以前の接続には現在のブロックの内容が含まれます。

ブロックを並べ替える

定義された順序で接続するブロックのセットを作成するには、現在のブロックの後に続くブロックを次回の接続チェックで指定し、前の接続チェックで現在のブロックの内容を指定する必要があります。

ステートメント ブロックがあり、

中間ブロックを多数設ける

多数の中間ブロックを許可する順序付きブロックのセットを作成するには、中間ブロックの前の接続チェックから少なくとも 1 つのエントリを中間ブロックの次の接続チェックに含める必要があります。そうすれば、ブロックの後ろに続きが来ます。

ステートメント ブロックを使用すると、

中間ブロックを許可しない

中央のブロックがオプションである順序付きブロックのセットを作成するには、中央のブロックの前の接続チェックと、最初のブロックの次の接続チェックに最後のブロックの以前の接続チェックの両方のエントリを少なくとも 1 つ含める必要があります。これにより、最初のブロックの後に、中間ブロックまたは最後のブロックを続けることができます。

ステートメント ブロックを使用すると、

いずれかのスタック

1 つのグループのブロックか、もう 1 つのグループのブロック(両方ではないグループ)の後にしかブロックできないブロックを作成するには、次の 2 つのことを行う必要があります。

  1. 最初のブロックの次の接続チェックには、以前の接続チェックの両方のグループから 1 つ以上のエントリを含める必要があります。

  2. 前回の接続チェックで使用した値のみが含まれるように、グループの次の接続チェックを定義する必要があります(同じグループのブロックのみが続くようにできます)。

ステートメント ブロックの後に、同じ種類のブロックの複数、または別のタイプの複数のブロックが後に続くことがあります。ただし、両方は指定できません。

制限事項

このシステムは非常に堅牢で、多くのユースケースを解決できますが、いくつかの制限があります。

上位コンテキストを制限する

このシステム自体は、接続で接続が許可される「上位のコンテキスト」を制限することはサポートしていません。たとえば、break ブロックが loop ブロックの内部にのみ存在できるとは言えません。接続チェック システムでは、直近の 2 つの接続のみが接続されているとみなします。

これは、イベント システムを使用してブロック移動イベントをリッスンし、ブロックが正しく配置されていないかどうかを確認することで対応できます

Blockly.Blocks['custom_block'] = {
  init: function() { }

  onchange: function(e) {
    if (this.workspace.isDragging()) return;
    if (e.type !== Blockly.Events.BlockMove) return;
    if (!this.getSurroundLoop()) this.outputConnection.disconnect();
  }

  loopTypes: new Set(); // Your valid *block types* (not connection checks).

  getSurroundLoop: function () {
    let block = this.getSurroundParent();
    do {
      if (loopTypes.has(block.type)) return block;
      block = block.getSurroundParent();
    } while (block);
    return null;
  },
}

一般的な種類

このシステム自体は汎用型の定義をサポートしていません。たとえば、どのような入力があっても「返す」「Identity」ブロックは作成できません。

これは、ブロックの出力の接続チェックをその入力に一致するように積極的に変更することである程度サポートできます。これは、イベント システムを使用して移動イベントをブロックするためにリッスンできます。

Blockly.Blocks['custom_block'] = {
  init: function() { }

  onchange: function(e) {
    if (e.type !== Blockly.Events.BlockMove) return;
    this.setOutput(
        true, this.getInputTargetBlock()?.outputConnection.getCheck());
  }
}

しかし、接続されたブロックも汎用である場合、これは正しく機能しません。この場合、回避策はありません。

接続チェッカー

このシステムがユースケースで機能しない場合は、カスタム接続チェッカーを作成して、接続チェックの比較方法を変更することもできます。

たとえば、このような制限の一部を処理する、より高度なシステムを作成する場合は、カスタム接続チェッカーを作成できます。