goo blog サービス終了のお知らせ 

惰天使ロック

原理的にはまったく自在な素人哲学

CドライブにインストールしたソフトをDドライブに移動する

2011年11月20日 | 不良プログラマの夕べに
blogの更新もしないで何をやっておるのだ、と思っている閲覧者はいないだろうが、いたとしたら題名の通りの作業をやっていたのである、と答えよう。念のため言うが「アンインストール/再インストールせずに、使用可能な状態を保ったままで」である。フリーソフトのようなものならともかく、市販のアプリケーション・ソフトの場合、そういうことは普通はできない。無理矢理「ファイル移動」などで移動するとアプリケーション自体が正常に動作しなくなってしまうことが多い。

とはいえ、Cドライブの容量が足りなくなってくると、HDDなりSSDなりを増設して、Cドライブ上のファイルを移動するわけである。その場合も基本的にはデータファイルを移動するのだが、それで済むような段階はとっくに過ぎてしまっていて、動かせるのは(それが可能なら)「Program Files」以下のアプリケーションしかない、ということも珍しくはないものである。

わがThinkPadの状況がまさにそれで、少々古いX61tであるためHDD容量が80Gしかなく、そこにOfficeはもちろん、「他人様の絵」加工用のグラフィックツールやら、VisualStudioのフルセットやら各種SDK(開発用キット)やら何やらをどかどか放り込んであるわけである。色々工夫して容量をやりくりしてはきたのだが、週末にOffice2007とVisualStudio2010の新しいサービスパックを入れたら、ついにどうやっても残り容量が10Gに届かなくなってしまった。これは何とかしたいなあ、というので色々調べていると、実は奥の手があることがわかった。

正確に言うと「奥の手」が存在すること自体は知っていた。Windowsの現在の標準のファイルシステムであるNTFSには「ジャンクション」と言って、わかりやすく言えば「どこでもドア」機能がついているのである。ファイルのアイコンはその中身を覗くためのドアのようなものだと思ってもらえば、そのドアを「どこでもドア」にして、開けた先をどこでも好きな場所に設定することができる。これを使えば「Program Files」以下のアプリケーションだろうと何だろうと自由自在に置き場所を変更できる。システムの方はドアが「どこでもドア」であるかどうかを区別しないので、移動したファイルがあたかももとの場所にあるかのようにアクセスする。理屈の上ではそうなる。理屈の上では、である。

そんな便利な機能があるのに普通は使われていない(少なくともWindowsは正式にはサポートしていない)のには理由がある。ドラえもんの便利な道具がたいていそうであるように、このNTFSの「どこでもドア」も不用意に使うと思わぬトラブルを引き起こす原因になりやすいのである。詳細は省くが、手作業でやるとどこかで手違いをやらかしてひどいことになりそうな予感がぷんぷんするので、できるだけやらない方がいい、という判断が成り立つような何かなのである。

だからこれを安全に実行してくれるツールがどこかにないかな、と探していたわけであるが、探したらあった。それが今回使用した「SteamMover」※である。


(リンクと画像は「lifehacker」様)

なんでも、これは本来「Steam」というネトゲのアイテムか何かのファイルを、上述の「ジャンクション」を利用して再配置するためのツールとして作られたものらしい。本来の目的はそうだが、使っている手段は普遍的なものなので、何にでも使えるわけである。

上のリンク(※)はSteamMover開発者の(つまり入手先の)サイトで、英語である。日本語で使い方のあらましを説明しているサイトを以下に掲げておく。上の画像も以下から拝借したものである。

lifehacker/『Steam Mover』はアプリを移動させ、プライマリドライブの空きスペースを増やしてくれる便利ツール

このサイトに書かれていないことで、使用上の注意点をふたつ書いておく。

(1) 特に「Program Files」上のフォルダを再配置する場合、このツール・プログラムは必ず「管理者として実行...」しなければならない。
(2) 移動元のCドライブも、再配置先のドライブも、両方ともNTFSでフォーマットされていなければならない。

まあ、どちらも当たり前のことであるが、詳しくない人はうっかりしそうなことである。

