2018年3月16日金曜日

オレオレ言語、Expressoについて・・・intseq編


こんにちは、はざまです。今回も懲りもせずにExpressoについての記事です。

特定の型に関する記事は特に書くつもりなかったのですが、面白い事実に気付いてしまったので、記事にすることと相成りました。
さて、Expressoのintseq型ですが、これは組み込みの型で、Pythonのxrangeや、RustのRange型を思い浮かべていただくと理解が早いかと思います。まあ、有り体に言えば、整数列を生成するgeneratorなので、そこらへんの基本機能は、他の言語と一緒です。Kotlinのrangeはちょっと強くて演算子で包含確認ができるみたいですが、ExpressoはIncludesというメソッド経由です。Expressoでもinはキーワードではあるものの、for文の右辺にしか使えません。
module main;


def main()
{
    for let i in 0..10 {    // start..end:stepは3項演算子。stepを省略すると1になる
        println(i);
    }

    for let j in 9...0:-1 { //stepを負にすれば、マイナス方向にも行ける。なお、整合性はチェックしてません(2018/4/5 追記: リテラルで指定している場合のみ、整合性をチェックするようになりました。0...9:-1と書くと警告が出ます。変数などを使ってるとチェックされません)
        println(j);
    }

    for let k in 0..10:3 {  //もちろん、stepは1以上でもいい
        println(k);
    }
    let a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ...]; //将来的には(0..10).select(|x| x);などと書けるようにしたいところ(2018/4/5追記: [0..10, ...];と書けるようになりました)
    let a2 = a[2...4];
    println(a2);
}

上記のコードで、想定通り[2, 3, 4]が出力されます(まあ、Slice型のToString()の結果なので、[List<int>, 2...4:1]みたいな感じですが)。a2の型はこちらも組み込みのslice型になります。Slice型自体は、Rustにもあるものの、このような書き方ができる言語がないので(修正: Rustでもできましたね、この書き方)、特筆すべきところはそこになります。
Kotlinだと、floatに対してもrangeが定義されてるみたいですが(floatの数列って意味をなさない気がするから気のせいなのかな)、Expressoの場合は、intだけです。その範囲外は多分死にます(型しか見てないので、範囲外が来ても明示的なエラーにできず、intへの型変換で落ちるはず)(2018/4/5追記: これは誤りでした。実際にはintの範囲外はdoubleと解釈され、intseqはdoubleを受け付けないと怒られます)。
ちなみにrange operatorは、Expressoに2種類ある3項演算子の1つです。もう一つは、有名な条件演算子( ? : )です。
2018/4/5追記: aの宣言のコメントにあるように、intseqでシーケンスを初期化できるようになりました。意外にも、RustやKotlin、Swiftなどではこの表記は採用されていないので、私の観測範囲ではExpresso固有の機能になります。なお、[0..10];と書けば、arrayにもできます。もちろん、stepを指定して、[0..10:2];などと書くこともできます。機能限定のリスト内包表記みたいな感じですね。

0 件のコメント:

コメントを投稿

なにか意見や感想、質問などがあれば、ご自由にお書きください。