Kuina-chan

くいなちゃん2018年12月11日


プログラミング言語Kuin」の逆引き辞典6、文とブロックの扱い方についてです。

目次

1基本的な処理を行う

1.1式を実行する



式を単に実行するには「do 」と書きます(図1-1)。
  1. func main()
  2.   var n: int
  3.   do n :: 1
  4. end func
図1-1: 式の実行

1.2変数にアクセスできるスコープを分ける



ある特定の範囲でしか使わない変数は、予期しないアクセスを防ぐために、ブロックの中で定義します(図1-2)。
  1. func main()
  2.   var a: int
  3.  
  4.   block
  5.     var b: int
  6.     do a :: 1
  7.     do b :: 1
  8.   end block
  9.  
  10.   do a :: 2
  11. end func
図1-2: 変数のスコープ
5行目のようにブロックの中で定義された変数bは、7行目のようにブロックの中でのみアクセスできます。
2行目のようにブロックの外で定義された変数aは、6行目のようにブロックの中でも、10行目のようにブロックの外でもアクセスできます。
ここでいうブロックとは「block」だけでなく、「if」「while」などのすべてのブロックを指します。

1.3ブロックを抜ける



「block」「if」「while」などすべてのブロックは、名前を付けることで「break」文で抜けることができます(図1-3)。
  1. func main()
  2.   block b
  3.     var x: int :: 3
  4.     break b
  5.     var y: int :: 5
  6.   end block
  7. end func
図1-3: break文
2行目のように「ブロックの種類 ブロック名」と書いて、4行目のように「break ブロック名」と書くと、そのブロックを抜けることができます。 この場合5行目の処理は行われません。
例えばifブロックの場合ではブロック名は、「if ブロック名(条件式)」と書きます(図1-4)。
  1. func main()
  2.   if a(3 < 5)
  3.     var x: int :: 3
  4.     break a
  5.     var y: int :: 5
  6.   end if
  7. end func
図1-4: ifブロックのbreak文

2条件分岐を行う

条件や値に応じて処理を分けるには、「if」ブロックや「switch」ブロックを使います。

2.1条件によって処理を分ける



条件式が真か偽かによって処理を分けるには「if」ブロックを使います(図2-1)。
  1. func main()
  2.   var n: int :: 3
  3.   var s: []char
  4.   if(n < 2)
  5.     do s :: "n < 2"
  6.   end if
  7. end func
図2-1: ifブロック
4行目のように「if(条件式)」としてbool型の条件式を書くと、式がtrueなら「end if」までの命令を実行し、falseなら「end if」までの命令を飛ばしてから、その後のプログラムを実行します。
条件式がfalseだったときにも、さらに「elif」を書いて条件式と処理を追加することができます(図2-2)。
  1. func main()
  2.   var n: int :: 3
  3.   var s: []char
  4.   if(n < 2)
  5.     do s :: "n < 2"
  6.   elif(n < 5)
  7.     do s :: "2 <= n & n < 5"
  8.   else
  9.     do s :: "5 <= n"
  10.   end if
  11. end func
図2-2: elif節とelse節
この例の場合、「n<2」の条件式がtrueなら中身の5行目を処理し、条件式がfalseで次の「n<5」の条件式がtrueなら中身の7行目を処理し、どの条件式もtrueにならなければ「else」の中身の9行目を処理します。
1つのifブロックに対し「elif」はいくつでも追加でき、「else」はそれらの最後に追加できます。
式の中で、条件式に応じて値を変えたい場合には、条件演算子「?(,)」が便利です。 「条件式 ?(trueのときの値, falseのときの値)」と書きます(図2-3)。
  1. func main()
  2.   var n: int :: 3
  3.   var s: []char
  4.   do s :: n < 2 ?("n < 2", "n >= 2") {"n >= 2"}
  5. end func
図2-3: 条件演算子

2.2値によって処理を分ける



値によって処理を分けるには「switch」ブロックを使います(図2-4)。
  1. func main()
  2.   var n: int :: 3
  3.   var s: []char
  4.   switch(n)
  5.   case 1
  6.     do s :: "n = 1"
  7.   case 3
  8.     do s :: "n = 3"
  9.   default
  10.     do s :: "n <> 1 & n <> 3"
  11.   end switch
  12. end func
図2-4: switchブロック
4行目のように「switch()」と書くと、式の値と合致する最初のcaseを探して、その中身を実行してからswitchブロックを抜けます。
このプログラムではn=3なので、7行目の「case 3」に合致し、中身の8行目が実行されます。 どのcaseにも合致しない場合には「default」の中身が実行されます。
defaultは省略可能で、省略したときはどのcaseにも合致しない場合には何もせずにswitchブロックを抜けます。
caseには、カンマ区切りで複数の値を指定したり、「to」を使って範囲を示すこともできます(図2-5)。
  1. func main()
  2.   var n: int :: 3
  3.   var s: []char
  4.   switch(n)
  5.   case 1, 2
  6.     do s :: "n = 1 | n = 2"
  7.   case 3 to 6
  8.     do s :: "3 <= n & n <= 6"
  9.   case 10, 13 to 15
  10.     do s :: "n = 10 | 13 <= n & n <= 15"
  11.   end switch
  12. end func
図2-5: case節
switchブロックに名前を付けると、switchブロックに渡された値を得ることができます(図2-6)。
  1. func main()
  2.   switch x(1 + 2)
  3.   default
  4.     var n: int :: x {3}
  5.   end switch
  6. end func
図2-6: switchブロックのブロック名

3繰り返し処理を行う

繰り返し処理を行うには、「while」ブロックや「for」ブロックを使います。

3.1条件によって繰り返す



条件式が真である限り処理を繰り返すには「while」ブロックを使います(図3-1)。
  1. func main()
  2.   var n: int :: 4
  3.   while(n <> 1)
  4.     do n :/ 2
  5.   end while
  6. end func
図3-1: whileブロック
whileブロックは「while(条件式)」と書くと、条件式が真の場合には「end while」までの中身を実行して再度「while(条件式)」の行までジャンプして戻ります。 条件式が偽の場合には「end while」の次の行へジャンプします。
最初に3行目に来たとき、nは4なので条件を満たすため4行目の処理(nの値を半分にする)を行います。 5行目にさしかかると3行目へジャンプし、再度3行目で条件の判定を行います。
2回目に3行目に来たとき、nは2なので条件を満たして4行目の処理を行い、5行目でまた3行目へジャンプします。
3回目に3行目に来たとき、nは1なので「n<>1」の条件を満たさないため、whileブロックを抜けて6行目へジャンプします。
また、最初の1回目は無条件にwhileブロックの中を実行させたい場合には、条件式の後に「, skip」と書きます(図3-2)。
  1. func main()
  2.   var n: int :: 0
  3.   while(n = 1, skip)
  4.     do n :+ 1
  5.   end while
  6. end func
図3-2: whileブロックの条件のskip
通常なら最初に3行目に来たとき、nは0で条件を満たさないため即座にwhileブロックを抜けて6行目へジャンプするはずですが、「, skip」があるため、無条件に4行目の処理を行ってから5行目で3行目へジャンプし、2回目以降で3行目に来たときに条件判断を行います。

3.2指定回数だけ繰り返す



指定した回数だけ処理を繰り返すには「for」ブロックを使います(図3-3)。
  1. func main()
  2.   var n: int :: 0
  3.   for i(1, 5)
  4.     do n :+ i
  5.   end for
  6. end func
図3-3: forブロック
forブロックは「for(初期値, 終値)」と書くと、初期値から終値まで1ずつ増やしながら数えて「end for」までの処理を繰り返します。
forブロックに名前を付けると、数えている最中の値が取得できます。 このプログラムでは4行目の「i」で数えている最中の値を取得していて、変数nは最終的に「1+2+3+4+5」つまり「15」の値になります。
1ずつ減らしながら数えるには、forブロックの括弧の最後に「, -1」と書きます(図3-4)。
  1. func main()
  2.   var n: int :: 0
  3.   for i(5, 1, -1)
  4.     do n :+ i
  5.   end for
  6. end func
図3-4: forブロックの増減値
このように「, 増減値」と書くことで、数えるときの増減値が指定できます。 例えば「, 3」と書くと3ずつ増やしながら数えます。
増減値が正なら、数えている値が終値より大きくなるとforブロックを抜け、増減値が負なら、終値より小さくなるとforブロックを抜けます。 数えている値が実際に増減するタイミングは「end for」の行です。

3.3繰り返し処理を1回飛ばす



whileブロックやforブロックの繰り返し処理を1回飛ばすには「skip ブロック名」と書きます(図3-5)。
  1. func main()
  2.   var n: int :: 0
  3.   for i(1, 5)
  4.     if(i = 2)
  5.       skip i
  6.     end if
  7.     do n :+ i
  8.   end for
  9. end func
図3-5: skip文
skip文は、「end ブロックの種類」の直前にジャンプする命令です。 このプログラムでは、iが2のときにforブロックの中のそれ以降の処理を飛ばして「end for」の直前にジャンプするため、最終的なnは「1+3+4+5」つまり「13」の値になります。

4例外を扱う

(この記事は執筆中です!)
1544535504jaf