...ing logging 4.0

はてなブログに移行しました。D言語の話とかいろいろ。

愚直に書くのが最速だった

final class Lexer
{
	private const string source;
	
	this(in string source)
	{
		this.source = source;
	}
	
	const(string)[] lex() const
	{
		static string[] f(string line)
		{
			auto app2 = appender!string();
			app2.put(line);
			app2.put(",");
			app2.put(TOKEN_END_OF_LINE_MARK);
			return split(app2.data, ",");
		}
		
		auto app = appender!(string[])();
		foreach (string line; splitLines(source))
			foreach (string r; f(line))
				app.put(r);
		return app.data;
	}
}

std.parallelismやThreadを使って書くよりも愚直にforeachで書く方が早かった.
むむむ.

何だかうまく書けない

final class Lexer
{
	class LexerThread : Thread
	{
		private const(string)[] lines;
		private Appender!(string[]) app;
		
		this(const(string)[] lines)
		{
			this.lines = lines;
			app = appender!(string[])();
			app.reserve(10000);
			super(&run);
		}
		
		void run()
		{
			foreach (line; lines)
			{
				auto app2 = appender!string();
				app2.put(line);
				app2.put(",");
				app2.put(TOKEN_END_OF_LINE_MARK); // "[TEOL]"
				app.put(split(app2.data, ","));
			}
		}
		
		string[] data() @property
		{
			return app.data;
		}
	}
	
	private const string source;
	
	this(in string source)
	{
		this.source = source;
	}
	
	const(string)[] lex() const
	{
		const(string)[] lines = splitLines(source);
		auto worker1 = new LexerThread(lines[    0 .. $/4*1]);
		auto worker2 = new LexerThread(lines[$/4*1 .. $/4*2]);
		auto worker3 = new LexerThread(lines[$/4*2 .. $/4*3]);
		auto worker4 = new LexerThread(lines[$/4*3 .. $    ]);
		worker1.start();
		worker2.start();
		worker3.start();
		worker4.start();
		worker1.join();
		worker2.join();
		worker3.join();
		worker4.join();
		auto app = appender!(string[])();
		app.put(worker1.data);
		app.put(worker2.data);
		app.put(worker3.data);
		app.put(worker4.data);
		return app.data;
	}
}

何がLexerなのか全然分からないけどそれは脇に置いておく.
linesへ1行ごとに格納して,それを4分割して4つのスレッドに処理を任せて,最後にapp.dataとして直列化する.
何かこういうことするにはsharedはいらないみたいだ.
もっとまともな書き方がありそうに思えるけど特に思いつくわけでもなく・・・.

std.traits.isCovariantWith

import std.traits;

interface I { I clone(); }
class C : I
{
    override C clone()   // I.clone() の共変オーバーライド
    {
        return new C;
    }
}

void main()
{
	{
		static assert(isCovariantWith!(typeof(C.clone), typeof(I.clone)));
	}{
		C function() derived;
		I function() base;
//		static assert(is(typeof(derived) == function));
//		static assert(is(typeof(base) == function));
		
		base = derived;
		static assert(isCovariantWith!(typeof(derived), typeof(base)));
	}{
		C delegate() derived;
		I delegate() base;
//		static assert(is(typeof(derived) == function));
//		static assert(is(typeof(base) == function));

		base = derived;
		static assert(isCovariantWith!(typeof(derived), typeof(base)));
	}
}

dmd 2.056から関数とデリゲートのcovarianceが考慮されるようになったので,たまたま見つけたisCovariantWithでも判定できるかと思ってやってみたら動かなかった.
isCovariantWith(F,G)のconstraintを消したら動いたけど,あれって必要なのかな?
そもそも,static assert(is(main == function);がfalseなんだけどis(... == function)ってどういうものだったっけ・・・.

typeof(main) == functionだった.

template isCovariantWith(F, G)
    if (is(F == function) && is(G == function) ||
        is(F == delegate) && is(G == delegate) || isFunctionPointer!F && isFunctionPointer!G)

こうかな.

import std.traits;

interface I { I clone(); }
class C : I
{
    override C clone()   // I.clone() の共変オーバーライド
    {
        return new C;
    }
}

void main()
{
	{
		static assert(isCovariantWith!(typeof(C.clone), typeof(I.clone)));
	}{
		C function() derived;
		I function() base;
		base = derived;
		static assert(isCovariantWith!(typeof(*derived), typeof(*base)));
		static assert(isCovariantWith!(typeof(derived), typeof(base)));
		//static assert(isCovariantWith!(typeof(derived), typeof(*base)));
		//static assert(isCovariantWith!(typeof(*derived), typeof(base)));
	}{
		C delegate() derived;
		I delegate() base;
		base = derived;
		static assert(isCovariantWith!(typeof(derived), typeof(base)));
	}{
		C function() derived;
		I delegate() base;
		//base = derived;
		//static assert(isCovariantWith!(typeof(derived), typeof(base)));
		//static assert(isCovariantWith!(typeof(*derived), typeof(base)));
	}
}