文字

文字 の Julia

4個の演習

文字について

これは_大きな_テーマです! これだけで長い本を1冊書くこともでき、実際に何人もの人が書いています(Amazonで「unicode book」を検索すると、いくつか例が見つかります)。

ごく簡単な歴史

数十年前、コンピューターで文字を扱うのはもっとずっと簡単でした。当時のプログラマーは、英語だけが重要な言語だと考えていたからです。 大文字と小文字を合わせた26文字、10個の数字、いくつかの句読点、それにベルを鳴らすためのコード(0x07)まで、すべてが7ビットに収まりました。それがASCII文字セットです。

当然のことながら、àやä、Łはどうするのかという声が上がり、次にはऄやஹ、ญはどうかという声が上がり、そして若い人たちは絵文字😱を求めるようになりました。 どうすればいいのでしょうか?

手短に言えば、多くの賢く辛抱強い人たちが何年も委員会に参加して、Unicode文字セットやUTF-8のようなエンコーディングの細部を詰めていきました。そして、たくさんのソフトウェアに_とてつもなく_複雑な書き直しが必要になりました。 さらに、たくさんの新しいバグも生まれました。

_すべて_が壊れるのを防ぐため、Unicode/UTF-8の設計では、最初の127個のコードがASCIIとまったく同じになるようにしています(ベルのコードまで)。

Juliaの文字

2005年以降に設計された言語には、それなりに安定したUnicode標準がすでに存在していたという大きな利点があります。

Julia(2012年に最初のリリース)は、文字も文字列も変数名や関数名も、数学演算子まで、すべてがUnicodeであることを前提にできました。

マニュアルを引用すると、「Juliaは、通常のASCIIテキストの扱いを簡単かつ効率的にし、Unicodeの扱いも可能な限り簡単かつ効率的にします」となります。この「可能な限り」という部分が重要です。

文字リテラルはシングルクォートで書きます。ダブルクォートで書く文字列とは別のものです。

これはC/C++の世界の人には当たり前に思えますが、PythonやJavaScriptのプログラマーには戸惑うところかもしれません。

julia> a = 'a'  # Roman alphabet
'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)

julia> typeof(a)
Char

julia> jha = 'झ'  # Devanagari alphabet
'झ': Unicode U+091D (category Lo: Letter, other)

julia> typeof(jha)
Char


julia> '❤'  # heart emoji
'❤': Unicode U+2764 (category So: Symbol, other)

例から、型がCharであることがわかります。また、Juliaは文字のカテゴリについてもっと詳しい情報を持っています。

よく見ると、これらの文字は4桁の16進数で表せるようです。 文字セット全体では、最大6桁の16進数が必要になります。

このような数を「コードポイント」と呼び、現在はU+0000からU+10FFFFまでの範囲にあります。 REPLではそのまま表示されますが、コードの中ではcodepoints()を使うと取得できます。

CharとIntの間の変換は簡単です。

julia> Int('a')
97

julia> Char(97)
'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)

コンパイラーは、Charに対する整数演算の_一部_の形を認めています。

julia> 'b' - 'a'  # interval, in alphabetic order
1

julia> 'b' + 'a'
ERROR: MethodError: no method matching +(::Char, ::Char)

julia> 'a' + 5
'f': ASCII/Unicode U+0066 (category Ll: Letter, lowercase)

julia> 'f' + ('A' - 'a')  # same as `uppercase('f')`
'F': ASCII/Unicode U+0046 (category Lu: Letter, uppercase)

文字のための関数

文字列を扱う関数の一部は、Charの入力に対しても使えます。

  • 対応しているアルファベットなら、uppercase()とlowercase()で大文字・小文字を変換できます。
  • 大文字か小文字かは、isuppercase()とislowercase()で調べられます。
  • 文字の種類は、次の関数で調べられます。
    • isletter()、多くのアルファベットに対応
    • isdigit()、厳密に0〜9かどうかを調べます
    • isnumeric()、isdigitより広く、¾やヨーロッパ以外のさまざまな文字体系でもtrueを返します
    • isxdigit()、16進数の数字
    • isascii()、Unicode以前の文字
    • ispunct()、句読点
    • isspace()、任意の空白文字
    • isprint()、表示可能な文字(逆はiscntrl())
islowercase('A')  # false
uppercase('γ')  # 'Γ': Unicode U+0393 (category Lu: Letter, uppercase)
ispunct('@')  # true
isdigit('A')  # false
isxdigit('A')  # true

ある文字が文字列の中に含まれているかどうかを調べるには、inがあります。 これは部分文字列の場合とは違うことに注意してください。

# char search
julia> 'a' ∈ "xabcahliazlnkiw"
true

# substring search
julia> "a" ∈ "xabcahliazlnkiw"
use occursin(needle, haystack) for string containment

また、正規表現(別の概念で扱うテーマです)を使えば、強力な検索や操作ができます。

CharのベクターとStringの相互変換

StringからCharのベクターへは、collect()を使います。

CharのベクターからStringへは、String()コンストラクターがあります。

julia> s = "abcde"
"abcde"

julia> cv = collect(s)
5-element Vector{Char}:
 'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)
 'b': ASCII/Unicode U+0062 (category Ll: Letter, lowercase)
 'c': ASCII/Unicode U+0063 (category Ll: Letter, lowercase)
 'd': ASCII/Unicode U+0064 (category Ll: Letter, lowercase)
 'e': ASCII/Unicode U+0065 (category Ll: Letter, lowercase)

julia> String(cv)
"abcde"

これはASCIIだけでなく、どんな文字でも使えます。

julia> collect("❤,😱")
3-element Vector{Char}:
 '❤': Unicode U+2764 (category So: Symbol, other)
 ',': ASCII/Unicode U+002C (category Po: Punctuation, other)
 '😱': Unicode U+1F631 (category So: Symbol, other)

String()コンストラクターはベクターに対して働くことに注意してください。 1つのCharを1文字の文字列に_キャスト_するには、小文字のsを使ったstring()という関数を使います。

julia> string('a')
"a"

格納

ここまでに説明したことはどれも比較的シンプルに見えるので、本当に心配することはほとんどないのでしょうか?

残念ながら、それは楽観的すぎます!

複雑な点の1つは、コードポイントごとに「最大」6桁の16進数が必要になることから来ています。 つまり、UTF-8でエンコードすると、文字によってメモリー上で必要な領域の大きさが変わるということです。

1バイトで格納できるのは(符号なしで)255まで、つまり16進数2桁分だけなので、UTF-8では1つのCharを格納するのに可変のバイト数(1〜4)を使います。 これを「コード単位」と呼び、ncodeunits()関数を使うと、ある文字に必要な数が返ります。

julia> codepoint(jha)  # jha 'झ' is defined in an earlier example
0x0000091d

julia> ncodeunits(jha)
3

julia> ncodeunits('a')  # ASCII character
1

julia> ncodeunits('😱')  # emoji
4

また、画面に表示できるものすべてが、それぞれ固有のコードポイントを持っているわけではありません。 見た目が異なる文字の中には、別の文字から派生したものとみなされるものがあり、Unicodeでは親の文字と修飾子の組み合わせとして扱われます。

GitHubで編集 リンクは新しいウィンドウまたはタブで開きます

文字を学習する

練習はロックされています

文字を練習するには、あと3個の演習のロックを解除してください