いずれにせよ上記のサイトの説明を読んでも、この記事を読んでも、何が何やらサッパリ判らぬという人は手を出さない方が吉である、と念を押しておく。わたし自身も現時点では重要なアプリケーションをこれで再配置はしていない。万が一のことがあってもギリギリ諦めがつくようなもの──めったに使わないDirectXのSDKとか──だけを再配置している。それでもあれやこれやで移動して5GBくらいは容量を稼ぐことができた。まずはひと安心である。

  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

高速goto入門(1) ─プログラム成形物語─

2011年08月13日 | 不良プログラマの夕べに
C#で1メソッド8000行を書いたツワモノがいるらしい。レガシーコード改善だっ!
(nnasaki)

@nnasaki 書きたくて書いたんじゃなくて、上からの命令で書いたんじゃねぇの?Cの時代でも似たような話聞いたことあるわ。オブジェクトがどうこう以前に、一つに書くのが哲学って奴いるしな。ちなみにVb6は制限のためそんなに書くと怒られます。
(uyat_)

黙ってるとすぐ長くなるC#でも8000行はすげえな。よくそんなもの間違わずに書けるもんだ。若さだよなあ。

近頃はそういう話になるとすぐ上の呟きみたいなこと言うやつがいるわけだが、俺なら直ちにそんなことは言わない。どうしてもそうなるということはありうる。たとえば字句解析や構文解析を手書きで書いてるような場合なんかは、どうしたってひとつの関数(メソッド)がswitch文の多重ネストになったりするわけで、そういうのを一気呵成に書いたりすると関数ひとつが数千行なんていうのは簡単に出来上がることがあるわけだ。しかもそういうのに限って関数を分割するのは必ずしも可読性の向上につながらないことがある。

プログラムなんていうのは所詮人の書くものだ。コードのよしあしということは、原則は原則としてモノは何だという具体性から柔軟に判断しなければならない。本当はな。そうは言っても近頃では上に立ってるやつでもプログラマとしてはそんなにたいした経験を持ってなかったりして、何かっつーと杓子定規の規則ばかり作りたがるのが多いわけなんだ。「goto文は絶対禁止」「絶対?なんでだよ。そんなのは原則でいいんだ。絶対なんて軽々しく言うな」「××の本にこう書いてあるから禁止だ」「その本書いてんのは大学教師でプログラマじゃねえよ」「いいから禁止だ」うぜぇ、と思いつつgoto文をdo~while(0)breakで置換したりしてな。プログラムの意味を変えずに見た目上gotoを消す定番のひとつだ。アホかっつーの。



副題にくっつけたのは若いころ読んだ「プラスチック成形物語」のパロディだ。プラスチック成形加工の職人技と、折からのTQC金科玉条主義の対立のドラマとでも言ったらいい本で、縁もユカリもない分野の本ながら楽しく読んだものだった。

プラスチック成形物語
鳴滝 朋
シグマ出版
Amazon

・・・ってAmazonにあったよ。古本なのに画像までついてたぞ。

  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

変形Whitesmithインデント(2)

2011年06月27日 | 不良プログラマの夕べに
考えてみると、「夕べに」というなら最初にこっちの曲を掲げてしかるべきであった。

from YouTube

この曲は邦題も「イン・ジ・イヴニング」で知られているわけで、訳せば「夕べに」であることに今まで気づいていなかった。まあ、ワタシはこの曲にはあんまり思い入れがないのである。



プログラマにとってインデント・スタイルというのは利き手の左右にも等しいもので、違うスタイルで書かれたプログラムは読むのも書くのも難儀をきわめるものである。またまさしく箸の握り方にも等しいものだから、どういうスタイルであろうとそれほど凝ったものにはなるわけもない。箸でシャーペン回ししながらでないとメシが食えないとか、そんな人はいないわけである。

そうは言ってもたぶん、実際に日常的にこんな書き方をしている人は、世界広しといえどもわたしのほかにはあんまりいないだろう、という「変形」Whitesmithの変形たるゆえんのひとつが以下のswitch文の書法である。

