コンテンツへスキップ
ものがたり
戻る

2005-04-14

何となくタイトルを変えてみました。最近あんましものものしくないのでw

cs2n

Nemerleでコードを考えると、breakやreturnでけっこう悩みます(苦笑)。関数型言語なので、再帰でどーにかするっていうのが正しいアプローチだとは思うのですが、それなりにC#に似ているだけに、どうしてもC#っぽいものを期待してしまうわけです。まあJavaのコードをC#に移植していても、break blahblah;がほしいなーとか思ってしまうわけですがw1

ところで最新のNemerleにはcs2nというコード変換ツールが付いてきます。これだとループ中のreturnに対して、どんなコードを生成してくれるんでしょうか。meiさんのコードで試しにやってみました。

C#コード:

using System;

public class Test
{
int n = 1;
int [] lhs = new int [] {1,2,3};
int [] rhs = new int [] {1,2,3};
public static void Main ()
{
Console.WriteLine (new Test ().Foo ());
}
private int Foo ()
{
for (int i = 0; i < n; ++i) {
if (lhs [i] != rhs [i])
return i;
}
return n;
}
}

$ cs2n mei-nem.cs

生成されたNemerleコード

using System;

public class Test
{
mutable n : int = 1;
mutable lhs : array [int] = array[1,2,3];
mutable rhs : array [int] = array[1,2,3];
public static Main () : void
{
Console.WriteLine ( Test ().Foo ());
}
private Foo () : int
{
{
mutable temp_2_return_ = Nemerle.Extensions.DefaultValue(int);
mutable temp_1_break_loop_ = false;
for (mutable i = 0; i < n && !temp_1_break_loop_; ++i) {
when (lhs [i] != rhs [i])
{
temp_1_break_loop_ = true;
temp_2_return_ = i;
}
}
if( temp_1_break_loop_ )
{
temp_2_return_;
}
else
{
{
n;
}
}
}
}
}

うーん、まあそういうことですよね…^^;

全然関係ないですがnemerleのビルドって何つーか美しいですよねぇ。見てて楽しくなっちゃいます。

日本語エンコーディング

