Hatena::ブログ(Diary)

やねうらお−ノーゲーム・ノーライフ このページをアンテナに追加 RSSフィード

GT-Rの買取ならここですわ。どこよりも高く買取ってもらえるはず。お勧め!GT-R 買取
電王戦出場記念! 書籍化されたで! 監修したで!(`ω´) 絶版なってしもた Kindle版で復活!! 記事書いたで!
解析魔法少女美咲ちゃん マジカル・オープン!

YaneuLabs / やねうら王公式 / やねうらおにメール / twitter / プロフィール

 | 

2009-12-30 サンタさん、ひゃくおくまんえんください(当方切実)

[] サンタさん、ひゃくおくまんえんください(当方切実)   サンタさん、ひゃくおくまんえんください(当方切実)を含むブックマーク   サンタさん、ひゃくおくまんえんください(当方切実)のブックマークコメント


※ これはとある目的のために別のブログに投稿した文章です。4人しか見てくれなかったのが悲しかったのでこちらに転載しておきます。なお、内容は一応フィクションです。



子供のころ、私の家では、サンタさんにお願いするためのプレゼントは、クリスマスの1週間前までにアンケート用紙に記入して母にそれを渡すとそれがクリスマスの日に届くという習わしになっていた。


「どうして一週間前がプレゼントの締め切りなの?」と私が母に尋ねると「サンタさんかて、プレゼント買う金をおろすのに銀行行かんとあかんやろ。年末になると銀行混んでるんや。ほやから早い目に銀行行かんとあかんねん。」と答えた。このとき私は初めてサンタも普段は家にはあまり現金を置いていないのだと知った。


「どうして、アンケート用紙には第三希望まで書かないといけないの?」と私が母に尋ねると「サンタさんかて、予算っちゅーものがあるんや。今年のサンタさん冬のボーナスが基本給の1.5ヶ月分しかでーへん。このご時世にもらえるだけでも有りがたいとしたもんや。この賞与のうち、1ヶ月分はローンの支払いで消える。今年は洗濯機つぶれたから新しいのに買い換えてしもたからな。」と答えた。よくはわからないが、サンタにもボーナスとかあって、洗濯機とか買って生活は困窮を極めているのだと子供心に思った。


「どうして、サンタさんボーナスは1.5ヶ月分なの?」と私が母に尋ねると「それはサンタさん大学出てへんから零細企業にしか雇ってもらわれへんかったからや。おまけに入社して10年目になるのにいまだに係長止まりで、あとから入社した大卒の人が上司になったりしていろいろ大変らしいねんで。いつも酒飲んだら愚痴ってはるわ」と母は悲しそうに言った。母は「アンケート用紙には、第三希望までだけじゃなく、もっとたくさん希望を書いておいてもええ」と付け足した。たくさん書いておけばそのうちのどれか一つぐらい叶うかも知れないと母は言った。


ところで、私には二歳年上の姉が居る。


お調子者である私は、テレビで「東大」が日本で一番賢い人の大学というのを知ると「将来は東大に行く!」だとか、プロ野球選手年俸は1億円をくだらないというのを聞くと「将来はプロ野球選手になる!」だとか、「ノーベル賞」が科学分野における最大級の栄誉であることを知ると「そして、ノーベル賞を取る!」だとか言っていた。


姉は、そのたびに「ほんまやな?ほんまにプロ野球選手になるんやな?」のように突っかかってきて、「な、、なる!絶対なる!!」と私が言うと、そのたびごとに誓約書を私に書かせた。小学低学年でろくに漢字も書けなかった私に姉は「プロやきゅうせんしゅになれなかったら、ミチコ(←姉の名前)に、ひゃくおくまんえん払います」と書かせた。


「ひゃくおくまんえん」がどんな貨幣単位かもわからないが、そんな調子で私が何か言うごとに姉は私に「ひゃくおくまんえん」の誓約書を私に書かせ、気がつくとそんな誓約書が十数枚たまっていた。金額に換算すると「十数百億万円」である。聞いたこともないようなお金単位だ。


私も小学校の高学年になると、この状況はまずいのではないかということにうすうす感づいたが、しかし「時、既に遅し」で、姉はその誓約書を鍵のかかる引き出しにしまい込んでいた。そうだ。サンタさんクリスマスプレゼントで「ひゃくおくまんえん」をもらえばいいんだと私は思った。しかし小学生低学年のときの私なら素直に「ひゃくおくまんえん」と書いていただろうが、そこは小学校の高学年である。ローンの支払いに困窮しているサンタにはそのような支払いは到底不可能である。そんな無理なお願いはしない。


だからその年のクリスマスアンケート用紙に次のように書いた。いままで姉に書いた誓約書の内容すべてを盛り込んだのだ。


第一希望. ( 東大合格してプロ野球選手になってノーベル賞をとって      )

第二希望. (  そのあと直木賞を取ってIQ300になって、アラブ石油王になって )

第三希望. ( 超能力者になって、億万長者になって、未来とか見えるようになって  )

 ノストラダムスを超えて、人智を超えて、人類の最後の叡智と呼ばれて、

 神とあがめられて、日本国民全員が信者になって、

 毎年のお布施が百億万円になって、

 ブッダとか日蓮とか空海とかと呼ばれて、

 キリストの生まれ変わりとかまことしやかに噂されて

 銀河鉄道列車に乗ってアンドロメダまで旅して

 機械の体とか手に入れて千三百歳まで生きて、

 そのあと火の鳥人魚の生き血をすすって不老不死になって

 体半分もぎとられてもなお生きて、地球核戦争後も生き残って、

 人類最後の子孫として末永くこの世界に君臨できますように。


その年のクリスマス当日の朝には私のベッドの枕元に「心が疲れたとき読む本 (PHP文庫)」、「精神科って、どんなとこ?―疲れた心と体を癒すストレスクリニック」という二冊の本がプレゼント包装をして置かれていた。たぶん、サンタ予算的に、そしてサンタ能力的にはそれが精一杯だったのだろう。「大学も出てねぇサンタは使えねぇな!!」と私は思った。


あれから、十数年経ったが、いまだにどの願いも叶っていない。姉は私の誓約書を持ったまま嫁いで行った。姉がいつ誓約書のことを言い出すか私は今日不安に怯えながら背中を丸くして縮こまって寝ている。


サンタさん、どうか今年こそは、どれかが叶いますように。

さもなくば姉がこの世から消えていなくなりますように


よろしくお願いいたします・・・

aa 2009/12/30 16:01 家のサンタは予算一万までって明言してました

サンタサンタ 2009/12/30 16:30 姉に書かされた誓約書って書けばよかったのに・・・

pp 2009/12/30 18:07 >姉に書かされた誓約書って書けばよかったのに・・・
それだ!

@@@@@@@@@@@@ 2009/12/31 07:26 大学院まで出て、入社15年目で肩書きなし。
後輩にもどんどん抜かれています…

新年新年 2010/01/01 00:07 あけおめ

トラックバック - http://d.hatena.ne.jp/yaneurao/20091230

2009-12-23 理解するってどういうことだろう?

[] 理解するってどういうことだろう?  理解するってどういうことだろう?を含むブックマーク  理解するってどういうことだろう?のブックマークコメント


「1,3,5,…と奇数の和をどこかで中断する場合を考える。例えば、1 + 3 = 4 , 1 + 3 + 5 = 9 , 1 + 3 + 5 + 7 = 16 , …。不思議なことに、それらはいつも平方数(自然数の2乗)になっている。」


↑を証明せよというのが、高校数学でΣの計算を学んだときに書いてあったと思う。


■ 理解のステップ1) Σの計算


よくは覚えていないが、解答はたぶん次のようなものだったと思う。なお、以下の"^" はべき乗を意味するとする。


S(n) = 1 + 2 + … + n = n(n+1)/2 全体を2倍して

2S(n) = 2 + 4 + … + 2n = n(n+1)


いま求める関数を g(n) = 1 + 3 + … + (2n -1) とおくと、

g(n) = S(2n) - 2S(n) = 2n(2n+1)/2 - n(n+1) = n^2

で確かにn(整数)の2乗になっている。


これをせずに、間違って

g(n) = 1 + 3 + … + (2n - 1) + (2n + 1)

とおいたりしたら、g(n) = S(2n+1) - 2S(n+1) = ... = n^2 + 2n + 1 = (n+1)^2

とかなって、余計な仕事が増える。


はたまた、

g(n) = 1 + 3 + … + m

とかおいて、これを計算するのに、g(n) から 2 + 4 + … + (n - 1) を引いたものだ、とか計算しようとしたら、それこそ大変なことになるだろう。


こういうことをしてしまうと、すこぶる大変になることを問題集の解答は教えてくやしない。問題集の解答はシンプルで、かつ最短距離である。


では何故、g(n)を上の最初の解答のように定義したのかというと、奇数の和g(n)がn^2と表わせることが事前にわかっていたので、まず小さなnで試したのだ。


たとえば3項目まで奇数の和を書き出す。1 + 3 + 5 = 3^2 で、5というのは、2×3 - 1だから、g(n)がn^2で表わされるなら、最後の項は(2n - 1)の形でなければならないと"決めつけて"、gをg(n) = 1 + 3 + … + (2n -1)とおいた。これなら、g(n)の一般項が n^2 になるはずだから、テキトーに一般項を求めさえすればこのシンプルな形になることは"事前に"わかっていた。


偶数なら2n、奇数と言えば2n + 1と置け」なんて馬鹿参考書には書いてあるけど、奇数だから"2n + 1"と置いたほうが良いとは限らないことは上の解答のプロセスを見てもわかる。正確には、「奇数を2n + aと置くなら、aはその問題を見て適切に決めるべき」だろう。


つまり、証明問題を解くときには、その証明内容は正しいものだと仮定して、正しいならばこうなるはず!と頭のなかで考えている。その考えが問題を解く上では重要なのだけど、しかし、これは理解とは違うと思う。なぜなら、端っから正しいと頭のなかで信じている時点で疑ってかかるプロセスが欠落している。


■ 理解のステップ2) 数学的帰納法


そのあと、数学的帰納法を学んだときにまた証明問題としてこの問題に出くわす。数学的帰納法なら証明は簡単だ。


1) 1 = 1^2は明らか。

2) f(n) = 1 + 3 + … + (2n-1) とおいて、f(n + 1) = 1 + 3 + … + (2n-1) + (2n+1)。

f(n) = n^2 が成りたつと仮定すると、f(n + 1) = n^2 + 2n + 1 = (n + 1)^2 も成り立つので(以下略)


うーん。簡単だが、これでは、私は何かわかった気にならない。明らかに理解するということと証明するということとは違う。証明することによって理解した気になる人もいるかも知れない。証明する過程で理解が得られることもあるかも知れない。誰かに説明したりする過程で自分の理解が促進されて腑に落ちるかも知れない。


しかし数学的帰納法はどうも証明した気にならない。数学的帰納法再帰プログラミングとも似ていて、その振る舞いを頭のなかでイメージしにくい。再帰で書くとエレガントに書けることがあるのと同様に、数学的帰納法だとエレガントに証明できることはあるのだけども。


■ 理解のステップ3) 図形的解釈


次のように図形的に解釈してはどうだろうか。平方数だから正方形の面積をイメージして、2cm×2cm = 4cm^2の面積をもつ正方形があるとしよう。


□□

□□


この外周を塗り固めて、3cm×3cm = 9 cm^2の正方形を作ることを考えよう。


□□■

□□■

■■■


■の部分はどれだけあるかというと、もとの1辺である2cmの長さのものが2つと、右下の角の■がひとつだ。2cm×2cm + 1cm^2 = 5cm^2。元の1辺がxだとすると足された部分は2x + 1。おお、xが自然数なら、2x + 1は奇数ではないか。


つまり、1辺がxの正方形(x^2)に 2x + 1の外周を足すと、それよりひとまわり大きい1辺がx+1の正方形 (x+1)^2 ができあがるわけだ。


証明としては多少、中途半端だが、こちらのほうが直観的ではある。説明としてはわかりやすいかも知れない。しかし、高校生のときの自分を振り返って考えるに、こんな説明では全く納得がいかなかった。


■ 理解のステップ4) 何故その問題が出てきたのかを考える。


当時の私(高校生)が思ったのは、「そもそもこの問題を考えた誰か(誰だかは知らん)は、どうやってこの問題を考えたのだ?この整数の性質はもっと別の何かから導き出したのではないのか?」ということだった。


私はそういうときいつも決まって適当物語を作った。例えば次のような感じだった。


きっとなんかいろいろ階差数列を調べてるおっさんがいたんじゃないかと勝手想像する。階差数列のいいところは、

f(x) = x^3

だとして、

f(n+1) - f(n) = 3n^2 + 3n + 1

と。変形すると

f(n+1) = 3n^2 + 3n + 1 + f(n)

と。f(n)がわかっていれば、2乗以下の計算だけで3乗の計算ができちゃうぞ、と。これは乗算回数が減るのでコンピュータ数値計算する上でとてもおいしい。


おお、階差数列萌えてきた!いろんな関数の階差数列を求めちゃうぞ!!


f(x) = x^aとして、a=1のときから調べる。このときf(x) = xだから

f(n+1)-f(n) = n+1 - n = 1

つねに定数。これはこれで使えるけどあまり面白くない。


a=2のときはどうだ。このときf(x) = x^2だから

f(n+1)-f(n) = (n+1)^2 - n^2 = 2n + 1

なんだ、この2x + 1って形は!奇数じゃん、これ。


変形すると

f(n+1) = f(n) + (2n + 1)

こうなって、f(n)は平方数だから、平方数に奇数を足すと平方数!うひょー!


次はa=3。このときf(x) = x^3

f(n+1) - f(n) = 3n^2 + 3n + 1

これ面白いか?a=3以上はつまんないかも知れない。


じゃあ、もう少し一般化すると(以下略)


というようなストーリーを頭のなかで組み立てる。


こういうストーリーが組み立てられて、それが自然に思えたときに、私は初めてその物事が理解できた気になる。要領のいい人は、たぶんこんなことを考えずに、問題集の解答を見ただけでそこから出題者の意図や解法のテクニックを会得するのだろうけど、私は要領がすこぶる悪く、上のように式をこねくり回したり、全然問題とは関係のないストーリーを作ったりして、無駄時間をかけてばかりだった。


私の高校のときの数学の成績は駿台河合塾東大模試でA判定になる程度には良かったが、それは、このように数学にひたすら時間を費やしていたからだと思う。1問を解くのにいくつもの方法を試したりして丸一週間かけたこともある。いま思い返してみるに、要領はすこぶる悪かった。どう見てもお馬鹿な子の勉強法だろう。最近本棚を整理していたら昔の数学ノートがいろいろ出てきたので見ていたら、問題作成者の気持ちを勝手想像して書き綴った漫画のストーリーのようなものがたくさん書いてあって頭がクラクラした。

melponmelpon 2009/12/23 09:54 その漫画の公開はいつ頃を予定していますでしょうか!

yaneuraoyaneurao 2009/12/23 10:03 えっ?公開?!よ、、読みたいの??

通縋通縋 2009/12/23 12:19 新しいタイプの黒歴史ですな。

ラマヌジャンラマヌジャン 2009/12/23 12:51 全てナーマギリが教えてくれますが、何か?

yaneuraoyaneurao 2009/12/23 13:18 今日のコメント欄は笑いのレベルが高いな…。

理解=モデル化 説理解=モデル化 説 2009/12/23 14:46 階差数列萌えなおっさんが過去に実在したことを頭のなかで信じている時点で
疑ってかかるプロセスが(ry

それはそうと、ある対象について、ああすればこうなる(例:右にハンドルを切れば車は右に曲がる)
という経験的に獲得した事実が整合性のある形で集積して現実の局面で知識として引き出せたり
実践できる状態になることが理解ではないですかね
そして理解には浅いの(上の例)と深いの(例:右にδだけハンドルを切れば車はεだけ右に曲がる)の違いがある

g(n)について物語まで作れるというのはg(n)について「ああすればこうなる」がたくさん集積された結果だからg(n)について深く理解したといえると思いますが、それが
g(n)がらみの問題を「効率良く解く」方法についての知識集積とはドメインが微妙にずれてるのは
当然であって不思議ではない感

それはそうと、2S(n) = (最小の正の偶数n個の和) = n(n+1) = n^2 + n
→最右辺の+nを移項して (最小の正の奇数n個の和) = n^2
もぜひコレクションに

yaneuraoyaneurao 2009/12/23 17:34 > 階差数列萌えなおっさんが過去に実在したことを頭のなかで信じている時点で疑ってかかるプロセスが(ry

ははは。私の場合、疑うところと疑わないところとがアンバランスで、妖精さんが実在するだとかそういうのは決して疑わないところだったんですよね。

> 2S(n) = (最小の正の偶数n個の和) = n(n+1) = n^2 + n
> →最右辺の+nを移項して (最小の正の奇数n個の和) = n^2

それはとてもエレガントですね。そういや昔、その公式(?)を見たことがあるのをいま思い出しました。

何故すぐに思い出せなかったかというと、私はΣの公式は、学生のころはみんなが使っているΣn,Σn^2,Σn^3,Σn^4とその関連の公式はなるべく使うのを避けて(Σn^3,Σn^4はあまり知っている人は少ないかも知れない)、Σn(n+1),Σn(n+1)(n+2),Σn(n+1)(n+2)(n+3)みたいな連続数の積を中心に使っていたからです。

特に後者は計算がしやすいので、次数が高くなるほどメリットが大きくておいしいのですよね…。なぜこれを学校で教えないのかよくわかりませんが。

いもいも 2009/12/24 01:43 つまらない指摘ですが、g(1)=1なので、g(n)=1+3+...+(2n+1)ではなく、g(n)=1+3+...+(2n-1)としなければなりません。
2n-1と置くと計算が簡単だからというわけではなく、2n+1と置くとそもそも間違いです。

それと、対称性から考えたときに、奇数を2n+1とするよりも2n-1とした方が美しくなります。
奇数を2n+1, 偶数を2nとすると、奇数のnの動く範囲は0,1,2,...、偶数のnの動く範囲は1,2,3,...となり、非対称ですが、
奇数を2n-1, 偶数を2nと表す場合、奇数のnの動く範囲は1,2,3,...、偶数のnの動く範囲も1,2,3....となり、対称性があって美しくなります。

yaneuraoyaneurao 2009/12/24 05:52 > g(1)=1なので (snip) 2n+1と置くとそもそも間違いです。

g(1)=1なんて条件はないですぞよ。

それはともかく、
> 対称性から考えたときに、奇数を2n+1とするよりも2n-1とした方が美しくなります。
これはそうですね。私は奇数を2n+1ではなく2n-1と置いたほうが解きやすい問題を結構見た覚えがあるのですが、それはそういう理由かも知れませんね。

神経質&神経質& 2009/12/24 07:52 m^2 + 2n + 1 = (m + 1)^2

すいません、これわかりません

yaneuraoyaneurao 2009/12/24 09:11 ↑すみません。おもいっきりtypoしてました。本文修正しました。

hiyahiya 2009/12/25 23:26 数学ってのは1個ずつ忠実に解いてゆけば、答えが導き出せると小学生のとき、後にお医者さんになった友人が言った言葉です。
これは、当時から数学が苦手だった私の支えになりました。

トラックバック - http://d.hatena.ne.jp/yaneurao/20091223

2009-12-03 やねうサーバーの受難

[] やねうサーバーの受難  やねうサーバーの受難を含むブックマーク  やねうサーバーの受難のブックマークコメント


以前、私の会社の社内サーバーは私の実家に置いてあるパソコンだった。母がインターネットをしたいというので、そのパソコン必然的に社内サーバー兼、母パソコンとなった。


母は省エネと称して勝手にそのパソコンの電源を切って、省エネに励んだ。おかげで社内サーバー接続できないこともしばしばだった。


ある雨の日に社内サーバーにつながらないので母に電話で尋ねたら、「雷が鳴っていたのでブレイカーをすべて落とした」とのことだった。言うまでもなく、サーバーは正常なシャットダウンではなく電源の突然のオフで、そのあと電源スイッチを押してももらえない。


ある日突然社内サーバー接続スピードが落ちたので母に尋ねたら、コーラスの練習ソフトを入れて、歌の練習をしていたのだそうだ。そのソフトwavファイルミキシングするために200MBほどメモリを食うようだった。ちなみに、そのパソコンは256MBしかメモリを積んでいない。


またある日は、そのパソコンウイルス感染した。ウイルスバスターを入れておいたのに何故感染したのかと思ったら、私が

ウイルスバスターがウイルスや
スパイウエアを駆除してくれる。

と書いておいたメモを見た母は「ウイルスバスターウイルスや!スパイウエアを駆除してくんろ!」と理解したらしく、急いでウイルスバスターアンインストールしたのだった。(私の手書きの字は汚く、確かにそう読めなくも無かった。)


そんな受難に満ちたやねうサーバーであったが、去年ぐらいから、ASP.NETを使ったサイトホスティングするためのサーバーを別に用意することになった。OSWindows Server 2008(その後R2にupdate)である。


このパソコンはいまの私の住んでいるほうの家に置くことにしたのだが、そういや、テレビ録画用のパソコンが古くなっているので処分しようと思い、Windows Server 2008のインストールされたパソコンを使ってテレビ録画をすることにした。あと24時間立ち上げておかないといけない某ネットゲーもそのパソコンで行なっている。


いまのところ、安定稼働している…が、そのサイトアクセスしているビジターは、まさかそのサーバーテレビ録画やネットゲーに使われているだなんて夢にも思ってもいないんだろうな…。

DmixDmix 2009/12/03 22:10 Windows Server2008にはウイルス対策ソフトをインストールする必要がありますか?

yaneuraoyaneurao 2009/12/03 23:22 ややこしくてすみません。母のパソコン兼社内サーバーはWindowsXPです。普通サーバー機にウイルス対策ソフトなんて入れないのですが、母が使うので特別に入れました。

DmixDmix 2009/12/04 12:37 サーバーについて詳しくないもので、少し教えて頂きたいのですが、通常のWEBサーバーとして使用する場合にはLinuxとWindowsServerではどちらが良いのでしょうか?
例えばチャットやオンラインゲームのようなサービスを提供する場合なのですが。
漠然とした質問で申し訳ないのです。

yaneuraoyaneurao 2009/12/04 13:30 ↑長くなったので↓に書いておきました。
http://yaneu.com/bbs/test/read.cgi/yaneurao/1195260091/64-65

DmixDmix 2009/12/04 23:11 ありがとうございます、私も↓に書いておきました。
http://yaneu.com/bbs/test/read.cgi/yaneurao/1195260091/64-66

トラックバック - http://d.hatena.ne.jp/yaneurao/20091203

2009-12-02 美しいループ記法求む!

[] 美しいループ記法求む!  美しいループ記法求む!を含むブックマーク  美しいループ記法求む!のブックマークコメント


いま私は速度的に特化したプログラムを書かなくてはいけない。1%でも速いほうが望ましい。必然的に言語C/C++となる。しかし、いまさらC/C++なんか使いたくない。もう少し洗練された記法が使える言語が好ましい。


なければ作ればいいやと思い、丸一日かけてC++のparserをC#で書いた。

C++言語の字句解析と構文解析は出来るようになった。(C++ templateは除く。)


あとは、いかようにも文法を拡張できる。この言語を仮にいまYaneCと名付ける。YaneCはコンパイルするとC++コードを生成する。


それでいま悩んでいるのがループ記法だ。C#のようなforeachが欲しい。最初、次のように書けるようにした。

foreach var x in vect
	sum += x;

ふむ、C#っぽくていい感じだ。C/C++のdefineマクロでforeachみたいなのを作ると次のようなものになるが、この末尾の");"を私は生理的に受け付けない。

foreach(x,vect,{
	sum += x;
});

次に範囲型という型を作って".."で書けるようにした。

foreach i in 0..9
	sum += i;

まあ悪くはない。N回まわるならどう書くか?

foreach i in 1..N
	sum += i;

ループzero originではないのは嫌だ。0からだろう。

foreach i in 0..N-1
	sum += i;

なんだこの"-1"というダサさ。これだと普通のforのほうがよっぽどマシだ。そもそも範囲型でExpression(式)をとれるようにしてしまうと、次のように書いたとき、"1"のあとの"*"を掛け算だと認識して次の行もExpressionとして捉えてしまうんだよ。

foreach i in 0..N-1
	*sum += i;

Cのポインタ記法が憎い。YaneCではC/C++ポインタ記法を禁止してもいいが、過去ソースとの互換がとれないのも嫌だ。

これを回避するためには、foreachの行末の改行をセパレータとして認識するようにするか、次ように"{"〜"}"でくくる記法にするしかない。行末の改行をセパレータと認識するようにすると、フリーフォーマットではなくなってしまう。それは少し嫌だ。だとすると後者か?

foreach i in 0..N-1
{
	*sum += i;
}

一気にダサくなった。げんなりである。すでに普通のforが恋しい。普通のforなら(C#なら)code snippetが使える。苦労してC++ parserまで書いて、状況は悪化している。やるせない。N回まわるのは、Rubyっぽく次のように書けばどうか。

N.times 
	printf( "こんにちは" );

こう書くには、integer型に対するstatic methodを定義できれば良い。こんなことは1時間もあれば楽勝だ。さっそく私はinteger型のstatic methodを書けるように拡張した。でもよく考えたら、ループ変数が欲しいこともある。Rubyに倣って次のように書けるようにするか?

N.times 
{ |i|
	sum += i;
}

なんだこれ。一気にダサくなった。おいおい勘弁してくれ。私は'{'とか'}'が大嫌いなんだよ。ループ内の処理を1行書きたいだけなのに、'{'で'}'囲って行数がだらだらと伸びるとソースが見にくくてしょうがない。あと、N+M回まわりたいときはどう書くんだ?

(N+M).times
{ |i|
	sum += i;
}

ダサすぎる。普通のforのほうがマシである。ループ構造なのだから、先頭に「これはループですよ」とわかる識別子が無いと可読性が悪いだろ。

foreach i in 10
	sum += i;

まだこちらのほうがマシだ。しかし「in 10」って英語的にどうなのか。これ絶対おかしいだろ。あと、foreachの"each"とタイプするのも面倒だ。forだけにさせてくれ。

for i 10 times
	sum += i;

言わんとすることはわかるが、どう見ても片言英語だ。しかもこの文法構造だと次のように書いたとき、Xが型名なのか変数名なのかを確定させるのにtimesのところまで読みにいかないと確定しない。

for X N times
	sum += i;

違う。こんなことがしたいんじゃない。ちなみに、VC++ソース入力することが前提なら、次のようにforの直後に"("を持ってきて、普通のfor文に見せかけてインテリセンスを騙すテクニックが考えられる。

	for(i in e)
		sum += i;

この場合、"sum += i"の部分を入力しているときに正しくインテリセンスが機能する。ここを"foreach"にしてしまうとインテリセンスは騙せない。いや、ちょっと待てよ。ダミーのforeachをdefineで定義しておけばインテリセンスを騙せるなぁ。

// ダミーのforeach
#define foreach(X)

どうせインテリセンスを騙すつもりならYaneCの文法をC#と文法をコンパチにしてしまう方法も考えられる。そうすればReSharperのような強力な開発支援ツールが使える。


しかし、C#だとtypedefやCのdefineのようなマクロが使えなくて、私の開発しているプログラムではC#の文法に準拠させるにはかなり追加コストがかかるのだ。それはとりあえずは避けたい。


やはりVC++インテリセンスを騙せる範囲で拡張記法を考えるのがよろしい。PASCAL風に':'を導入してはどうか。

	for(i:10 times)
		sum += i;

これは読みやすいだろうか?またこの場合、多重ループは次のようになる。

	for(i:10times,j:5times,k:3..5)
		sum += i*j*k;

あとはC#のようにユーザー定義型に対してもfor(foreach)を定義できるようにしたい。しかしこのとき":"だとPASCALの型宣言のようでforeachっぽくない。

for(sq:uservar)
	target&=mask[sq];

やはり、次のように書かれているほうが私としては読みやすい。

for(sq in uservar)
	target&=mask[sq];

ここまで書いてきてから言うのも何だが、これなら、Cで普通にforeach_XXXをdefineして、次のように書けばいいんじゃないかと言う話になる。読みやすさで言えばさほど変わらない。末尾の"});"が気になるだけの話だ。

foreach_XXX(sq,uservar,{
	target&=mask[sq];
});

スタート地点に戻ってしまった。何をやっているのかさっぱりわからない。


そんなわけで、美しい回数ループ記法を求む!


・回数ループが美しく書ける

・回数ループループ変数がわかりやすく表記できる

・読みやすいforeach構文

・多重foreachが簡潔に書ける

インテリセンスを騙せる


以上の条件をある程度満たすものが望まれる。コメント欄でお願いします(´ω`)人

