.NETのYieldが何をしているか
.NETのYieldがどんなふうにILを出力してるんか調べてみた
VBだけ調べたけどC#も多分一緒だろう
割とcall/ccするのめんどいな
1. Yieldの付いた関数毎にIEnumeratorなクラスを作る、とりあえずStateMachineと呼ぶ
2. Yieldの付いた関数の引数、ローカル変数を全部メンバ変数に持つ
3. 戻り値と状態もメンバ変数に持つ
4. Yieldの出現箇所にユニークな連番を振る
5. Yieldしている個所の前で次のことをする
・Yieldの値を戻り値のメンバ変数に入れる
・4.で付けたユニークな番号を状態のメンバ変数に入れる
・Return Trueしとく
・Returnの後にユニークな番号に対応したラベルを張る
6. 関数を抜けるときに次のことをする
・最終行でっせというラベルを張る
・状態のメンバ変数に最終行でっせという値を入れる
・Return Falseする
' 呼び出し側 For Each x In Cdr(xs) ' なんか処理 Next Public Shared Iterator Function Cdr(xs As List(Of Integer)) For i = 1 To xs.Count - 1 Yield xs(i) Next End Function ↓ ' 呼び出し側 For Each x In New StateMachine With {._xs = xs} ' なんか処理 Next ' Yieldの関数展開結果 Class StateMachine Implements IEnumerator Private _i As Integer Private _xs As List(Of Integer) Private _value As Integer Private _state_machine As Integer = 0 Public ReadOnly Property Current() As Boolean Get Return _value End Get End Property Public Function MoveNext() As Boolean If _state_machine = 1 Then Goto __STATE1 If _state_machine = 2 Then Goto __STATE2 _i = 1 Do While _i <= _xs.Count - 1 _value = _xs(_i) _state_machine = 1 Return True __STATE1: _i += 1 Loop __STATE2: _state_machine = 2 Return False End Function End Class
簡単にcdrするILの関数書きたいだけなんだけど難しいなー・・・
クラッシュレポートを表示しない方法
Windowsでわざとクラッシュするプログラムを作ると報告ダイアログなんかがでてきてうっとうしかった
標準エラーにエラーはいてただ落ちればいいのに・・・
レジストリを設定すれば正しい動作に修正できるみたい
ついでにクラッシュダンプも作るのやめれるっぽい
これでセグメンテーションフォルト起こし放題だね!やったね!
Windows Registry Editor Version 5.00 [HKEY_CURRENT_USER\Software\Microsoft\Windows\Windows Error Reporting] "DisableQueue"=dword:00000001 "ForceQueue"=dword:00000001
関数の戻り値型から空配列の型解決
なんのこっちゃか分かりにくいけど
戻り値の型から空配列の型解決ができるようになった
型解決をするために配列を正規化している
return([]) ↓ $0 = [] return($0)
これをやると問題になるのがこんなやつ
xs = [Int]() ↓ $0 = [Int] xs = $0()
Intってのが型解決してみるまで変数なのか型なのか分からないので$0が配列型か配列か分からない
ってゆーか、変数に型の代入ができなかった
Nodeにインスタンスか型なのかのフラグを付けて対応したけど、これができひんのは分かっている
どうしようもないので後で考える
var xs = [] xs.Add(Int) var i = xs[0]()
ブラックジャックの点数
ブラックジャックの点数を数えるプログラムが思ってたのと全然違った
employment.en-japan.com
Aを2回以上11と数えるとバースト確実やねんから
Aの枚数=Aの合計値とみなしてかまへん
Aの枚数とA以外の合計値を求め、合計値-1が10以下ならA1枚を11とする
他はAを1と数えるだけでいい
せやないと6個のデッキをごちゃまぜにしてプレイしたときの
エース21枚という合法手に対し計算がややこしくなるやん(するかい、そんなん)
sumHand2 :: [Card] -> Int sumHand2 cards | as == 0 = ax | ax + as - 1 <= 10 = ax + as - 1 + 11 | otherwise = ax + as where (a, xs) = partition (== A) cards ax = sum (map toPoint2 xs) as = length a toPoint2 :: Card -> Int toPoint2 A = 1 -- 不要だけど書いておく toPoint2 (N n) = n toPoint2 _ = 10
そういえば練習でポーカーの手役を判定するプログラムと麻雀のシャンテン数を数えてたけど
作り途中でほっぽったのはどこ行ったんだろう
前のPCの中かな?
空気を読んだ関数のオーバーロード
関数の戻り値から関数のオーバーロードができるようになった
いゃったぁ!
こんな書き方しないけど!
今までインナー関数はマングリング(?)してグローバル関数として作っていたけど
returnを関数として実装している都合、関数毎にインナー関数用のスコープを持たせることにした
弟切草
叔父が亡くなって洋館を相続したので、彼氏と見学に行く
実は叔父が実の父で、なんか有名っぽい画家だったらしい
洋館を探索してるとミイラを見つけてしまい、逃げようとするけど車が倒木直撃し大破
管理人に襲われ、管理人室を見つけると監視カメラが全室に仕掛けられていた
管理人が彼女の妹(のような弟)で彼氏をクロスボウで射抜き、姉に父の絵を完成させるように迫る
絵が目を潰し炎に焼かれる絵なので、その通りにし館全焼
そこで終わってりゃいいものを、ゲームのプレイオチで、彼氏が助けて生き延びるシーンも見る
低予算を無理矢理誤魔化しました感が隠しきれてない
原作ゲームだからってそっちのオチに持ってくこと無いだろうに…