switch(p->input_datatype)
        {
case DOUBLE_POWER:
        for(i = 0; i < p->samples; i++)
                { p->s[i].db = line[i]; }
        break;
case FLOAT_POWER:
        fline = (float *)line;
        for(i = 0; i < p->samples; i++)
                { p->s[i].db = (double)fline[i]; }
        break;
case DOUBLE_LINEAR:
        for(i = 0; i < p->samples; i++)
                { p->s[i].db = log10(line[i])*20.0; }
        break;
case FLOAT_LINEAR:
        fline = (float *)line;
        for(i = 0; i < p->samples; i++)
                { p->s[i].db = log10((double)fline[i])*20.0; }
        break;
case COMPLEX:
        cline = (complex *)line;
        for(i = 0; i < p->samples; i++)
                { p->s[i].db = log10(ZSQ(cline[i]))*20.0; }
        break;
        }

caseを中括弧より一段前に書く」という掟破りのインデントである。

わたしはもともと他人にコードを読ませる気がない(そもそも他人の書いたコードを読みたいなんて奴がいるわけがない。そして文章であれプログラムであれ、読みたいと思わない奴に読ませることほど悪い行為はめったにない)のだが、仕方なく読ませなければならないことはたまにあって、そうすると百発百中で相手が面喰らうのがこれである。その顔を眺めて「だから言っただろ?俺のコードなんか見ないで自分で自分のコードを書け」と言うのがわたしである。

どうしてこんな面妖なスタイルが生じたのかというと、C言語を覚えた時からこのswitch文というのが無駄にインデントを食うものであることが気に食わなかったわけである。昔のPCは1行80文字程度しかなかったから、ハードタブでインデントしているとすぐに1行の端まで到達してしまう。通常のスタイルではswitch文が入れ子になったりすると、いったいどんな風に書いても判りにくい代物になってしまう。なんとかなんないものかと考えあぐねているうち、このcaseというのはgotoラベルと同じようなものだということに気がついた。だったらラベルと同じように一段前にしてしまえば、switch文のせいでインデントが爆発することは、なくなりはしないまでも減るのではないかと思って意識的にそう書くようになったのである。果たして見違えるようにスッキリするようになった。以後どんな言語でもこのスタイルで通すようになったのである。

  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

変形Whitesmithインデント(1)

2011年06月25日 | 不良プログラマの夕べに
突発的に思いついてカテゴリ題を変えてみた。例によって「~の夕べに」って、いっぺん使ってみたかっただけだということもなくはない。

まあせっかくだから柄にもない動画を貼ってみる。深夜だしー

from YouTube

で、「不良プログラマ」というのはほかでもない、わたしは職業プログラマだが、他人の決めた規則は基本的にも原則的にも実際的にも全部破るというのがポリシーのようになってしまっているところがある。別にそうしようと思ってそうしているというよりも、昔はそんなバカみたいな規則でプログラマの手が縛られるなんてことはなかったのだが、気がつくと規則だらけになっていて、わたしのような古株は黙ってても不良扱いになってしまっているわけである。

せっかくだからその不良の流儀を紹介して行くことにした。まずはインデント・スタイルからで、題名通りのことである。Whitesmithスタイルというのは、たとえばfor文ならこんな風になる。

for(i = 0; i < n; i++)
        {
        printf("%d\n",i);
        }

「ブロックの中括弧は行送りした上でナカミとインデント・レベルを合わせる」のが基本である。この方法の何がいいかというと、C言語はともかくPASCAL/Delphiのようにブロックをbegin/endで括るような言語でも、インデントのつけ間違いをしでかすことはまずないということである。プログラマは、たとえばエディタが「メモ帳」しかないところでプログラムを書かなければならない場合もある。つまり気のきいたインデント・チェッカも何もない環境でも、このスタイルなら耐えられるのである。

そういうところに根拠のあるスタイルなので、タブは当然ハードタブで8文字である。DOS窓でタブを打たせてみればわかる通り、ターミナルのハードタブは普通8文字なのである。設定で変更できる場合もあるができない端末だってあるわけである。

  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

近況

2011年06月23日 | 不良プログラマの夕べに
このぶんだとTHNの私訳はいったいいつまで続けることになるのだろうという気が、我ながらしているところだが、この超気長なプロジェクトを細々やっていることが全然別の方向でいい作用を及ぼしていたりする。

時々書いてることだが、わたしは本来途轍もなく飽きっぽい性質なので、こんな地味なことを何か月も何年も続けてやったことがほとんどないわけである。それがわかっているからMSWの私訳のときは非常に急いだりしたわけである。