nn 2009/12/02 06:58 D言語と同じで良いような
foreach(x; vect) sum+=x;
foreach(i; 0..10) sum+=i;
foreach(sq; uservar) target&=mask[sq];
インテリセンス的な問題があるかも?

hogehoge 2009/12/02 07:03 Ruby っぽくいくなら 0...N で N を含まない範囲 [0,N) を作ればええんでないの

yaneuraoyaneurao 2009/12/02 07:07 > インテリセンス的な問題があるかも?

foreachのあと"("があり、")"まではインテリセンスは読み飛ばしますので、")"以降は正しくインテリセンスが機能します。

私は、N回まわるときに、0..N-1 の "-1"がすごく嫌なんです。

> Ruby っぽくいくなら 0...N で N を含まない範囲 [0,N) を作ればええんでないの

はい。[0,N) をうまく書く表記があれば良いのですが、"("と対応していない ")" がインテリセンスを阻害するので、これはまずいのです。

全角文字を投入して、"【0,N》"とかする方法も無くはないのですが、タイプしにくさから少し敬遠しています。

satoru_hsatoru_h 2009/12/02 07:27 N回まわるときは0..Nですよね?>D言語。

yaneuraoyaneurao 2009/12/02 07:44 ↑あっ、そうですね。D言語では、A..B だとB-A回ループを回るんですね。なんか紛らわしいですなぁ・・(´ω`)

でも慣れれば0..NでN回まわるのは結構いいような気はします。私はPASCALの部分範囲型とかすごく好きなので。

matarillomatarillo 2009/12/02 09:01 「rubyっぽくいくなら」と上の人が書いてるのは、rubyだとピリオド2つで閉区間、ピリオド3つで左閉右開区間だからです。つまり「ピリオド3つで、0...Nと書けるようにすればええんでないの」という意味でしょう。

yaneuraoyaneurao 2009/12/02 09:06 > rubyだとピリオド2つで閉区間、ピリオド3つで左閉右開区間だからです

うわ!知らなかった。そうなんですか。それはとても面白い記法ですね。目の悪い私は「..」の数を見誤りそうなので採用はしませんけど..。

kanokekanoke 2009/12/02 09:27 for(0<=i<N)
とか駄目ですかね?

yaneuraoyaneurao 2009/12/02 09:39 ↑ "i<N"の部分とかがbool型に見えてしまい、X<Nなら3回、さもなくば5回まわるループを書こうと思ったときに、for(0<=i<X<N?3:5) のようになって、これきちんとparseできるようにするのはちょっと大変でございます(´ω`)

