mono
2010/02/01 § コメントする
ubuntu9.10上でmono-develを入れて、以下のコードがコンパイルできた。
using System; public class Program { public static int Main(string[] args) { Console.WriteLine("Hello World"); return 0; } }
$csc hello.cs $./hello.exe Hello World
lispとrubyとpythonと その4 Cライブラリの呼び出し(python) の追記
2009/02/21 § コメントする
lispとrubyとpythonと その4 Cライブラリの呼び出し(python) – テンポラリにfgshunさんからコメントをもらったので試してみた。
呼び出しているcライブラリはこんどもlispとrubyとpythonと その4 Cライブラリの呼び出し(lisp) – テンポラリと同じもの。
呼び出し先のcで確保した領域はcontentsに入ってくるけど、元の変数にセットされない。
分かるような、納得いかないような。
p = pp.contents
で自分でセットしなおしといた。
import ctypes from ctypes import * so = ctypes.CDLL("./libffi-test.so") so.f.argtypes = [c_int] so.f.restype = c_int def f(i): return so.f(i) print(f(5)) so.f0.argtypes = [c_char_p,c_int] so.f0.restype = c_int def f0(buf,len): return so.f0(buf,len) buf0 = create_string_buffer(10) f0(buf0,10) print(buf0.value) so.f1.argtype = [POINTER(c_char_p)] so.f1.restype = c_int def f1(buf): return so.f1(pointer(buf)) buf1 = c_char_p() f1(buf1) print(buf1.value) so.f2.restype = c_char_p def f2(): return so.f2() print(f2()) class Person(Structure): _fields_ = [("name",c_char_p), ("age",c_int)] so.f3.argtype = [POINTER(c_void_p),c_int] so.f3.restype = c_int def f3(person): person.name = cast(create_string_buffer(16),c_char_p) return so.f3(pointer(person),16) p1 = Person() f3(p1) print(p1.name) print(p1.age) so.f4.argtype = [POINTER(POINTER(c_void_p)),c_int] so.f4.restype = c_int def f4(person): return so.f4(person) p = Person() pp = pointer(p) ppp = pointer(pp) f4(ppp) print("ppp:" + ppp.contents.contents.name) print("pp:" + pp.contents.name) #print("p:" + p.name) p = pp.contents print("p:" + p.name) #->ppp:名前いいい # pp:名前いいい # p:名前いいい
LinuxでC#を書いてみた(Mono)
2008/12/21 § コメントする
Seriesとか、Pythonのジェネレータを触っているとLINQとかと比べたくなる。
しかし家に帰ってまでWindowsを起動したくない。(IPhoneのファームを上げるとき以外は)
ならMonoでも動かしてみるか、と急に思い立った。
取り合えずUbuntuのSynapticパッケージマネージャでmonodevelopを入れる。
よくわからんがmonoの開発するっぽい名前だから。
monodevelopを入れると依存関係で他にも色々はいるみたい。けど細かいことは気にしない。
次はコンパイルの仕方と動かしかた。
コンパイラはgmcsらしい。
最初はやっぱりhello worldかなぁ。
サクッと書く。emacsでC#のコードを書くのはちょっと不思議な感じだ。
やっぱりVisual studioで書く方が楽。
//Hello.cs using System; public class Program { public static int Main(string[] args) { Console.WriteLine("Hello World"); return 0; } }
こんなソースを書いて
gmcs Hello.cs
でコンパイル。成功してHello.exeができる。
実行は
./Hello.exe
でOKみたい。
Hello World
と表示される。
さて。動作確認はとれた。
あとはどこまでできるかだ。そもそもMonoってLINQ通るんかな?(先に調べろ)
//Hello2.cs using System; using System.Collections.Generic; using System.Linq; public class Program { public static int Main(string[] args) { var lst = new List<int>(); lst.Add(1); lst.Add(2); lst.Add(3); lst.Add(4); lst.Add(5); var lst_gt3 = lst.Where(i => i > 3); lst_gt3.ToList().ForEach( i => Console.WriteLine(i)); Console.WriteLine("----------------------------"); var result = from e in lst where e > 3 select e; foreach(var e in result) { Console.WriteLine(e); } return 0; } }
というわけでLINQテスト用。
gmcs Hello2.cs
でコンパイルするとエラーはなし。
./Hello2.exe で 4 5 ---------------------------- 4 5
が出力された。おお。LINQもいける。
いい感じだ。
あとは開発環境だな。なんでかわかんないけどC#はEmacsで書く気になれない。
Eclipseでも入れてみるかな・・・。
lispとrubyとpythonと その4 Cライブラリの呼び出し(まとめ)
2008/10/16 § コメントする
それぞれの言語でCと連携してみたまとめ、というか感想というか。
lispもRubyもPythonも呼び出し自体はわりと簡単。
ちゃんと動くかどうかは別として・・・。
一番すんなり理解できたのはSBCLだったような気がする。
Rubyの「拡張ライブラリをCで書く」っていうアプローチが僕にとっては新鮮だった。
CでmallocしたメモリをGCがどんな風に扱うかが気になってGCも調べた。・・・けどよくわかんない。
CommonLisp
CommonLispというか、SBCLだけど。
CのコードをLispにマッピングして書くイメージ。
sb-alien:load-shared-object
ライブラリをロード
sb-alien:define-alien-routine
C関数を呼び出すラッパを宣言
sb-alien:define-alien-type
Cの構造体に対応したデータ構造を宣言
sb-alien:with-alien
Cの変数をレキシカル変数として宣言
sb-alien:make-alien
malloc
sb-alien:free-alien
free
ここ読むとSBCLは保守的GCらしい。
ということはrubyと一緒でコンパクションはしてないのかな。
Ruby
SBCLとは違って、RubyのクラスをCで作るイメージ。
C側で作ってしまえばRubyから使う方はrequire xxxとするだけなので簡単。
Cでクラスを作るときは
#include <ruby.h>
が必須
rb_define_alloc_func
newのときに呼び出される関数を登録
rb_define_private_method
rb_define_method
メソッドにあたる関数を登録
RubyのGCはmark and sweepで保守的GC。
1.9でもコンパクションはしないみたい。
Python
ctypesだとloadは
ctypes.CDLL(“xxx”)
でOKだし、呼び出しもなんとなく通るので楽。
argtype
引数のタイプを指定
restype
戻り値のタイプを指定
メモリのアロケートの仕方はなんだかよくわからない。
PythonのGCは基本が参照カウンタで、循環参照の解決にmark and sweepっぽい仕組みを使ってる。(らしい)
メモリのコンパクションをしてるのかは不明。
参考
GCについて色々見てて見つけたサイト。
保守的GCで豪快にメモリリークするケースの話。
なるほど。。。
GCの話が色々
http://tiki.is.os-omicron.org/tiki.cgi?c=v&p=GC
perlは(5.0?)
参照カウント + (スレッド終了時に)マーク・スイープなんだってさ。
lispとrubyとpythonと その4 Cライブラリの呼び出し(python)
2008/10/14 § コメントする
最後はpython。
Cとの連携方法はいくつかあるみたい(boost.pythonとかswingとか)あるみたいなんだけど、ctypesを使用。
呼び出しているcライブラリはlispとrubyとpythonと その4 Cライブラリの呼び出し(lisp) – テンポラリと同じ。
参考は、まぁここ。
http://www.python.org/doc/2.5.2/lib/module-ctypes.html
int f4(person_t** person);の呼び出しかたがわかんなかったんだけど今日はもう力尽きた・・・。
# -*- coding:utf-8 -*- import ctypes from ctypes import * so = ctypes.CDLL("./libffi-test.so") so.f.restype = c_int def f(i): return so.f(i) print f(5) so.f0.argtypes = [c_char_p,c_int] so.f0.restype = c_int def f0(buf,len): return so.f0(buf,len) buf0 = create_string_buffer(10) print f0(buf0,10) print buf0.value so.f1.argtype = [POINTER(c_char_p)] so.f1.restype = c_int def f1(buf): return so.f1(pointer(buf)) buf1 = c_char_p() f1(buf1) print buf1.value so.f2.restype = c_char_p def f2(): return so.f2() print f2() class Person(Structure): _fields_ = [("name",c_char_p), ("age",c_int)] so.f3.argtype = [POINTER(c_char_p),c_int] so.f3.restype = c_int def f3(person): person.name = cast(create_string_buffer(16),c_char_p) return so.f3(pointer(person),16) p1 = Person() f3(p1) print p1.name print p1.age #so.f4.argtype = [POINTER(POINTER(Person))] #so.f4.restype = c_int #p2 = POINTER(POINTER(Person)) #print so.f4 #print p2 #so.f4(p2) #so.f4(pointer(pointer(p2))) #so.f4(p2) #print p2.name
lispとrubyとpythonと その4 Cライブラリの呼び出し(ruby)
2008/10/14 § コメントする
つぎはruby。
rubyだとCライブラリを呼び出すというよりはrubyのクラスをCで書く感じ。
ruby1.9でためしたんだけど、1.9では
RSTRING(xxx).ptr
とか
RSTRING(xxx).len
ではなくて
RSTRING_LEN(xxx)
RSTRING_PTR(xxx)
と書くみたい。
参考はこのへん。
http://i.loveruby.net/w/RubyExtensionProgrammingGuide.html
でcで書いた拡張ライブラリがこんなの。
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <ruby.h> typedef struct { VALUE prefix; VALUE suffix; } decorator; void decorator_mark(decorator *p) { rb_gc_mark(p->prefix); rb_gc_mark(p->suffix); } void decorator_free(decorator *p) { } VALUE decorator_alloc(VALUE cls) { decorator *p = ALLOC(decorator); return Data_Wrap_Struct(cls,decorator_mark,decorator_free,p); } VALUE decorator_initialize(VALUE self,VALUE prefix,VALUE suffix) { decorator *p; Data_Get_Struct(self, decorator, p); Check_Type(prefix,T_STRING); Check_Type(suffix,T_STRING); p->prefix = prefix; p->suffix = suffix; return Qnil; } VALUE decorator_get_string(VALUE self,VALUE str) { Check_Type(str,T_STRING); decorator *p; Data_Get_Struct(self, decorator, p); char* buf = ALLOC_N(char,RSTRING_LEN(p->prefix) + RSTRING_LEN(str) + RSTRING_LEN(p->suffix) + 1); memset(buf,0,RSTRING_LEN(p->prefix) + RSTRING_LEN(str) + RSTRING_LEN(p->suffix) + 1); strncat(buf,RSTRING_PTR(p->prefix),RSTRING_LEN(p->prefix)); strncat(buf,RSTRING_PTR(str),RSTRING_LEN(str)); strncat(buf,RSTRING_PTR(p->suffix),RSTRING_LEN(p->suffix)); return rb_str_new2(buf); } void Init_decorator() { VALUE d; d = rb_define_class("Decorator", rb_cObject); rb_define_alloc_func(d, decorator_alloc); rb_define_private_method(d, "initialize", decorator_initialize, 2); rb_define_method(d, "get_string", decorator_get_string, 1); }
で、こんな感じのスクリプトを実行
ruby -r mkmf -e 'create_makefile("decorator")' make # ruby
実行するとmakeまで走ってdecorator.soができる。
rubyからの呼び出しはこんな感じ。
require 'decorator.so' d = Decorator.new "start:" , ":end" puts d.get_string("aaa")
lispとrubyとpythonと その4 Cライブラリの呼び出し(lisp)
2008/10/14 § コメントする
今回はCライブラリの呼び出し。
SBCL限定なので注意。
sb-alienにCを呼び出すために必要なもろもろが入ってる。
一応動いてるんだけど、これであってんのかなぁ。
C側でmallocした時とか、GCのコンパクションでまずいことになったりしないんだろうか・・・。
参考はここ。
http://www.sbcl.org/manual/Foreign-Function-Interface.html#Foreign-Function-Interface
まず、呼び出すcのライブラリはこんなの。
ffi-test.h
int f(int i); int f0(char* buf,int len); int f1(char** buf); char* f2(); typedef struct person{ char* name; int age; } person_t; int f3(person_t* person,int len); int f4(person_t** person);
実装はこちら。
ffi-test.c
#include <stdio.h> #include <stdlib.h> #include <string.h> #include "ffi-test.h" int f(int i) { return i + 1; } //呼び出し元でAlloc int f0(char* buf,int len) { printf("hello\n"); strncpy(buf,"日本語\n",len); return 0; } //関数内でAlloc int f1(char** buf) { int sz = sizeof(char) * 64; *buf =(char*) malloc(sz); strncpy(*buf,"日本語2\n",sizeof(char) * 64); return 0; } //戻り値で返してみる char* f2() { int sz = sizeof(char) * 64; char* buf =(char*) malloc(sz); strncpy(buf,"日本語3\n",sizeof(char) * 64); return buf; } //構造体 呼び出し元でAlloc int f3(person_t* person,int len) { strncpy(person->name,"名前あああ",len); person->age = 30; return 0; } //構造体 関数内でAlloc int f4(person_t** person) { int sz1 = sizeof(person_t); *person = (person_t*)malloc(sz1); int sz2 = sizeof(char) * 64; (*person)->name = malloc(sz2); strncpy((*person)->name,"名前いいい",sz2); (*person)->age = 40; return 0; }
んで、これを
gcc -shared ffitest.c -o libffi-test.so
でコンパイル。
呼び出すlisp側はこんな感じ。
define-alien-routineでcライブラリとのラッパを宣言。
make-alienがmallocでfree-alienがfree。
(load-shared-object "libffi-test.so") (declaim (inline f)) (sb-alien:define-alien-routine f sb-alien:int (i sb-alien:int)) (declaim (inline f0)) (sb-alien:define-alien-routine f0 sb-alien:int (buf (sb-alien:* sb-alien:char)) (len sb-alien:int)) (declaim (inline f1)) (sb-alien:define-alien-routine f1 sb-alien:int (buf (sb-alien:* (sb-alien:c-string :external-format :utf8)))) (declaim (inline f2)) (sb-alien:define-alien-routine f2 sb-alien:c-string) (sb-alien:define-alien-type person_t (sb-alien:struct person (name (sb-alien:* sb-alien:char)) (age int))) (declaim (inline f3)) (sb-alien:define-alien-routine f3 sb-alien:int (person (sb-alien:* person_t)) (len sb-alien:int)) (declaim (inline f4)) (sb-alien:define-alien-routine f4 sb-alien:int (buf (sb-alien:* (sb-alien:* person_t)))) (defun lisp-f0() (sb-alien:with-alien ((len sb-alien:int (* (sb-alien:alien-size sb-alien:char) 64)) (buf (sb-alien:* sb-alien:char) (sb-alien:make-alien sb-alien:char len))) (unwind-protect (sb-alien:with-alien ((status sb-alien:int (f0 buf len)) (rtn (sb-alien:c-string :external-format :utf8) buf)) rtn) (sb-alien:free-alien buf)))) (defun lisp-f1() (sb-alien:with-alien ((buf (sb-alien:c-string :external-format :utf8))) (sb-alien:with-alien ((rtn sb-alien:int (f1 (sb-alien:addr buf)))) buf))) (defun lisp-f2() (sb-alien:with-alien ((buf (sb-alien:c-string :external-format :utf8) (f2))) buf)) (defun lisp-f3() (sb-alien:with-alien ((len sb-alien:int (* (sb-alien:alien-size sb-alien:char) 64)) (p (sb-alien:* person_t) (sb-alien:make-alien person_t 1))) (unwind-protect (progn (setf (slot p 'name) (sb-alien:make-alien sb-alien:char len)) (unwind-protect (sb-alien:with-alien ((status sb-alien:int (f3 p len)) (rtn (sb-alien:c-string :external-format :utf8) (slot p 'name))) rtn) (sb-alien:free-alien (slot p 'name)))) (sb-alien:free-alien p)))) (defun lisp-f4() (sb-alien:with-alien ((p (sb-alien:* person_t)) (status sb-alien:int (f4 (sb-alien:addr p))) (rtn (sb-alien:c-string :external-format :utf8) (slot p 'name))) rtn))
で呼び出し結果がこれ。
CL-USER> (lisp-f0) "日本語 " CL-USER> (lisp-f1) "日本語2 " CL-USER> (lisp-f2) "日本語3 " CL-USER> (lisp-f3) "名前あああ" CL-USER> (lisp-f4) "名前いいい"
Yコンビネータができるまで(C#)
2008/09/22 § コメントする
Yコンビネータ復習 – テンポラリをC#で書いてみた。
再起呼び出しをちょびちょび書き換えるので結構長編です。
C#だと静的型なので自己呼び出しするdelegateが必要。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Linq.Expressions; namespace Y { class Program { delegate int sum_delegate(int n); delegate sum_delegate fun_delegate(fun_delegate f); static void Main(string[] args) { int i = Fun(3); Console.WriteLine(i); Console.ReadKey(); } static int Fun(int n) { if (n == 0) { return 0; } else { return n + Fun(n - 1); } } } }
こんな感じの再帰関数をYコンビネータっぽいのを使って書き直す。
まずは再起呼び出しのFunを外からパラメータとして受け取るようにする。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Linq.Expressions; namespace Y { class Program { delegate FUNC SelfCaller<FUNC>(SelfCaller<FUNC> f); static void Main(string[] args) { int i = Fun(Fun)(3); Console.WriteLine(i); Console.ReadKey(); } static Func<int, int> Fun(SelfCaller<Func<int, int>> fun) { return delegate(int n) { if (n == 0) { return 0; } else { return n + fun(fun)(n - 1); } }; } } }
こうなった。
つぎにFunをMakeFunに変えて、MakeFunを呼び出すラッパをFunにする。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Linq.Expressions; namespace Y { class Program { delegate FUNC SelfCaller<FUNC>(SelfCaller<FUNC> f); static void Main(string[] args) { int i = Fun()(3); Console.WriteLine(i); Console.ReadKey(); } static Func<int, int> Fun() { return MakeFun(MakeFun); } static Func<int, int> MakeFun(SelfCaller<Func<int, int>> fun) { return delegate(int n) { if (n == 0) { return 0; } else { return n + fun(fun)(n - 1); } }; } } }
fun(fun)(n – 1)部分を切り出す。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Linq.Expressions; namespace Y { class Program { delegate FUNC SelfCaller<FUNC>(SelfCaller<FUNC> f); static void Main(string[] args) { int i = Fun()(3); Console.WriteLine(i); Console.ReadKey(); } static Func<int, int> Fun() { return MakeFun(MakeFun); } static Func<int, int> MakeFun(SelfCaller<Func<int, int>> fun) { return delegate(int n) { Func<int, int> imple = delegate(int m) { return fun(fun)(m); }; if (n == 0) { return 0; } else { return n + imple(n - 1); } }; } } } ||> 実処理を外から受けとるようにする。 static Func<int, int> Imple(Func<int, int> fun)が実際の処理。 >|cs| using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Linq.Expressions; namespace Y { class Program { delegate FUNC SelfCaller<FUNC>(SelfCaller<FUNC> f); static void Main(string[] args) { int i = Fun()(3); Console.WriteLine(i); Console.ReadKey(); } static Func<int, int> Fun() { return MakeSelfCaller(Imple)(MakeSelfCaller(Imple)); } static SelfCaller<Func<int, int>> MakeSelfCaller(Func<Func<int, int>, Func<int, int>> imple) { return delegate(SelfCaller<Func<int, int>> caller) { Func<int, int> makeFun = delegate(int m) { return caller(caller)(m); }; return imple(makeFun); }; } static Func<int, int> Imple(Func<int, int> fun) { return delegate(int n) { if (n == 0) { return 0; } else { return n + fun(n - 1); } }; } } }
FunがImpleをとるようにして、FunをYに改名。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Linq.Expressions; namespace Y { class Program { delegate FUNC SelfCaller<FUNC>(SelfCaller<FUNC> f); static void Main(string[] args) { int i = Y(Imple)(3); Console.WriteLine(i); Console.ReadKey(); } static Func<int, int> Y(Func<Func<int,int>,Func<int,int>> imple) { return MakeSelfCaller(imple)(MakeSelfCaller(imple)); } static SelfCaller<Func<int, int>> MakeSelfCaller(Func<Func<int, int>, Func<int, int>> imple) { return delegate(SelfCaller<Func<int, int>> caller) { Func<int, int> makeFun = delegate(int m) { return caller(caller)(m); }; return imple(makeFun); }; } static Func<int, int> Imple(Func<int, int> fun) { return delegate(int n) { if (n == 0) { return 0; } else { return n + fun(n - 1); } }; } } }
SelfCallerをインラインに展開してしまう。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Linq.Expressions; namespace Y { class Program { delegate FUNC SelfCaller<FUNC>(SelfCaller<FUNC> f); static void Main(string[] args) { int i = Y(Imple)(3); Console.WriteLine(i); Console.ReadKey(); } static Func<int, int> Y(Func<Func<int, int>, Func<int, int>> imple) { Func<Func<Func<int, int>, Func<int, int>>, SelfCaller<Func<int, int>>> caller = delegate(Func<Func<int, int>, Func<int, int>> prmImple) { return delegate(SelfCaller<Func<int, int>> prmCaller) { Func<int, int> makeFun = delegate(int m) { return prmCaller(prmCaller)(m); }; return prmImple(makeFun); }; }; return caller(imple)(caller(imple)); } static Func<int, int> Imple(Func<int, int> fun) { return delegate(int n) { if (n == 0) { return 0; } else { return n + fun(n - 1); } }; } } }
Impleは消しちゃって、Lambda式を受けとるように変更。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Linq.Expressions; namespace Y { class Program { delegate FUNC SelfCaller<FUNC>(SelfCaller<FUNC> f); static void Main(string[] args) { int i = Y(f => n => { if (n == 0) { return 0; } else { return n + f(n - 1); } })(3); Console.WriteLine(i); Console.ReadKey(); } static Func<int, int> Y(Func<Func<int, int>, Func<int, int>> imple) { Func<Func<Func<int, int>, Func<int, int>>, SelfCaller<Func<int, int>>> caller = delegate(Func<Func<int, int>, Func<int, int>> prmImple) { return delegate(SelfCaller<Func<int, int>> prmCaller) { Func<int, int> makeFun = delegate(int m) { return prmCaller(prmCaller)(m); }; return prmImple(makeFun); }; }; return caller(imple)(caller(imple)); } } }
intにしてた型をT、TResultに戻す。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Linq.Expressions; namespace Y { class Program { delegate FUNC SelfCaller<FUNC>(SelfCaller<FUNC> f); static void Main(string[] args) { int i = Y<int,int>(f => n => { if (n == 0) { return 0; } else { return n + f(n - 1); } })(3); Console.WriteLine(i); Console.ReadKey(); } static Func<T, TResult> Y<T, TResult>(Func<Func<T, TResult>, Func<T, TResult>> imple) { Func<Func<Func<T, TResult>, Func<T, TResult>>, SelfCaller<Func<T, TResult>>> caller = delegate(Func<Func<T, TResult>, Func<T, TResult>> prmImple) { return delegate(SelfCaller<Func<T, TResult>> prmCaller) { Func<T, TResult> makeFun = delegate(T m) { return prmCaller(prmCaller)(m); }; return prmImple(makeFun); }; }; return caller(imple)(caller(imple)); } } }
あとはちょこちょこと整える。
わかりやすいようにdelegateで書いてる部分をLambdaに置き換えていく。
最終的にはこんな感じ。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Linq.Expressions; namespace Y { class Program { delegate FUNC SelfCaller<FUNC>(SelfCaller<FUNC> f); static void Main(string[] args) { string s1 = Y<int,string>(f => n => { if (n == 0) { return "0"; } else { return n.ToString() + f(n - 1); } })(3); Console.WriteLine(s1); string s2 = Y<int, int, string>(f => (n, m) => { if (n == 0) { return "0"; } else { return n.ToString() + ":" + m + ":" + f(n - 1, m); } })(3, 4); Console.WriteLine(s2); Console.ReadKey(); } static Func<T, TResult> Y<T, TResult>(Func<Func<T, TResult>, Func<T, TResult>> imple) { Func<Func<Func<T, TResult>, Func<T, TResult>>, SelfCaller<Func<T, TResult>>> caller = prmImple => prmCaller => prmImple(m => prmCaller(prmCaller)(m)); return caller(imple)(caller(imple)); } static Func<T1, T2, TResult> Y<T1, T2, TResult>(Func<Func<T1, T2, TResult>, Func<T1, T2, TResult>> imple) { Func<Func<Func<T1, T2, TResult>, Func<T1, T2, TResult>>, SelfCaller<Func<T1, T2, TResult>>> caller = prmImple => prmCaller => prmImple((a,b) => prmCaller(prmCaller)(a,b)); return caller(imple)(caller(imple)); } } }
LINQで非決定性計算
2008/09/11 § コメントする
↑前にhaskellでやってたのをC# + LINQでやってみた。
前は意味わかんなかったけど、今なら読めるしかけるなぁ。
public void f1() { var result = from baker in Enumerable.Range(1, 5) from cooper in Enumerable.Range(1, 5) from fletcher in Enumerable.Range(1, 5) from miller in Enumerable.Range(1, 5) from smith in Enumerable.Range(1, 5) where !new[] { baker, cooper, fletcher, miller, smith }.Dup() && baker != 5 && cooper != 1 && fletcher != 1 && fletcher != 5 && miller > cooper && Math.Abs(smith - fletcher) != 1 && Math.Abs(fletcher - cooper) != 1 select new { baker = baker, cooper = cooper, fletcher = fletcher, miller = miller, smith = smith }; result.ToList().ForEach( r => Console.WriteLine( "baker:{0} cooper:{1} fletcher:{2} miller:{3} smith:{4}", r.baker, r.cooper, r.fletcher, r.miller, r.smith)); } ユーティリティがコレ public static class Util { public static bool Dup(this int[] values) { return values.Distinct().Count() != values.Length; } } メソッドで書くとこんな感じ? public void f2() { var result = Enumerable.Range(1, 5).SelectMany( baker => Enumerable.Range(1, 5).SelectMany( cooper => Enumerable.Range(1, 5).SelectMany( fletcher => Enumerable.Range(1, 5).SelectMany( miller => Enumerable.Range(1, 5).SelectMany( smith => Enumerable.Repeat(new { baker = baker, cooper = cooper, fletcher = fletcher, miller = miller, smith = smith }, 1)))))).Where( r => !new[] { r.baker, r.cooper, r.fletcher, r.miller, r.smith }.Dup() && r.baker != 5 && r.cooper != 1 && r.fletcher != 1 && r.fletcher != 5 && r.miller > r.cooper && Math.Abs(r.smith - r.fletcher) != 1 && Math.Abs(r.fletcher - r.cooper) != 1); result.ToList().ForEach( r => Console.WriteLine( "baker:{0} cooper:{1} fletcher:{2} miller:{3} smith:{4}", r.baker, r.cooper, r.fletcher, r.miller, r.smith)); }
SQLServer2005 バルクコピー
2008/04/29 § コメントする
メモ。
でかいサイズのデータを高速コピー。
http://msdn2.microsoft.com/ja-jp/library/7ek5da1a(VS.80).aspx
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Transactions; using System.Data.Sql; using System.Data.SqlClient; namespace BulkCopy { class Program { static void Main(string[] args) { //Exec_Datatable(); Exec_Datareader(); } static void Exec_Datareader() { var con = new SqlConnection(@"Data Source=xxx\sqlexpress;Initial Catalog=LockTest;Integrated Security=True"); con.Open(); var cmd = new SqlCommand("select * from tb2", con); var dr = cmd.ExecuteReader(); var sbc = new SqlBulkCopy("Data Source=xxx;Initial Catalog=Test;Integrated Security=True"); sbc.DestinationTableName = "tb0"; sbc.ColumnMappings.Add( new SqlBulkCopyColumnMapping( "cd_", "cd")); sbc.ColumnMappings.Add( new SqlBulkCopyColumnMapping( "data1_", "data1")); sbc.ColumnMappings.Add( new SqlBulkCopyColumnMapping( "data2_", "data2")); sbc.WriteToServer(dr); } static void Exec_Datatable() { using (var scope = new TransactionScope(TransactionScopeOption.RequiresNew)) { var da = new LocktestTableAdapters.tb2TableAdapter(); var dt = da.GetData(); var sbc = new SqlBulkCopy("Data Source=xxx;Initial Catalog=Test;Integrated Security=True"); sbc.DestinationTableName = "tb0"; sbc.ColumnMappings.Add( new SqlBulkCopyColumnMapping( "cd_", "cd")); sbc.ColumnMappings.Add( new SqlBulkCopyColumnMapping( "data1_", "data1")); sbc.ColumnMappings.Add( new SqlBulkCopyColumnMapping( "data2_", "data2")); sbc.WriteToServer(dt); scope.Complete(); } } } }