SML# - Library/LMLML Diff

  • Added parts are displayed like this.
  • Deleted parts are displayed like this.

'LMLML'は、Library of MultiLingualization for ML すなわちMLでの多言語処理の支援を目的とするライブラリである。現在は多バイト文字処理機能のみを提供している。

既存のML処理系やML Basisライブラリの文字列処理関連モジュールは、1文字を1バイトで表現する符号化方式のみを事実上前提としており、1文字を複数バイトで表現する方式で符号化されたいわゆる多バイト文字列を処理対象として想定していない。
このため、たとえば、多種多様な符号化方式でクライアントとの間の通信内容が符号化されるWebアプリケーションをSML言語で開発することは困難である。
SML#プロジェクトでは、このような多バイト文字列を扱うプログラムの開発を支援する多バイト文字列処理ライブラリLMLMLを開発した。

!特徴

!!Standard ML Basisとの高い互換性
LMLMLは、BasisのStringモジュールやCharモジュールに対してほぼ上位互換であるインタフェイスを提供している。これにより、既存のMLプログラムをわずかな変更のみで多バイト文字対応させることができる。

!!符号化方式依存部分の局所化
LMLMLは文字列の符号化方式を文字列単位で動的に選択することができる。
また、異なる符号化方式で符号化された文字列を同じ型の値として扱うことができる。
したがって、LMLMLを利用すれば、実行時に決定される異種の符号化方式を同時に扱う必要のあるプログラムにおいても、プログラム中で特定の符号化方式に依存する処理部分を局所的にとどめることができる。

!!ユーザによる拡張
LMLMLは、ShiftJISやUTF-16など主要な符号化方式にはあらかじめ対応している。
LMLMLが対応していない符号化方式を扱う必要がある場合、ユーザがモジュールを作成して追加することにより、LMLML本体を変更することなく、新たな符号化方式に対応することが可能である。

!!Standard ML準拠
LMLMLの主要機能はStandard ML言語とBasisのみを利用して実装されている。
LMLMLは、SML#コンパイラだけではなく、SML/NJやMLtonなど他のSML処理系で利用可能である。

!リソース
[[API ドキュメント|smlsharp:lib/LMLML/doc/api/]]

!プログラム例

LMLMLを使用したプログラム例として、文字列"白血病abc剣道"中の文字'剣'を検索する。

"白血病abc剣道"をShift_JISで符号化すると、バイト列
0wx94, 0wx92, 0wx8C, 0wx8C, 0wx95, 0wx61, (* 白血病 *)
0wx61, 0wx62, 0wx63, (* abc *)
0wx8C, 0wx95, 0wx93, 0wxB9 (* 剣道 *)
が得られる。
'血'の二バイト目と'病'の一バイト目が 0wx8C, 0wx95 であり'剣'と同じである。
このため、このバイト列で'剣'(0wx8C, 0wx95)を検索すると、"白血病"の二文字目と三文字目にまたがる部分が該当してしまう。

LMLMLを用いると、以下のように正しい検索結果が得られる。

まず、バイト列をShift_JISで復号化する。

(* "白血病abc剣道" *)
val bytes =
     Word8Vector.fromList
     [
       0wx94, 0wx92, 0wx8C, 0wx8C, 0wx95, 0wx61, (* 白血病 *)
       0wx61, 0wx62, 0wx63, (* abc *)
       0wx8C, 0wx95, 0wx93, 0wxB9 (* 剣道 *)
     ];
val string = MultiByteString.String.decodeBytes "Shift_JIS" bytes;

(* "剣" *)
val KenBytes = Word8Vector.fromList [0wx8C, 0wx95]; (* 剣 *)
val KenString = MultiByteString.String.decodeBytes "Shift_JIS" KenBytes;

そして、"白血病abc剣道"中に"剣"を探す。

val (leftSS, rightSS) =
     MBSubstring.position KenString (MBSubstring.full substring);

こうして得られるleftSSは"白血病abc"の六文字であり、七文字目の"剣"が正しくマッチしたことが分かる。

# MBSubstring.size leftSS;
val it = 6 : int

この例で符号化方式はShift_JISに固定されているので、以下のように書くこともできる。

val ShiftJISString = ShiftJISCodec.String.fromBytes bytes;
val ShiftJISKenString = ShiftJISCodec.String.fromBytes KenBytes;
structure ShiftJISSubstring =
           SubstringBase
               (struct
                  open ShiftJISCodec.String
                  val compareChar = ShiftJISCodec.Char.compare
                end);
val (leftSS, rightSS) =
     ShiftJISSubstring.position
         ShiftJISKenString (ShiftJISSubstring.full ShiftJISString);
val len = ShiftJISSubstring.size leftSS;