zer0-star / Nim-ACL

ACL (AtCoder Library) implementation in Nim
Creative Commons Zero v1.0 Universal
22 stars 3 forks source link

modintなどのコンストラクタ(converter)問題 #20

Open chaemon opened 4 years ago

chaemon commented 4 years ago

Twitterでも提起したconverterの問題です。例えばジェネリクスを使ってライブラリを使うときに、整数nをジェネリクスTに変換したい場面がよく出てきます。TはModInt以外にもfloatやint自身だったり行列だったりいろいろ考えられます。通常T(n)を呼ぶとこの変換ができるという風にするのが自然です。

このとき、modintをdistinctで定義すると、converterが勝手に定義され、ModIntMを呼んだとき、initModIntが呼ばれず、n>=Modだったりn<0だったりするときに、バグを発生させる危険があります。 実はdistinctを用いない場合でもconverterを定義しても下記のような不具合があります。 modintのコンストラクタのルールとしては以下が考えられるのですが、どれがよろしいですかね!?

  1. distinctを用いる 利点: ModIntMが自動で定義され、そのまま呼べる 欠点: 利点で定義したものから変更できない。特にnが0..<Mに含まれないときは要注意

  2. distinctを用いない 利点: Mごとに個別に定義すればconverterが定義できる 欠点: バグなのかわからないが、ModIntMが呼べない。type mint=ModInt[M]としてmintに対するコンバータを定義すれば大丈夫。

  3. コンストラクタにconverterを用いない ModInt[M].init(n)でintからModInt[M]に変換できるようにする。 利点: 新たな関数を定義するためconverterの不具合とは無縁である 欠点: ジェネリックプログラミングをする際、int型やfloat型でもint.initやfloat.initを定義しないといけない