いい作用というのはほかでもない、プログラミングの私的プロジェクトの方も、実はTHNの私訳と同じくらい長丁場になりそうだということが、やってるうちに明らかになってきた。今までならそれだけで目を回して放棄してしまうところなのだが、同じように長丁場になるのが判りきったTHN私訳をすでにやっていることで、すでにある長丁場がもうひとつ増えるだけだという程度には気分が楽になっているわけなのである。

今は逆ポーランド言語の方は一時中断して表計算風のユーザ・インターフェースの設計と製造に集中している。これは最終的には「一風変わった表計算ソフトのようなもの」になる予定だが、まずはその部品として「汎用スプレッドシート・コントロール」を作ろうとしているわけである。VisualBasicのGridコントロールとか、最近の.NETについてるDataGridViewとか、それ風のコントロールは有料無料のものがいろいろあるわけだが、ずばり表計算なコントロールというのは案外ないのである。ないこともないが、有料のものはバカみたいに高価だし、無料のものは、なるほどこれは無料だなというクオリティである。

仕事だとだいたいはDataGridViewやPropertyGridを工夫して使うことが多いわけだが、プロにはプロの見切りということがあって、とことん出来栄えにこだわってモノ作りをするということは、ご時世ということもあってまずそんな機会がない。何か提案しても予算が試験が工程表がと言って却下されるか、却下される以前に露骨に嫌な顔されるから言い出す気にもならないということが、日ごとに多くなっているわけである。そういうものは、だから私的に勝手にタダ働きして作ってしまえということに、結局なるわけである。

表計算コントロールというのは、これまでにも何度か作ろうと思って手をつけては放棄してきたネタのひとつである。そんなに複雑なものではないのだが、本気を出せば出すほど無限に複雑になってくるようなところがある。

普通だったら、たとえばスクロールバーのコントロールを自前で作り直すなんてことはしないわけである。だが、これに限ってやりたくなるのだから困る。結局表計算ソフトというのはPCの華だからなのだろう、と思う。Excelを起動してスクロールバーを眺めてみればわかると思うが、ExcelのスクロールバーもWindowsの標準コントロールとは違う、ほとんど独自に新たに設計製造したらしきものなのである。なんでわざわざ、と言って、はっきり言って単に画面構成のデザイン的な統一感のためだけだとしか思えないのだが、それなら色と形が違うだけかというと、実はそうでもない、なんでまあこんなことにと思うくらい細かいところで変に凝った作りにもなっているわけである(詳細に調べてみて初めてわかる、意外な手抜きとか、バグ潰しの跡とかも見つかったりする)。

  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

アタマにきた

2011年06月21日 | 不良プログラマの夕べに
THNの私訳の今日分は後で出てくる。とりあえず今日の作業でアタマにきたことがあったのでそれを書く。

.NETが本職の人にとっては常識なのかもしれないが、昔気質なわたしは今日、フォームのサーフェスの上でラスタオペレーションをやるようなコードを書こうとしたわけである。そしたらいくら探してもGraphicsクラスの描画関数にそれらしいものがない。そんなバカなと思って調べたら本当にないらしい。

クソが、と思ってC#から直接APIのSetROP2を叩き、これでなんとかなんだろと思って実行したら、どうしたことか設定したラスタオペレーションがキャンセルされてしまう。どうもわざわざキャンセルしているとしか思えない。例外的にラバーバンド的なものを描くだけの関数なら別のクラスで用意されていたりするからだ。

ラスタオペレーションというのは古い方法だと言えば古い方法ではあるわけだが、Excel2010なんかでも使われているし、Windowsフォームのコントロールの中でも使われている、プログラマにとってもユーザにとっても現役の描画技法である。これを「わざわざ使えなくしている」のは最低だと言わざるを得ない。

本格的にどうにかするとしたらGraphicsクラスから派生させて・・・と思ったりしたが、このGraphicsクラスというのがこれまた「わざわざ継承できなくしてある」のである。結局、必要な部分は全部API呼び出しの形に書きかえなければならなくなった。・・・もう、どこまでも最低な作りである。.NETで何かちょっとしたことをやろうとすると何でもこんな調子である。設計だテストだと称して変なツールを陸続と作ってみせることにはやたら熱心なくせに、実際的なコードを書くことについてはのべつこんな非生産的な仕様に煩わされる。.NETの設計チームはいっぺんと言わず千万回氏んで来い!

  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

