C の弱点 default のスペルミスを継承していた

no more creat。

package main
import "fmt"

func main() {
	a := 4;

	switch a {
	case 0, 1, 2:
		fmt.Println( a );
	case 3:
		fmt.Println( "いっぱい" );
	defuuuuult:
		fmt.Println( "defuuuuuuult" );
/*
	default:
		fmt.Println( "default" );
*/
	}
}

何も表示されません。
文法見ると禁止されてるっぽいのに、穴がありますね。「defuuuuult:」は前の「case 3:」に続く StatementList 中のラベルになってるのかも。

「$ hg log」したらこんなのが。やられたw

changeset:   3956:4a3f6bbb5f0c
user:        Ken Thompson 
date:        Tue Nov 10 15:05:15 2009 -0800
summary:     spell it with an "e"

$ hg log -r3956 -p

+	O_CREATE	= O_CREAT;		// create a new file if none exists.

goroutine を使ってみた

Go 翻訳プロジェクトが立ち上がったようですね。チュートリアルのかなりの部分がもう訳されてます。
http://go.shibu.jp/

遊んでるうちに、将来は C に取って代わりそうだなという気がしてきました。

昨日のコードの goroutine 版が動きました。まだ goroutine がどういうものかさっぱりわからないので、使い方が間違ってる可能性大ですが。
ちょっと新人いじめがすぎました。遅いです。いや、使い方が間違ってるほうが大きいかもしれないけど。

(追記) うわさの runtime.GOMAXPROCS つけたらものすごく速くなった!使えるかもと思った。コードは差し替えておきます。
4CPU割り当ててやってみたらむしろ遅くなったw みんな並列じゃ苦労してるんだねw

以下、コード

続きを読む

Go でバックトラックを書いてみた

Go language に De Bruijn sequence を列挙するコードを移植してみました。C# で書いたときのコードは
goroutine を使って並列化したいんですが、まだデッドロックしてうまくいってませんw なのでとりあえずできたシーケンシャル版。ちなみに効率的に列挙するコードじゃなく、いじめ試験みたいなものです。

De Bruijn の読みがずっと謎だったんですが、コンピュータの数学という本では「ドブリューイン」としてました。O記法の数学のあたりにちらっと名前が出てきました。

Go は関数から多値で返す文法がきれいでいいですね。C# の out はやってることは正しいのに、汚い文法なのが悲しい。レシーバーとインターフェイスでも遊んでみたいな。Go を最初に見たときは古臭い文法だと思ったけど、調べているといろいろと今どきっぽい機能をちゃんと持ってたりします。まーまだわからないことだらけですが。

package main

import (
    "math";
    "fmt";
    "os";
    "container/vector";
)

type DeBruijnSeq struct {
    k, n, max int;
    results *vector.Vector;
}

func Init( k, n int ) ( d *DeBruijnSeq, ok bool ) {
    if k < 2 || 10 < k { return nil, false }
    if n < 1 { return nil, false }

    pow := math.Pow( float64( k ), float64( n ) );
    if float64( 0x7FFFFFFF ) < pow { return nil, false }
    max := int( pow );

    r := vector.New( 0 );
    return &DeBruijnSeq{ k, n, max, r }, true
}

func ( d *DeBruijnSeq ) Search() {
    a := vector.NewIntVector( d.n );
    for i := 0; i < d.n; i++ { a.Set( i, 0 ) }
    d.searchCore( a );
}

func ( d *DeBruijnSeq ) searchCore( a *vector.IntVector ) {
    // 重複判定
    if !d.isUnique( a ) { return }

    // 完成判定
    if d.isComplete( a ) {
        d.output2( a );
        return
    }

    // 次の反復へ
    for i := 0; i < d.k; i++ {
        b := vector.NewIntVector( 0 );
        b.AppendVector( a );  // copy
        b.Push( i );
        d.searchCore( b );
    }
}

func ( d *DeBruijnSeq ) isUnique( a *vector.IntVector ) bool {
    if a.Vector.Len() <= d.n { return true }

    pos := a.Vector.Len() - d.n;

    for i := 0; i < pos; i++ {
        if sequenceEqual( a, i, pos, d.n ) { return false }
    }
    return true
}

func sequenceEqual( v *vector.IntVector, a, b, len int ) bool {
    for i := 0; i < len; i++ {
        if v.At( a ) != v.At( b ) { return false }
        a++; b++;
    }
    return true
}

func ( d *DeBruijnSeq ) isComplete( a *vector.IntVector ) bool {
    if a.Vector.Len() != d.max { return false }

    b := vector.NewIntVector( 0 );
    b.AppendVector( a );  // copy

    for i := 0; i < d.n - 1; i++ {
        b.Push( b.At( i ) );
        if !d.isUnique( b ) { return false }
    }
    return true
}