Spring 88Spring 88 2009/12/02 09:44 >> いまさらC/C++なんか使いたくない。
おじさんほんき?
いまさらC/C++(の記法)なんか使いたくない。
の意味ですよね?

わたし、foreach なんかいらない。C/C++ のfor() で十分!
めんどうくさくfor()を書いているようでも、その間、気分が休まるので。

yaneuraoyaneurao 2009/12/02 09:56 > いまさらC/C++(の記法)なんか使いたくない。

いや、できればC/C++ともおさらばしたいんですけど、おさらば出来ないなら出来ないで、見えないところにC/C++が居てくれればそれでいいんですけど。

> その間、気分が休まるので。

私は開発は撮りためてあったテレビドラマを見ながらやってます。気分的にはずっと休まってます。

さすがにプログラムを30年以上やっていれば手を動かしているだけでぼけーっとしててもプログラムは完成します。どうせ手を動かしているだけでいいなら、動かす手の量は極力少ないほうが腱鞘炎にならなくていいよね、という。

ufcppufcpp 2009/12/02 11:35 集合論的にみると 10 = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 } なので、in 10 って表記は別におかしくないと思います。

yaneuraoyaneurao 2009/12/02 11:46 ↑あっ、そうですか..。それならfor(i in 10)でよければ表記的にはすっきりしますね。10回ループならfor(10)とか。間違えてwhile(10)と入力して永久ループになったりして(´ω`)

valpvalp 2009/12/02 11:54 VC++限定で良ければ、本文中のfor(sq in uservar)に近い構文、for each (type t in v)のようなfor each構文が使えます(vはvector<int>などbegin/endメンバ関数を持つオブジェクト)。
http://msdn.microsoft.com/en-us/library/ms177203.aspx
それはさておき、本文中の案では、ループ変数と回数の指定をすべて括弧の中に書くか、括弧が登場しないかのどちらかだけのようですが、for i in (0, N)またはfor 0, N (int i)のようにどちらかだけ括弧の中に入れるというのはどうでしょう?

yaneuraoyaneurao 2009/12/02 12:04 > 、for i in (0, N)またはfor 0, N (int i)のようにどちらかだけ括弧の中に入れるというのはどうでしょう?

それは、見た目、なかなか美しいですね。
左閉区間右開区間は意外とよいような気がしてきました。

p95095yyp95095yy 2009/12/02 12:09 トランスレーターは、コンパイルエラーが出たときに大変ではないですか?
あまりないかもしれませんが。

yaneuraoyaneurao 2009/12/02 12:29 単純なトランスレーターではなく意味論的なチェックも行なうので、まあたいていは変換時にエラーが出ます。

やむなく変換後にエラーが出た場合は、ソースファイル名とソース行を変換後の各行に埋め込んでおいて、Visual Studioのマクロか何かでそこから変換元ファイルの該当行にタグジャンプできるようにしようと思ってます。(まだそこまで出来てませんが)

p95095yyp95095yy 2009/12/02 13:14 トランスレーターがコンパイルエラー相当(トランスレートエラー?)をサポートするわけですね。YaneCはより賢いトランスレータというわけですね。

ss 2009/12/02 16:50 あまり知られていませんが、VisualStudio2005以降なら(マネージドでない普通の)C++でも普通にfor each使えますよ。MSが用意してるのじゃだめですか?

例:
vector<int> v;
v.push_back(1);
v.push_back(2);

for each(int item in v){
item++;
}

yaneuraoyaneurao 2009/12/03 06:37 ↑*1は、↑*6で既出でございます。

それはそうと、foreachしたいのはclass / structとは限らず、普通にtypedefした型や、enumなんかに対してもforeachが使いたいというのと、定数回のループをもっと簡潔に書けないかなというのがあるので"for each"では少し物足りないのです。

hogehoge 2009/12/03 19:15 色々心配してる人はまあ #line とか知らないんでしょうな。確かにマイナーだけども。

aoisomeaoisome 2009/12/03 19:17 C++のparserを一日で書いてしまうなんて凄すぎます!
手書きのparserなんですか?アルゴリズムは何を使ってるんですか?
何かのライブラリやツールを使っているのでしょうか?
どうしたらそんなに速く組めるのか教えてください。

yaneuraoyaneurao 2009/12/03 21:38 > 手書きのparserなんですか?アルゴリズムは何を使ってるんですか?

完全に手書きの普通の再帰下降型parserでございます。C#で書くと開発効率が良くて、まあ、tokenを切り出す部分と、構文解析する部分ぐらいまでは1日あれば十分書けます。そこまででソース行数は1500行程度です。

慣れていれば、4時間ぐらいで書けるのでしょうけど、私はそこまで慣れてないです(´ω`)