続・CからC#を呼ぶ

2011年06月10日 | 不良プログラマの夕べに
今日は出勤前に話が解決した(笑)。

昨日のサンプルは「C#からC関数を呼び、その中からC#メソッドを関数として呼び返す」ものだった。つまりこの例だとEXE自体はC#で作っていなければならなかったわけである。

そうではなくてCのEXEから直接C#のDLLにアクセスする場合はどうするか。これはCの側のメイン・プログラムをC++/CLIで作ってやって、そのusing文の中でC#モジュールを指定してやる。C++/CLI自体は「C++のニセモノ」あるいは「文法その他をC++のそれに似せたC#」とでもいうべきもので、CでもC++でもない。ただ、その中からC言語の関数を呼ぶことは普通にできるし、Cで作ったobjファイルをリンクしてひとつのexe(ないしdll)にすることもできる。

注意すべき点はCのソースファイルをC++/CLIのプロジェクトに含める場合、ソースファイルのプロパティ画面で「共通言語ランタイム サポートを使用しない」「プリコンパイル済みヘッダーを使用しない」のふたつを設定しなければならないことである。

  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

真・CからC#を呼ぶ方法

2011年06月09日 | 不良プログラマの夕べに
我ながらバカらしくなってきた。昨日のをうpしてから「そんなわけはない」的に再度調べ直していたら、冗談じゃない、まったく素直で簡単な方法がやはりあったのである。

昨日のコードの上にbutton2を追加したと思ってもらいたい。さらにC#のコードに以下を追加する(以下は必要な部分のみ)。

using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace call_csharp_method_from_c_function
{
public partial class form: Form
{
public form() { InitializeComponent(); }

public delegate int func(int a,int b);

public static void one()
{
MessageBox.Show("what?");
}

public static int two(int a,int b)
{
return 2*a+3*b;
}

[DllImport("cmodule.dll")]
public static extern int cmodule_exec2(IntPtr p);

[DllImport("cmodule.dll")]
public static extern int cmodule_exec3(IntPtr p);

public void button2_click(object sender,EventArgs e)
{
MethodInvoker mi = one;
func mi2 = two;
IntPtr p = Marshal.GetFunctionPointerForDelegate(mi);
cmodule_exec2(p);
p = Marshal.GetFunctionPointerForDelegate(mi2);
cmodule_exec3(p);
}

} // end of class
} // end of namespace

Cのソースとヘッダにはそれぞれ以下のような内容を追加する(同じく必要な部分のみ)。
・ヘッダ

#ifndef _CMODULE_H_
#define _CMODULE_H_

#ifdef CMODULE_EXPORTS
#define CMODULE __declspec(dllexport)
#else
#define CMODULE __declspec(dllimport)
#endif

(中略)

typedef void (__stdcall *voidfunc)(void);
typedef int (__stdcall *binaryfunc)(int a,int b);

// function prototypes
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus

CMODULE int __stdcall cmodule_exec2(voidfunc f);
CMODULE int __stdcall cmodule_exec3(binaryfunc f);

#ifdef __cplusplus
}
#endif // __cplusplus

#endif // _CMODULE_H_


・ソース

#include "cmodule.h"

CMODULE int __stdcall cmodule_exec2(voidfunc f)
{
f();
return 0;
}

CMODULE int __stdcall cmodule_exec3(binaryfunc f)
{
printf("f(1,2) = %d\n",f(1,2));
return 0;
}

せっかく作ったインデントつきタグ付けプログラムがいらないくらい単純である。これを実行してbutton2を押せば、最初に「what?」というメッセージボックスが表示され、そのOKボタンを押すと続けてDOS窓に

f(1,2) = 8

が表示される。まったく何の懸念も問題もない。結論を特筆大書しておこう。C#メソッドは普通にCから呼び出せるのである。唯一注意すべきことがあるとすれば、Marshal.GetFunctionPointerForDelegateで得られる関数ポインタを使ってC側から呼び出す際は「__stdcall」修飾子が必須だということである(上のふたつのtypedefの記述にあるのがそれである。もっとも、最初のパラメタなし関数はそれなしでも動く。またこれらのことはVisualStudioのヘルプにも──かなりひどい日本語だが──書かれている)。