func ( d *DeBruijnSeq ) output2( a *vector.IntVector ) {
    d.results.Push( a )
}

func main() {
    d, ok := Init( 4, 2 );
    if !ok { os.Exit( 1 ); }

    d.Search();

    fmt.Println( d.results.Len() );

    if len := d.results.Len(); len < 10 {
        for i := 0; i < len; i++ {
            fmt.Println( d.results.At(i) )
        }
    }
}

VMware Player 上の x86Ubuntu に 2CPU 割り当てて実行したんですが、結構速いかも。

Go

ロブ パイクとケン トンプソン(と V8 の人。扱い低くてゴメンナサイ)の新言語が2009年の今、出てくるなんてスゴイですね。C/C++ の幕引きは俺たちの手で…ってところでしょうか。Plan9 もきっと Unix の幕引きのために作ったんだろうなぁ。
でも、Go って名前の googlability 悪すぎ。わざとだろうけどw 検索するとイラっとくるw
それにしても、初日からプログラム書いた人があちこちにいてすごい。
とりあえず Go のチュートリアルをちまちまやって楽しんでます。

(追記) x86用の汎用 Makefile おいときます。1ソース→1実行ファイル用

.SUFFIXES:.go .8
.go.8:
	8g $<

.SUFFIXES:.8 .out
.8.out:
	8l -o $@ $<

GO	= $(wildcard *.go)
OUT	= $(GO:.go=.out)

all:	$(OUT)

!8 とかやると泣けるので(T-T)


(追記2) The Go Programming Language とか書いておかないと気付いてもらえない気がしたので書いておく。でも Issue 9 って名前に変わるならそれでもいいw
文字列の長さは utf8.RuneCountInString( s ) で取れた。len(s) だとutf8でのバイト数が返ってくる…
RuneUnicode character のことを短くそう呼んでるそうな。


(追記3) /go/src/pkg/exp/spacewar/ こ、これは伝説のwww
// This package and spacewar.go implement a simple PDP-1 emulator
// complete enough to run the original PDP-1 video game Spacewar!
でも make できない!

string の IndexOf は .NET4 でもカルチャー依存のまま

昨日の記事は例が悪かったのでわんくまの中さんに正反対に誤読されて残念なので、わかりやすく一覧表にしてみました。

string の StartsWith, EndsWith, IndexOf, LastIndexOf のカルチャー依存/非依存(ordinal)の状況

.NET2〜3.5.1 カルチャー依存
.NET4 CTP ordinal
.NET4 beta1 カルチャー依存 (元に戻した)
.NET4 beta2 カルチャー依存
.NET4 正式版 カルチャー依存 (たぶん)

CTP ではセキュアな変更を行ったものの、互換性のために beta1 以降元に戻されました。
BCL チームによると

UPDATE for .NET 4 Beta 1 In order to maintain high compatibility between .NET 4 and previous releases, we have decided to revert this change. The behavior of String's default partial matching overloads and String and Char's ToUpper and ToLower methods now behave the same as they did in .NET 2.0/3.0/3.5. The change back to the original behavior is present in .NET 4 Beta 1. We apologize for any interim confusion this may cause. We continue to recommend being explicit about the string comparison behavior you want, by always specifying a StringComparison value for the methods on String that accept it.

http://blogs.msdn.com/bclteam/archive/2008/11/04/what-s-new-in-the-bcl-in-net-4-0-justin-van-patten.aspx

だそうです。

ちなみに Silverlight3 は ordinal です。

そしてもう一度書いておくと、BCL Team 曰く「StringComparison パラメータをとるオーバーロードが存在するときはいつでも、このパラメータをとらないオーバーロードの代わりにそれを使ってください。それは、あなたのコードをより明白で維持するのをより簡単にします。」だそうです。
推奨事項は http://blogs.msdn.com/bclteam/archive/2005/06/01/424012.aspx
また、FxCop が指摘してくれるので使うことをおすすめします。
何が危ないの?って問題は昨日の記事を読んでください。

この問題とは別に〇の問題などが修正されているようです。

あなたがやりたいことはきっと "Hoge".IndexOf( "Hoge" ) ではなく "Hoge".IndexOf( "Hoge", StringComparison.Ordinal )

ずいぶん前にも書きましたが string の IndexOf には罠があります。ただ単に IndexOf( "Hoge" ) と書くと IndexOf( "Hoge", StringComparison.CurrentCulture ) の動作をしてしまいます。きっとあなたがやりたいことは IndexOf( "Hoge", StringComparison.Ordinal ) だと思います。