aoisomeaoisome 2009/12/03 23:05 それぐらいコーディングが速いから「無ければ作ればいいや」っていう発想になるんでしょうねー
私の速度ではそんな発想にならないです。

MMXMMX 2009/12/05 11:30 Google の開発中の言語 Go では slice や range のほうに 振り分けて for 構文は Cのまま、言語の設計はバランスらしい。
Matz日記
http://www.rubyist.net/~matz/20091113.html

variantvariant 2009/12/10 20:49 parser無駄になるけど、
BOOST_FOREACHマクロ使って、回数ループは"Range"のコンセプトを満たして、1〜Nを返すような関数オブジェクトを使うとかはダメ?

yaneuraoyaneurao 2009/12/10 21:34 ↑まあ、普通(?)、boost使いならそうしますよね。

私、boostのRangeの細かいところまで見ていないのですが、Rangeはbeginとかendとか定義できないといけないような?

例えば、いま私がやりたいのは、uint型の整数のbitが1のところだけforeachで回したいのですが、これを事前にend()を求めるためには、1であるbitを数える(ex.Popucount)必要があって、これを事前にやりたくないのです。

1であるbitは、下位からなら、x &= x -1 みたいな形で自然な形で除去できるのでループ終了判定はなりゆきまかせにしたいのです。