上の例もパラメタや戻り値は整数だが、この方法ならもっと複雑なパラメタや戻り値をもつことも簡単にできる。Cから呼ばれることがわかっている関数なら、複雑な構造体はアンマネージ領域のポインタをIntPtrで受け取り、関数の中で明示的にマーシャリングして使えばいい。戻り値や副作用も同様である。そうでないC#関数はラッパーを用意してその中でマーシャリングした上で本体を呼び出せばよい。

こんな素直で単純で、しかも確実な方法があることに今まで気づかなかったというのは、まったく我ながらマヌケもいいところだった、ということにはなる。マヌケという点については言い訳はしないでおこう。事実マヌケだとしか言いようがない。「素振り」の比喩で言えば、外人投手を相手にするときはバットを逆さに持って振らなければならないと思い込んでいたようなものである。

とはいえ、おそらくはわたしと同程度のマヌケが、少なくとも日本にはたくさんいるはずだということも間違いなさそうである。C#とC(もしくはC++)の相互運用なんて仕事でさんざんやっているわけだが、過去にわたしが仕事でかかわった誰ひとりとしてこのことに言及した人間はいなかったわけである(そもそもmarshalないしmarshalingという単語の意味から説明してかからなくてはならないことの方が多い、というか、してもほとんど誰ひとり理解した顔をしない)。

  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

CからC#を呼ぶ方法(一部削除・抹消)

2011年06月08日 | 不良プログラマの夕べに
普段はあんまりやらないのだが、いずれ必要になるかなと思って題名の方法について調べたら、ググってもろくな情報が出て来ないことに気づいた。結構需要はあるらしく(Cで書かれたコード資産の膨大さを考えれば当然だ)、あっちこっちの掲示板でネタに上がっているのだが、一向にまともな回答がなされていないわけである。挙句の果てに「そんなことはできない」などと回答者が無能をさらけ出していたり、あるいは「COMモデルがどうのこうの」と仰々しい話に(例示されているコードがまた、おどろおどろしい)オチていたりする。

しまいにバカらしくなって自分で作ってみたら、結構簡単にできてしまったので紹介しよう。

ポイントは「CからC#を呼び出す」ということの字義にこだわらないことである。もともとC#の方がそういう風にできていない(実に愚かな設計だ!)のだから、直接呼び出すのには無理があるのである。じゃあどうするか。普通誰でもこうするだろうという方法のひとつは、C#からC関数(DLL)を呼び出すことはいたって簡単にできる(そうでないとWindowsのAPIとか呼び出せないから、この機能は必須なのである)わけである。ならば、呼び出し関係を裏返しに使って、あたかもCからC#を呼び出しているかのような(実際にはC#がC関数を呼び出している)格好を作ってしまえばいいのである。

(以降ソースと説明は削除。6月9日の「真」の方を参照されたい)

以上はせいぜい整数型のパラメタ/戻り値の受け渡しをやってるだけだが、適当に手を加えればどんな複雑な構造でも受け渡しすることは可能になるはずである。ただC#の方はマーシャリングといって大きなデータは素直に渡ってくれない(わざわざマネージ領域からアンマネージ領域に、あるいは逆に、データをコピーするわけである。ああ愚かしい)。そのオーバヘッドが嫌だ、という場合は.net 4.0で導入されたメモリマップトファイルを使ってデータの受け渡しをするという方法も考えられる。

こんなのを自分で作れるのに何で最初はググって調べていたのかって、それはもちろん、もっと素直で簡単な方法があるに違いないと思ったから調べていたのである。上の方法は簡単ではあるが、それでもトリッキーな方法には違いないわけで、ここ一番これしかないという時でなければあまり使いたくない方法である。(以降削除)

  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

ちょっと工作

2011年06月07日 | 不良プログラマの夕べに
このカテゴリを新設して、今後は文章内にコードを書く機会が増えるだろうと思って、ちょっとした工作をした。要は下みたいなコードのタグつけをワンタッチでやってくれるプログラムを作ってみたわけだ。この記事はそのテストを兼ねている。

