有効範囲

有効範囲(スコープ)とは、代入したり宣言したりした変数または、宣言した手順が使える範囲を表します。
変数は、有効範囲の中で使うことができ、有効範囲を超えると変数の内容を取得できなくなります。
手順は、有効範囲の中で呼び出すことができ、有効範囲を超えた場所からは呼び出せません。

プロデルでは、有効範囲の単位として次のような範囲があります。

  • プログラム全体 (変数・手順)
  • 種類内部 (変数・手順)
  • 手順内部 (変数)
  • 制御文(もし文・繰り返し文)内部 (変数)
  • ブロック式内部 (変数)

変数の暗黙宣言と明示的宣言

プロデルの変数は、便宜上、明示的に宣言することなく、使うことができます。
変数に対して値を代入した時点で、暗黙的に変数が宣言されたものとして扱われ、変数を使えるようになります。
暗黙的に変数を宣言した場合、変数の有効範囲は、その変数が代入された手順が属する種類内部となります。
手順が種類に属していない場合は、プログラム全体となります。

一方、変数を特定の有効範囲内でのみ使いたい場合(ローカル変数として使いたい場合)は、
【 】を使って変数を明示的に宣言する必要があります。
明示的に変数を宣言した場合、変数の有効範囲は、その変数が宣言された場所と同じ有効範囲となります。
例えば、手順内部で変数宣言した場合は、有効範囲が手順内部になります。

プログラム全体

プログラム全体は、プロデルプログラムに含まれるすべての種類・手順を対象とします。
プロジェクトモードの場合は、プロジェクトに含まれるすべてのプロデルプログラムのすべての種類・手順を対象とします。

有効範囲の対象

宣言・代入場所

プログラム冒頭で、宣言または初めて代入した変数は、プログラム全体が有効範囲になります。
プログラム冒頭とは、プロデルデザイナでの「(全体)の(はじめ)」にあたる部分を指します。

有効範囲

有効範囲がプログラム全体である変数・手順は、プロデルプログラム内のすべての種類・手順から使えます。

種類内部

種類内部は、一つの種類に含まれるすべての手順を対象とします。

宣言・代入場所

種類の「はじめ」の手順または種類の宣言領域で、宣言または初めて代入した変数は、種類内部が有効範囲になります。
種類の宣言領域とは、種類内部のうち、手順内部ではない部分を指します。

例えば、種類内部が有効範囲の変数を明示的に宣言するには、次のように書きます。

車とは
  +名前
終わり

また、次のように「はじめ」の手順で「名前」変数に値を代入した時も、「名前」変数の有効範囲は、種類内部になります。

車とは
  はじめの手順
    名前は、「太郎の車」
  終わり
終わり

有効範囲

有効範囲が種類全体である変数・手順は、その種類内のすべての手順から使えます。

なお、種類内の変数や手順が公開状態場合(+記号で宣言した場合)は、
種類名を指定すれば、その種類以外の有効範囲から使えます。
例えば、「車」種類にある「名前」変数は、種類内の手順では「名前」と書けば使えます。
その種類以外からは、「車の名前」と書ければ使えます。

名前を表示する  //名前という変数はありません
車の名前を表示する

車とは
  +名前

  はじめの手順
    名前は、「太郎の車」
  終わり

  走る手順
    名前を表示する
  終わり

終わり

手順内部

手順内部とは、一つの手順の中にある文を対象とします。

明示的に変数を宣言した場合

手順で変数を宣言すると、変数の有効範囲は、手順内部になります。
また、手順の仮引数の有効範囲も、手順内部になります。

有効範囲が手順内部である変数は、その手順内でのみ使えます。

例えば、次のプログラムにある「走る」手順で、
「名前」変数を宣言していますので、変数の有効範囲は、その手順内部となります。
そのため、それ以外の手順からは、「名前」変数を使えません。

