Zenにおける文字列の扱いについて解説します。
まず、Zenには文字列専用の型は存在しません。全てのテキストはUTF-8でエンコードされたバイト列として処理されます。
実行時に動的に文字数が変化する文字列を作るには、標準ライブラリの
ArrayListまたはBufferを使います。
文字列は""で囲う単一行の文字列リテラルと、\\から始まる複数行の文字列リテラルで記述します。
文字列リテラルはu8の配列です。""で囲んだ中身が単一行の文字列リテラルになります。また、その配列はC言語と同様NULL文字 (\0) で終端しています。
単一行の文字列リテラル内では改行できません。
examples/ch02-primitives/src/strings.zen:4:16
test "string literals" {
    const hello = "hello";
    ok(@TypeOf(hello) == *[5:0]u8);
    ok(hello[0] == 'h');
    ok(hello.len == 5);
    // ひらがなは1文字3バイト
    const japanese = "こんにちは";
    ok(@TypeOf(japanese) == *[15:0]u8);
    // 「こ」は`{ 0xe3, 0x81, 0x93 }`
    ok(japanese[0] == 0xe3);
    ok(japanese.len == 15);
}
上の例では、変数 hello の型は *[5:0]u8 です。配列のポインタ型に似ていますが :0 がついていることで "hello" がNULL文字で終端していることを示しています。
文字列リテラルはNULL文字で終端していますが、要素数にNULL文字の分は含みません。上の例では変数 hello の要素数はNULL文字を含まない 5 となります。
終端文字自体にはアクセスすることはできません。
以下のコードはコンパイルエラーになります。
examples/ch02-primitives/src/strings.zen:18:20
test "termination character access" {
    const hello = "hello";
    ok(hello[5] == 0);
}
error[E04028]: index is out of bounds
    ok(hello[5] == 0);
いくつかの文字はバックスラッシュ (\) によるエスケープが必要です。
| 文字 | エスケープシーケンス | 
|---|---|
| シングルクォート ( ') | \' | 
| ダブルクォート ( ") | \" | 
| 改行 | \n | 
| キャリッジリターン | \r | 
| タブ | \t | 
| バックスラッシュ ( \) | \\ | 
| 16進数文字コード | \xHH | 
| 16進数Unicode | \u{HHHHHH} | 
例えば、次のようなエスケープシーケンスにより、文字列リテラル内にUnicodeの文字を埋め込むことができます。
examples/ch02-primitives/src/strings.zen:24:28
test "escape sequence" {
    const japanese = "こんにちは";
    const unicode = "こ\u{3093}にちは";
    equalSlices(u8, japanese, unicode);
}
\\ で複数行の文字列リテラルを記述できます。
改行は文字列リテラルに\nで格納されます。ただし、最終行の改行は含まれません。
test "string multi-line literals" {
    const hello = 
        \\Hello
        \\World
    ;
    equalSlices(u8, hello, "Hello\nWorld");
}
複数行の文字列リテラルでは、エスケープシーケンスを記述することはできません。
test "no-escape sequence" {
    const text_not_newline =
        \\\n
    ;
    ok(text_not_newline[0] != '\n');
    const text_not_n =
        \\\u{3093}
    ;
    ok(text_not_n.len > 3);
    for("\u{3093}") | chara, idx | {
        ok(text_not_n[idx] != chara);
    }
}
配列リテラルと同様に、コンパイル時計算可能な文字列リテラルは、++演算子によって連結することができます。
examples/ch02-primitives/src/strings.zen:30:35
test "concatenates string literals" {
    const hello = "hello";
    const world = "world";
    const message = hello ++ " " ++ world ++ "\n";
    equalSlices(u8, message, "hello world\n");
}
また、コンパイル時計算可能な文字列リテラルは、**演算子によって複数回繰り返した文字列を作ることができます。
examples/ch02-primitives/src/strings.zen:37:41
test "multiplies string literals" {
    const hyphen = "-";
    const line = hyphen ** 10;
    equalSlices(u8, line, "----------");
}
文字列はu8の配列なので、スライスとして使用することもできます。
examples/ch02-primitives/src/strings.zen:43:48
test "string slice" {
    const hello = "hello world";
    const world = hello[6..];
    equalSlices(u8, world, "world");
}
      ☰ 人の生きた証は永遠に残るよう ☰
      Copyright © 2018-2020 connectFree Corporation. All rights reserved. | 特定商取引法に基づく表示
      Zen, the Zen three-circles logo and The Zen Programming Language are trademarks of connectFree corporation in Japan and other countries.