for(int i = 0; i < 100; i++)
        {
        printf("[%d] %f,%f",i,buf[i].r,buf[i].i);
        z.r = z.i = 0.0;
        for(int j = -half; j <= half; j++)
                {
                z.r += buf[i+j].r*rot.r-buf[i+j].i*rot.i;
                z.i += buf[i+j].r*rot.i+buf[i+j].i*rot.r;
                }
        printf(" - %f,%f\n",z.r,z.i);
        }

・・・若干改良の余地はあるけれど、まあ、とりあえずはこんなもんだろう。ちなみに、上のコードに意味はないのであしからず。

●(追記)
というわけで早速改良した。最初のバージョンは行間が広過ぎたので少し狭くした。

それはそうと、このタグつけをやってうpした後で編集画面に戻るとタグが壊されてしまうことが判明した。記事を直打ちすると後から直せなくなってしまうというわけである。まったくちょぼくさい編集画面だ。

  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

Expressionクラスの逆ポーランド拡大(1)

2011年06月05日 | 不良プログラマの夕べに
いやー、冷房を入れたとたん筆が、いやキーボードが進む進む(笑)。

このblogは本来素人哲学のblogだから、眺めに来る人というのは大方そっちの方に関心があるのかもしれない。そうだとすると、そもそも「逆ポーランド」とは何のことかと思っているに違いない気がする。

そんなもんググればいくらでも判るじゃないか、ということにはなるのだが、「1+2」を「1 2 +」と書くことにどんな利得があるのかということは、そんなに簡単にはわからないことかもしれない。

昔だったらMindというプログラミング言語の話をすればいいというところがあった。Mindは日本語プログラミング言語で、数式を日本語で「1と2を足す」などと書くことができた(昔の記憶なので、実際は微妙に違ったかもしれない)。言語の文法が基本的に逆ポーランドで、そこにちょっと足し前することで、比較的自然な日本語のそれに近い形でプログラムを記述できるようになっていたわけである。

もちろん今はMindというプログラミング言語は、実質的に言って影も形もなくなっているに等しい。第一、当時だってかくべつ流行ったわけではなかった。一部に熱狂的な支持者というかユーザが、ちらほらといただけである。今も覚えているのは、わたしのようなこの界隈の古株くらいのものであるはずだ。

日本語でプログラムが書けるというのは決しておかしなアイデアではなかったし、プログラミング言語処理系としてとてもよくできた製品だったことは間違いない。でも残念ながらプログラミングという作業にとってはたぶん、それはそれほど本質的なことではなかったのである。それはどうしてなのか、プログラミングという作業にとって何が本質的なことであるのか、たとえば日本人が日本語でプログラムを書くことはどうしてそれほど本質的なことではない(現になかった)のか、そうしたことの研究や論文はあるのかもしれないが、わたしは読んだことはない──というか、包括的な形ではあるわけがないと勝手に思い込んでいる。計算機科学に関してはわが師匠も同然で、尊敬している木村泉大先生の弟子筋とかで、その手の研究というか考察の後を継いだ人がいればいいのだが、たぶんいないんだろうなあ、と。