.NET4 で、この文字列の危険な落とし穴を修正しようとしたようですが、結局変更はキャンセルされたようです。BCL Team Blog によると、CTP では StartsWith, EndsWith, IndexOf, LastIndexOf をカルチャー依存から非依存(ordinal)に変更したけど、β1で戻したよとあります。実現していれば大きな影響を与えただけに反対されたのでしょうか?
変更しようとした理由はセキュリティへの懸念で、開発者が気づかずにカルチャー依存の文字列比較を行ってしまうことを防ごうとしたようです。これやばいんじゃね?とタレこんだけど使い方次第だと却下された私としては変更して欲しかったのですが、実現ならずで残念です。でも、BCL チームが変更しようとしたということは、やはり危険だと強く認識してるってことなので、無駄じゃなかったのかなとちょっと報われた気持ちです(私のタレこみがきっかけかどうかはわかりませんが)。

もう一度 IndexOf で遊んでみます。@IT 会議室の @echo さんの例を試してみます。「〇」は漢数字の零です。

using System;

class P
{
  static void Main()
  {
    Console.WriteLine( "AA".IndexOf("〇A") );           // 0
    Console.WriteLine( "AA".IndexOf("〇") );             // 0
    Console.WriteLine( "A〇A".IndexOf("AA") );         // 0
    Console.WriteLine( "〇A〇A".IndexOf("AA") );       // 1
    Console.WriteLine( "〇A〇A".IndexOf("〇A") );       // 1
    Console.WriteLine( "〇A〇A".LastIndexOf( "〇A" ) ); // 3
    Console.WriteLine();

    Console.WriteLine( "AA".IndexOf( "〇A", StringComparison.Ordinal ) );         // -1
    Console.WriteLine( "AA".IndexOf( "〇", StringComparison.Ordinal ) );           // -1
    Console.WriteLine( "A〇A".IndexOf( "AA", StringComparison.Ordinal ) );       // -1
    Console.WriteLine( "〇A〇A".IndexOf( "AA", StringComparison.Ordinal ) );     // -1
    Console.WriteLine( "〇A〇A".IndexOf( "〇A", StringComparison.Ordinal ) );     // 0
    Console.WriteLine( "〇A〇A".LastIndexOf( "〇A", StringComparison.Ordinal ) ); // 2

    Console.ReadKey();
  }
}

右側に書いた結果は Windows7/.NET3.5.1 での実行結果です。@echo さんの当時の実行結果と違いますが、やはりおかしいのは一緒です。どうしてこうなるのかわかりません。Ordinal での比較は OK ですね。@IT 会議室にめーさんが投稿したきっかけはカルチャー依存比較で無限ループするという問題でした。ソースコードは一見正常に見えるので、カルチャー依存がデフォルトなのは、問題が起きるまで気付かないタイプのいやらしい問題を産むということがわかります。怖いですね。
でもまあ FxCop が指摘してくれるので、使うことをおすすめします。

BCL Team 曰く「StringComparison パラメータをとるオーバーロードが存在するときはいつでも、このパラメータをとらないオーバーロードの代わりにそれを使ってください。それは、あなたのコードをより明白で維持するのをより簡単にします。」だそうです。recommend

でも、忘れちゃうんだよね…。やっぱり変えて欲しいんだけどなぁ…。

(追記) Silverlight で試してみると、ややこしいことにカルチャーに依存しない動作がデフォルトでした。つまり、"Hoge".IndexOf( "Hoge" ) が "Hoge".IndexOf( "Hoge", StringComparison.Ordinal ) の動作と同じです。
それはそれでいいんですが(ややこしいけど)、VisualStudio 2010 beta2 で試してみるとカルチャーに依存しない動作をしました…。どーなってるんだ…。
(追記2) aetos さんからのコメントによると、.NET4 Beta2 の IndexOf はカルチャー依存で、〇のおかしな挙動が修正されたとのことです。おそらく .NET4 が Unicode 5.1 準拠になった影響と思いますが詳しいことはわかりません。
aetos さんの濁点のテストを Silverlight でやってみると、やはり Silverlight の IndexOf は Ordinal でした。そして、StringComparison.CurrentCulture を明示した場合は一致と判断されました。

WPF を使ったブラウザ

実用性はないけどおもしろいw
こんなにゆがんでてもスクロールできるし、クリックもできる。Chromium を利用しているっぽい。よく読んでないのでよくわかってないんだけど。ClickOnce でインストールできますが、サーバーが遅いのかものすごーく時間がかかるのでご注意を。5年後のインターネットはブラウザの四角い枠がなくなってるかもね。
via http://chriscavanagh.wordpress.com/2009/08/25/a-real-wpf-webbrowser/

こちらにソースもあります。

3Dバージョンもあった(^^;

(追記) そんなものよりこれがおもしろかった。クリックが止まらないw
Silverlight。2D 物理エンジンなのかな。プルプルムニムニモフモフ