↑boostのRangeの実装よく見てないので見当違いならすみません。

ただまあ、こういうところに頭を悩ませるぐらいなら、最初から単にdefineでforeach_XXXを定義してしまって、それを使うだとか、自分で簡単なコンパイラを書いたほうがまだすっきりするなぁというのが私の考えです。

名無し名無し 2009/12/23 06:27 http://image.blog.livedoor.jp/zonkichi180/imgs/9/a/9a56706c.jpg
これ思い出した

yaneuraoyaneurao 2009/12/23 06:41 ↑あ、まさにそんな感じだ!!

通りすがり通りすがり 2010/02/05 06:35 foreach_XXX(sq,uservar){ target&=mask[sq]; }
なら define できそうだけど、どうかな。

#define foreach(T, i, d) for(T i=(d).begin();i!=(d).end();++i)
みたいな。多重もできそう。

takano32takano32 2010/03/07 08:45 0..^n

トラックバック - http://d.hatena.ne.jp/yaneurao/20091202
 | 

1900 | 01 |
2004 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2005 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2006 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2007 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2008 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2009 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2010 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2011 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2012 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2013 | 01 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2014 | 01 | 02 | 03 | 04 | 06 | 08 | 10 | 11 | 12 |
2015 | 01 | 02 |


Microsoft MVP
Microsoft MVP Visual C# 2006.07-2011.06