そういうわけでまあ、逆ポーランド記法なら「日本語の語順に近い」という話は、今ではしてもあんまり効き目がなさそうである。では何がいいのか。一番簡単に言えば逆ポーランド記法は構文それ自体が線形だということである。通常の記法で「(1+2)*3」は逆ポーランドなら「1 2 + 3 *」と書く。カッコがいらない。式のどこで切っても、また前後にどうつなげても文法的な正則性が失われない。たとえば「(1+2」は中置記法の記述として文法的に正則ではない。カッコが閉じていないからである。逆ポーランド記法による記述は、それが文法的に正則であるかどうか、複雑な構文規則に沿って前後を詳しく調べてみる必要がない。このことは言語処理系の実装を、コンパイラであれインタプリタであれ、著しく単純で判りやすいものにするのである。

たとえば式ツリーすなわちExpressionオブジェクトとして「(1+2)*3」を記述するとこんなことになる。

Expression.Multiply
        (
        Expression.Add
                (
                Expression.Constant(1),
                Expression.Constant(2)
                ),
        Expression.Constant(3)
        );

こんな簡単な式でもこれだけ大袈裟なことになる。しかもExpressionオブジェクトはinvariantで、後から上の「1」を「5」に入れ替えようとか、そういうことはできない(Reflectionを使えばできるけどさ)のである。これを

xx.push(1);
xx.push(2);
xx.push(cmd.add);
xx.push(3);
xx.push(cmd.mul);

などと書けるようになったら、それだけでも結構便利だと思わないだろうか。しかもpushされたコードは内部で線形リストになっているだけだから「xx[0] = 5」という置き換えも、コード生成する前であれば自由にできるとしたらどうだろう。便利ではないか。

  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

30個目のカテゴリ新設

2011年06月05日 | 不良プログラマの夕べに
このgooブログは仕様によって30個までしかカテゴリを作れないのである。だからこれが最後のカテゴリだということに、一応はなる。仮に今後新たなカテゴリを作るとしたら、既存のどれかは潰れる(他のどれかと統合する)ことになる。

正直、プログラミングのネタをこのblogで扱うつもりは、開始当初はまったくなかった。

本当のことを言って、わたしは計算機屋としてはとっくに耐用年数を過ぎた老いぼれのポンコツである。そうでなくてももともとプログラマの能力的には大したことがないと自分でも思っている。無駄に年季だけは入っているからハケンの仕事を続けてはいるけれど、来年はあるのか、いや来月がすでに怪しいと思いながら仕事を続けて、そろそろ十年になろうとしている。

考えようによっては幸運なことである。同世代の中でも今なお現役のプログラマで稼いでいるという人は、すでにそんなにいないだろうからである。たいていの人は管理職になったり、技術営業とか何とかの、つまりは専ら人間や人間の組織を相手にするような仕事をしていることだろう。そういう仕事ならわたしはやりたくないし、第一できると思っていない。どういう理由とどういう意味でできないのかも明確である。

わたしは、仮に自分にコドモがいたとして、そのコドモが「学校に行きたくない、勉強はやりたくない」と言ったら、それを否定する言葉も論拠もまったく持っていない人である。俺だって学校も勉強も大キライだった。たまさか「学校は友達と遊ぶところだ、世界中の誰がどんなに否定したとしても」と思うことができなかったら、小学校だって毎日通いはしなかっただろう。だから空想上の自分のコドモが「学校はキライだ」と言ったら、それは端的に正しいことを言っているわけである。正しいことを否定するのは、自分の中のどんな哲学と倫理を参照しても決して正当化できないことである。

だから俺は人の親にはならない。職業なら「教師」にはならない、職制なら「管理職」にはならない、と、これは小学生の頃からの信念なのである。ひとくちに言って、わたしは他人に何かを命じるということが一切できない。他人に何かを命じるという行為それ自体に合理的な根拠を認めることができないし、現に持っていない。むろん、そんな根拠など持たなくたって口先から命令語を発することはできるだろう。だが、そんな茶番が言葉通りの意味を持つということを、わたしはわたしの哲学にかけて否定しているわけである。

・・・プログラミングの話をするつもりが関係ないことを書いてしまった。最後にちょっとだけ書くと、先日(5/31)示した開発目標のうち、逆ポーランド言語処理系は.net 4.0の動的コード生成を大いに利用した形で作り直すことにした。ここ数日はその下準備で「Expressionクラス」の調査に時間を費やしていた。このExpressionクラスは.net 3.5あたりから導入されたものだが、当初はなんちゃってラムダ式くらいにしか使えなかったので、今回の開発でも当初は無視していたのだが、ひょんなことで調べ直してみたら、実は最新の4.0ではかなり使いでのあるものに変貌していたわけである。とはいえ、これを利用して言語処理系を作ることは、パッと見で考えるほどたやすいものではないことも事実である。

それをもっと簡単にする上で、いま構想している逆ポーランド言語処理系の枠組みが逆に利用できるのではないかと思えてきた。簡単に言えば「push(1); push(2); push(add);」と並べて書けば「1+2」を意味する式ツリーのオブジェクトが出来上がるようなものを作ろうとしているわけである。これができれば言語処理系それ自体よりもExpressionクラスの汎用的なアプリケーションとして有用である、はずである。

  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする