競プロでプロデル入門

# まえがき
プロデル Advent Calendar 2019 16日目 の記事です．

プロデルはWindowsデスクトップアプリを作ることに適した，GUIベースのリッチな開発環境が提供されていますが，コンソールアプリケーションの開発も可能です．
競プロをはじめとしたテキストベースのデータ処理に必要となるであろう処理を昨日の[精選10問を解いてみた記事](https://qiita.com/Mopepe51/items/fe35a9e02f1b07666448)の経験を元にまとめていきたいと思います．

2019/12/18 更新：ブロック式・**種類**のアクセス修飾子について追記．[公式マニュアル](https://rdr.utopiat.net/docs/onepage/syntax.html)に従い表記を変更[^hyouki]．
2019/12/29 更新：複文について追記．

[^hyouki]: 説明用記号を〈〉から《》に変更

# プログラムの実行
実行環境は[公式サイト](https://rdr.utopiat.net/)からインストーラーが配布されているため簡単にセットアップできます．

「プロデル デザイナ」によりコーディング，保存したのち，

```
$ pconsole source.rdr
```

でインタプリタ実行できます．

また，プロデルデザイナから ファイル＞実行可能アプリを作成＞"ファイルの種類"を「コンパイル済みコンソールアプリ」指定 して保存することで実行ファイル形式のMSIL中間コードへコンパイルすることが可能で，[「通常のインタプリタ版の実行可能ファイルに比べて繰り返し処理や配列の処理の速度が高速になります。」](https://rdr.utopiat.net/docs/onepage/devenv.html#makeexe)とのこと．
しかし，[前記事](https://qiita.com/Mopepe51/items/fe35a9e02f1b07666448)で実行してみたところ実行時エラーが発生してテストできませんでした．
これについては今後解決を試みたいと思います．

# 基本事項
以下，プロデルのテクニカルタームは**ほげ**のように太字で表すことがあります．
また挿入コード中の`《ほげ》`はメタ言語的な説明に用い，それ以外の記号は基本的にプロデル中の記号です．

基本的には命令型のオブジェクト指向言語です．
命令文は動詞と目的語(引数)により構成されます．
Hello, worldは

```
「こんにちは，世界！」をコンソールに表示する
```

のように書きます[^2]が，動詞が`表示する`で，助詞`に`に繋がる`コンソール`と，`を`に繋がる`「こんにちは，世界！」`が引数になります．
引数の順序は可換で，

```
コンソールに「こんにちは，世界！」を表示する
```

とも書けます．
なお，動詞につく送り仮名・助動詞は無視されるため

```
「こんにちは，世界！」をコンソールに表示
「こんにちは，世界！」をコンソールに表示せよ
「こんにちは，世界！」をコンソールに表示してください
「こんにちは，世界！」をコンソールに表示しない
```

はいずれも同じ命令となります．(否定文は解釈されないことに注意)

[^2]: このままでは改行はされないため，改行が必要な場合は`表示して改行する`などのようにします．

## 変数の宣言・代入

変数への代入は

```
《変数名》は、《代入する値》
《変数名》を《代入する値》とする
《変数名》＝《代入する値》
《変数名》へ《代入する値》を代入する
```

のように書きます(４つとも等価)．
宣言されていない変数へ代入すると自動で型推論され宣言されますが，スコープを明示したいとき，型注釈をつけたいときは`【《変数名》：《型名》】`のように書くことができます(型注釈は省略可)．

# 出入力
## 入力
標準入力は`コンソールから受け取る`によって１行，文字列として取得できます．
[※ABSの解法を参照](https://qiita.com/Mopepe51/items/fe35a9e02f1b07666448#0-practicea---welcome-to-atcoder)

```
コンソールから受け取ってＸとする
Ｘは，コンソールから受け取ったもの
```

## 空白による分割
競プロでは１行に空白で分割されて複数の入力が与えられることがありますが，文字列の空白分割は`《文字列》を《区切り文字》で区切る`でできます．
`A_1 A_2 ... A_N`を配列として受け取る処理は

```
Ａは，コンソールから受け取ったものを「 」で区切ったもの
```

のようになります．

## 出力
前述のように，標準出力は`《文字列》をコンソールへ表示する`と書きます．
なお，`コンソールへ`はオプション引数ですが，デフォルトではダイアログボックスへの表示となり，コンソールでは

```
----- 《ファイル名》 -----
《文字列》
```
のように表示されます．

## 埋め込み文字列
文字列に式を埋め込むことができます．
文字列は`「ほげ」`のように`「」`で囲んだものですが，この中に`［］`で囲った式を埋め込むと式を評価した文字式が埋め込まれます．

```
ほげは，「世界」
「こんにちは，［ほげ］！」をコンソールに表示して改行
// => こんにちは，世界！
```

# 数値演算
数値の型には以下のものがあります．

+ 固定小数
+ 長整数
+ 整数
+ 浮動小数
+ 倍浮動小数

また，これらをまとめて**数値**とも呼べ，型注釈で`【ほげ：数値】`とするとこれらの中から型推論してくれます．（もちろん`【ほげ：整数】`のように直接指定もできます．）

数値の演算は以下の演算子を使った数式の形で書けます．

|記号|意味|
|:--:|:--|
|＋	|足し算|
|－	|引き算|
|＊，×	|かけ算|
|／，÷	|わり算|
|＾	|累乗|
|￥	|整数除算（商を整数値に切り捨て）|
|％	|剰余|

また，動詞を使っても表せます．

ex.
`（４＋５×３）％２`
`(４と(５と３を掛ける)を足す)を２で剰余演算する`
※`剰余演算する`はIEEE754準拠の剰余演算で，前者と結果が異なる場合があります．


その他，数値計算**手順**は[公式レファレンスを参照](https://rdr.utopiat.net/docs/reference/core/math.htm)

## 比較演算
値の比較は`《値》《比較演算子》《値》`または`《値》は、《値》《比較述語》`と表されます．
比較演算子には以下のようなものがあります．
`＝`．`＜`，`≦`，`＜＝`，`＞`，`≧`，`＞＝`，`≠`，`！＝`，`＜＞`
比較述語には否定の`でない`が使えます．

例.
`２≦１１でない`
`３は－４より大きい`

# 条件分岐
## 判断文
if文に相当する構文です．

```
もし《条件１》なら
　　《条件１が正しいときに実行する処理》
他でもし《条件２》なら
　　《条件２が正しいときに実行する処理》
そうでなければ
　　《条件が違うときに実行する処理》
もし終わり
```

## 真偽値演算
真偽値のリテラルは`○`・`×`と表されます．
真理値演算は`かつ`，`または`で論理積，論理和演算ができます．
例. `もし（ほげ＜０または１００＜ほげ）かつふが≠０ならばぴよする`

## 分岐文
switch文などに相当する構文です．C言語等のように条件ごとにbreakする必要はありません．

```
《変数》について分岐
《分岐させる値》の場合
︙
分岐終わり
```

``` :おみくじプログラム
数値は、0から5までの乱数
数値について分岐
0の場合
　　　「大吉」を表示する
１の場合
　　　「凶」を表示する
2の場合
　　　「小吉」を表示する
他の場合
　　　「中吉」を表示する
分岐終わり
```
※ https://rdr.utopiat.net/docs/manual/basis/switch.htm より

# 繰り返し
繰り返しの構文は用途に応じて複数用意されています

## 指定回数の繰り返し
```
《繰り返す回数》回、繰り返す
  《繰り返す処理》
繰り返し終わり
```

一行で
`《繰り返す回数》回、《繰り返す処理》を繰り返す`
と書くこともできます．

## インデックス付きの指定回数繰り返し
```
《繰り返す回数》回、《変数名》にカウントしながら繰り返す
    《繰り返す処理（《変数名》を用いる）》
繰り返し終わり
```

indexは１から始まるので注意が必要です．

## 変数が指定した値になるまで繰り返す
一般的なC言語風のfor(…, …, …)文の構文はこうなります

```
《変数名》を《初期値》から《増減数》ずつ増やしながら《最終値》まで 繰り返す
    《繰り返す処理》
繰り返し終わり
```

## 条件に応じて繰り返す
while文はこちら

```
《条件式》の間、繰り返す
    《繰り返す処理》
繰り返し終わり
```

条件がfalseの間繰り返す事もできます

```
《条件式》になるまで繰り返す
    《繰り返す処理》
繰り返し終わり
```

## 無制限に繰り返す
無限ループはこちら

```
繰り返す
    《繰り返す処理》
繰り返し終わり
```

~~神奈川県警に捕まらないよう~~条件に応じてループから抜けましょう．
break文は`繰り返しから抜ける`となります．

## 配列の内容に応じて繰り返す
配列を舐める形のループ(foreach文)を書くこともできます

```
《配列》を《変数名》へそれぞれ繰り返す
    《繰り返す処理》
繰り返し終わり
```

**範囲**（range等に相当）が`《開始値》～《終了値》`と書けるので，これを用いてカウンタ付きの繰り返しを

```
（《開始値》～《終了値》）を《変数名》へそれぞれ繰り返す
    《繰り返す処理》
繰り返し終わり
```

と書くこともできます．インデックスが１スタートでないときなどに便利です．

# 配列
既に何度か登場していますが，プロデルでも値のコレクションである配列が扱えます．
配列を明示的に宣言するには
`【《変数名》：《内容物の型》の配列】`
と書きます．（デフォルトでは可変長配列です．固定長配列を扱うこともできます）
また，初期化は
`《変数》は、｛《１番目の値》、《２番目の値》、…｝`
と書けます．

要素へのアクセスは
`変数（《インデックス》）`
のように`（）`で何番目かを指定します．1-indexedなので気をつけましょう．

さらに，`{}`で囲われ，`,`で区切られた文字列は`配列化`**手順**で配列にすることができます．
`「{１,３,２}」を配列化する`=>`{１,３,２}`
カンマ区切りの入力ではこの方法で配列として受け取ることができますね．

# 辞書
連想配列，dictionary，map，hashなどと呼ばれるコレクションです．
初期化は
`《変数》は、｛《見出し１》＝《値１》、《見出し２》＝《値２》、…｝`
と書けます．**見出し**には文字列のみ使うことができます．

要素へのアクセスは
`変数（《見出し》）`
と**見出し**を指定します．インデックスが文字列であること以外は配列と同様です．

さらに，初期化の形の文字列は`辞書化`**手順**で辞書にすることができます．
`「{ほげ＝１,ふが＝３,ぴよ＝２}」を辞書化する`=>`{ほげ＝１,ふが＝３,ぴよ＝２}`
カンマ区切りの入力ではこの方法で配列として受け取ることができますね．

# 手順 の定義
これまでは組み込みの**手順**を使ってきましたが，自分で**手順**を定義することも可能です．

```
《手順名》手順
    《処理内容》
終わり
```

例：

```
挨拶する手順
    「こんにちは、世界！」をコンソールに表示する
終わり

挨拶する //＝＞こんにちは、世界！
```

引数のある**手順**は助詞を指定します

```
［《変数名》］《助詞》……、《手順名》手順
    《処理内容》
終わり
```

例：

```
［対象］に、挨拶する手順
    「こんにちは、［対象］！」をコンソールに表示する
終わり

「地球」に挨拶する //＝＞こんにちは、地球！
```
※注：例の１行目の`［］`は引数を表し，２行目は埋め込み文字列のエスケープとなっています．

## ブロック式
`『』`で囲い，ブロック式として扱うことが可能です．
このブロック式は無名手順オブジェクトとして扱われ，変数に代入したり手順の引数とすることが可能です．

```
//ブロック式の代入
甲＝『「こんにちは」をコンソールに表示』
甲を実行
//=> こんにちは

甲をコンソールに表示 
//=> 匿名手順 (オブジェクト@《オブジェクトのアドレス》)

３回，甲を繰り返す
//=> こんにちは
//   こんにちは
//   こんにちは

３回，乙にカウントしながら『乙をコンソールに表示』を繰り返す
//=> １
//   ２
//   ３

```

ブロック式を上に挙げた`繰り返す`文の補語とすることで簡潔に繰り返しを書くことができますね．

# 種類
プロデルはクラスベースオブジェクト指向なのでクラスを定義することができます．
プロデルのクラスは**種類**と呼ばれます．


```
《種類名》とは
    《種類内の変数や手順》

    《変数名》を持つ
    《変数名》：《種類名》＝《値》

    ［自分］を、《手順名》手順
        《手順の内容》
    終わり
終わり
```

**種類**中での変数の宣言は`持つ`とします．
**手順**の定義は`自分`への参照を持ちます．

また変数，手順にアクセス修飾子をつけることができます．宣言の冒頭に以下の記号を付加します．

|識別子	|意味|
|:--:|:--:|
|`+`,(なし)	|公開(Public)|
|-	|非公開(Private)|
|#	|限定(Protected)|

※参照：https://rdr.utopiat.net/docs/onepage2019/syntax/construct.html#construct_modifier




その他，コンストラクタ・getter/setterの宣言，**種類**の継承などができます．
詳しくは[公式マニュアル](https://rdr.utopiat.net/docs/manual/practice/class.htm)を参照．

# 複文（≒メソッドチェーン）
プロデルでは，特殊変数`それ`の機能を利用してメソッドチェーンのように動詞を書き連ねることができます．

特殊変数`それ`は最後に実行された**手順**の戻り値を格納しています．
例えば

```
１と２を足す
それと３を掛ける //１＋２＝３が格納されている
それを表示する  //３×３＝９が格納されている
//=> ９
```

のようになります．

さらに，特殊変数`それ`の応用機能として**補語**の省略機能があります．
`それ`に値が格納されている状態では次の**手順**で一つ**補語**（引数）を省略することができ，自動で引数に`それ`が補完されます．
上の例は

```
１と２を足す
３を掛ける //「～と」が省略されている
表示する  //「～を」が省略されている
//=> ９
```

と記述できます．

さらにさらに，動詞を連用形にすることで複数の**手順**を連ねて書くことができます．

```
１と２を足して３を掛けて表示する
//=> ９
```

引数・戻り値が一つずつの**手順**を連ねて書けばメソッドチェーンのような記法が可能となります．

なお，戻り値を複数与えるときは，意味が一通りに定まるよう**補語**の順序に制限があります．（動詞が現れる時点でそれまでに出現したすべての補語を消費していること）
詳しくは [プロデルで日本語らしくプログラミング「プログラム文」―プロデルブログ](https://wp.utopiat.net/2018/02/466/#i-7) を参照．


# あとがき
まだ十分使いこなせていないため不足等あるかと思いますが，今後もアップデートしていきたいと思います．