車とは

  走る手順
    【名前】
    名前は、「太郎の車」
  終わり

  止まる手順
    名前を表示する  //「名前」という変数はありません。
  終わり

終わり

この有効範囲で代入した場合

宣言せずにはじめて代入した変数は、種類内部が有効範囲になります。
種類に属さない手順の場合は、プログラム全体になります。

例えば、次のプログラムにある「走る」手順では、
「名前」変数へ値を代入しているだけなので、変数の有効範囲は、種類内部となります。
そのため同じ種類のそれ以外の手順からも、「名前」変数を使えます。
ただし、手順が属する種類の以外からは、使えません。

車とは

  走る手順
    名前は、「太郎の車」
  終わり

  止まる手順
    名前を表示する
  終わり

終わり

掃除する手順
  名前を表示する  //「名前」という変数はありません。
終わり

制御文内部

制御文内部とは、一つの制御文の中にある文を対象にします。
有効範囲が個別に決められている制御文は、「もし」文と「繰り返す」文だけです。
それ以外の制御文は、手順内部の有効範囲のままとなります。

制御文の有効範囲

明示的に変数を宣言した場合

もし文・繰り返す文で変数を宣言すると、変数の有効範囲は、制御文内部になります。

有効範囲が制御文内部である変数は、その制御文内でのみ使えます。
例えば、次のプログラムのもし文の内部では、
「A」変数を宣言していますので、変数の有効範囲が制御文内部となります。
そのため、もし文が終わると、「A」変数は使えなくなります。

もし値が1なら
  【A】=10
そうでなければ
  【A】=20
もし終わり
Aを報告する  //Aという変数はありません

この有効範囲で代入した場合

宣言せずにはじめて代入した変数は、種類内部が有効範囲になります。
種類に属さない手順の場合は、プログラム全体になります。

例えば、次のプログラムにあるもし文の内部では、
「A」変数に値を代入しているだけなので、変数の有効範囲は、種類内部になります。
種類に属さない手順の場合、変数の有効範囲はプログラム全体になります。
もし文が終わっても、「A」変数を使えます。

もし1=1なら
  Aは、10
そうでなければ
  Aは、20
もし終わり
Aを報告する

ブロック式内部

ブロック式内部とは、一つのブロック式の中にある文を対象にします。

ブロック式内部の有効範囲

明示的に宣言した場合

ブロック式で変数を宣言すると、変数の有効範囲は、そのブロック式内部になります。
有効範囲がブロック式内部である変数は、そのブロック式内でのみ使えます。

例えば、次のようにブロック式内部で宣言した「A」変数は、変数の有効範囲がブロック式内部となります。
そのため、ブロック式が終わると「A」変数は使えません。

『【A】=1。A=A+1』を実行する
Aを報告する  //Aという変数はありません

この有効範囲で代入した場合

宣言せずにはじめて代入した変数の有効範囲は、ブロック式を書いた手順が属する種類内部になります。
種類に属さない手順の場合、プログラム全体になります。

クロージャ

プロデルのブロック式は、実行時に評価されると「匿名手順」種類のオブジェクトとなります。
このオブジェクトの「実行する」手順が実行されたときは、ブロック式が評価された時の有効範囲が適用されます。

例えば、次のプログラムでは、「閉包処理を実行した」時には、
「クロージャを生成する」手順にある「A」変数の有効範囲が適用されます。

つまり、本来は、「クロージャを生成する」手順で宣言した「A」変数は、手順が終わると使えなくなりますが、
ブロック式を書いて、匿名手順にすることで、手順が終わった後でも「A」変数を使えるようになります。

閉包処理は、クロージャを生成したもの

5回、繰り返す
  閉包処理を実行したものを報告する
繰り返し終わり

クロージャを、生成する手順
  【A】=0
  『A=A+1。Aを返す』を返す
終わり

このように、ブロック式を使うことによって、本来の変数の有効範囲を超えて変数を使うことができる仕組みを
一般にクロージャと呼びます。