Open chaemon opened 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のコンストラクタのルールとしては以下が考えられるのですが、どれがよろしいですかね!?
distinctを用いる 利点: ModIntMが自動で定義され、そのまま呼べる 欠点: 利点で定義したものから変更できない。特にnが0..<Mに含まれないときは要注意
distinctを用いない 利点: Mごとに個別に定義すればconverterが定義できる 欠点: バグなのかわからないが、ModIntMが呼べない。type mint=ModInt[M]としてmintに対するコンバータを定義すれば大丈夫。
コンストラクタにconverterを用いない ModInt[M].init(n)でintからModInt[M]に変換できるようにする。 利点: 新たな関数を定義するためconverterの不具合とは無縁である 欠点: ジェネリックプログラミングをする際、int型やfloat型でもint.initやfloat.initを定義しないといけない
Twitterでも提起したconverterの問題です。例えばジェネリクスを使ってライブラリを使うときに、整数nをジェネリクスTに変換したい場面がよく出てきます。TはModInt以外にもfloatやint自身だったり行列だったりいろいろ考えられます。通常T(n)を呼ぶとこの変換ができるという風にするのが自然です。
このとき、modintをdistinctで定義すると、converterが勝手に定義され、ModIntMを呼んだとき、initModIntが呼ばれず、n>=Modだったりn<0だったりするときに、バグを発生させる危険があります。 実はdistinctを用いない場合でもconverterを定義しても下記のような不具合があります。 modintのコンストラクタのルールとしては以下が考えられるのですが、どれがよろしいですかね!?
distinctを用いる 利点: ModIntMが自動で定義され、そのまま呼べる 欠点: 利点で定義したものから変更できない。特にnが0..<Mに含まれないときは要注意
distinctを用いない 利点: Mごとに個別に定義すればconverterが定義できる 欠点: バグなのかわからないが、ModIntMが呼べない。type mint=ModInt[M]としてmintに対するコンバータを定義すれば大丈夫。
コンストラクタにconverterを用いない ModInt[M].init(n)でintからModInt[M]に変換できるようにする。 利点: 新たな関数を定義するためconverterの不具合とは無縁である 欠点: ジェネリックプログラミングをする際、int型やfloat型でもint.initやfloat.initを定義しないといけない