ええと、monoのサポートは非常にヨワヨワです。日本語エンコーディングまわりがイケてないことに気づいたのは1.0リリース直前で手の出しようが無く、そして最近まで忘れてました(ばく 僕は全然使わないので…。日本語処理まわりが弱いよー、という話は、僕ができる範囲では声を大にしてw説明してきたつもりですが…

で、以下サマリーですが

という状態です。誰かやってくれないかなぁ…

ちなみにUnicode (utf-8/utf-16)は、System.Text.Encodingとしては問題なく使えるはずです。

で、各論。(1)shift_jisサポートがダメダメなのは、ひとつにはこれらがPortable.NETのコードをベースにしていて、けっこうやっつけな部分があるということ。PNETは日本人参加者がゼロで、日本語エンコーディングにはunicodeコンソーシアムが提供している変換マッピングでは使い物にならないとか、その辺のことをあまり知らずに2使っていたりするので、shift_jisの互換性はあまりよくありません。僕が1.0リリース直前に気づいて直した部分がちょっとはありますが、焼け石に水です。それと(2)非Windows環境におけるshift_jisの扱いってかなり微妙ですというか分かりません。たとえばUnix環境上で動作しているMySQLやPostgreSQLと接続するときに、MS932でもいいものなんでしょうか。SJISを使う.NETアプリケーションをそのままLinuxに持って行って、何の問題もなく動くことが期待できるとは、ちょっと思えません。

euc-jpは、monoに存在していないことに気づいたときに、僕が何日かで形だけやっつけたものなので、品質はきわめて悪いです。

ていうか昔書いてました

実際この辺も直したいとは思っていて、Miguelに「collationもそうだけど、エンコーディングまわりも改善の余地があるよね」と話してたりしたんですが。I18Nのフレームワーク部分以外では99.9*%日本人にしか利益が無い部分ですし…

Who’s the origin?

Duncanに「高橋メソッドって何?」と聞かれたので教えていたら、曰く

he uses the lawrence lessig approach to slides

おー確かに。Free Cultureのなんてそうだったかもしれない。僕が2,3年前に東大で見てた奴はそうだった気がする。ていうかあれは英語だけだったけど面白かった。

ていうか早速はてなキーワードになってるし…

Unicode文字/文字列のつかいかた

id:siokoshouさんが言及されていたので、ちょっとこの辺の話を。

僕が例に挙げたやつは、別に僕の発見ではなく、CompareInfoについて調べていたときに@IT会議室が引っかかったというだけのことです。それどころか、こちらで書かれていることと内容としては全く同じ話です。

まず、String.IndexOf()やString.Compare()の処理結果は、CultureInfo.CurrentCultureに依存します。Unicodeのcodepointだけを比較するIndexOf()に相当する機能は~~無いと思います3~~CompareInfo.IndexOf()で、Compare()には対応するCompareOrdinal()というのがSystem.Stringにあります。

InvariantCultureを使っても、文字列がcodepointで比較されるようになるわけではありません。InvariantCultureのCompareInfoでも、Compare()やIndexOf()は「やわらかく」(←てきとーな表現)行われます。この場合、IndexOf()は対応するCultureInfoのCompareInfoのIndexOf(string, string, CompareOptions)に該当します。CompareOptionsは_たぶん_Noneが渡されますし、IgnoreXXXのいずれのフラグも立っていない状態なので、例のゼロ文字が無視されるのは納得できないかもしれませんが、これは納得できません(何だそりゃ)。Unicode Normalization (UTR#15)では、\u3007はcompositionの対象とはされていませんし(されても困る)、Unicode Collation Algorithmのデフォルトテーブルでも\u3007は無視される文字としては定義されていないので4、前回書いたとおり、MicrosoftのMichael Kaplanがいうところの「MS仕様」なのかもしれません。

このような文字列比較を実際に行っているのは、PlatformSDKでいうところのLCMapStringのはずです(MSDNにそう書かれているので)。だから、上記のMS Accessのページで説明されていることと同じ結果になるわけですね5

ええと、ちなみにこれは別にUCA (UAX#10)に違反しているということではありません。文字列比較はCulture(Info)に依存して、それぞれの文化に特化して行われて良いので、InvariantCultureも含めて、一と一〇が同一視できるというのがMicrosoftの文化だというのであれば、別にそれはUnicode標準に違反しているわけではないのです6

Compare()やIndexOf()と似たようなCultureInfo依存の機能に、ToLower(), ToUpper()というものがあります。これは、まずCultureInfoに依存しますので、トルコ(tr)やアゼルバイジャン(az)の環境で実行した結果は、その他の全ての国で実行した結果とは微妙に異なりますし、非ASCII文字についても文字変換が行われます。ややこしいことに、ToUpper()やToLower()は、CompareOptions.IgnoreCaseとは無関係です(のようです。具体例を見つけたら追記します)。

この辺の詳しい話は、例のMichael Kaplanのblogが参考になるでしょう。正しい実装のあり方は勉強できないかもしれませんが、MS実装がどうなっているかについては勉強することができると思います。


コメント

siokoshou — 04/14/2005 14:14:36

私も@IT会議室の話題を見つけて興味を持ちました。UnicodeやUnicodeのMSの実装の知識がまるでないので、ゼロ文字の扱いには驚きました。
「Compareではゼロ文字は無視され、IndexOfではゼロ文字は全ての文字にヒットする」この動作は困る場合が多いのでは?と思ってしまいます。
codepointを比較するIndexOfは、CompareInfo.IndexOf( String, String, CompareOptions.Ordinal )が該当しそうです。
MS Accessのページおもしろいですね。勉強になります。笑っちゃいましたが(^^;

atsushieno — 04/14/2005 14:45:18

あ、そうでしたIndexOf()はありますね。ありがとうございます。

akiramei — 04/14/2005 22:43:00

cs2n
あまりに関数型言語っぽくなくて笑いました。

atsushieno — 04/15/2005 01:25:29

ハイブリッド言語ですしね…。実際のところ置き換えとしては妥当な設計かなあと思います。

Footnotes

  1. gotoでいいじゃん、っていうフローブランチング最適化なんて無視無視なツッコミは梨のつぶてでお願いします^^;

  2. まあ僕も調べるまでは知らなかったわけですが

  3. どなたかご存じでしたら教えてください

  4. 少なくともUAX#10では。

  5. って僕は〇以外は確認してないので、細かい違いがあるかもしれませんが。

  6. もちろん、直すべきかどうかとは別の議論ですが。


この記事を共有:

前の記事
cs2n
次の記事
the latest Japanized MonoDevelop