つかもと
Jump to navigation
2005・05・27
Perl
今度Perlを使うことになったので、基本的なところについて見てみました。CPAN(http://search.cpan.org/)のドキュメントを見ていますが、Perlでは処理内容が一行のif文を書くときに、
if ($bv) {
print "Ariel AirOne ProjectA";
}
と書く代わりに、
print "Ariel AirOne ProjectA" if $bv;
と書けるそうです。最初の書き方がthe tranditional way、後の方がthe Perlish post-condition wayと説明されていました。せっかくPerlで書くので、後者を使いたいところですがどうでしょう。
アリエル
先日のオークスに、ヤマニンアリエルという馬が出走しました。結果、16番人気で、16着でした。別にうちの会社とは全然関係ないのですが、4着が5着くらいに入ってくれると良かった気がします。
2005・03・25
javaのhttp関連のクラス2
httpのリクエストのパラメータで、日本語をUTF8で送信する必要があったので、前回と同じ箇所をいじりました。
元のコードは次のようになっていました。
HttpURLConnection conn = (HttpURLConnection)(new URL(url).openConnection());
int code = conn.getResponseCode();
...
ここで、urlStringが url + "?param1=$param1¶m2=$param2..." というようになっていて、そもそもURLオブジェクトにurlだけでなくリクエストのパラメータ込みのものを渡していました。
この方法でも英数字だけの場合には正常に動作していましたが、Unicode以外の日本語を利用する場合はうまくいきません。
リクエスト用のパラメータを設定するような直接的な関数(setRequestParameters(Hashtable parameterValues, String encode)みたいな感じのもの)が見つからなかったので、どうやって設定するのか調べたところ、HttpURLConnectionオブジェクトのoutput streamに文字列をUTF8にエンコードしたバイト列を書き込めばできるようです。この方法で書き換えて、次のようになりました。
ByteArrayOutputStream params = new ByteArrayOutputStream().writeTo(new String("?param1=" + $param1 + "¶m2=" + "$param2" + ...).getBytes("UTF8"));
HttpURLConnection conn = (HttpURLConnection)(new URL(url).openConnection());
conn.setDoOutput(true);
params.writeTo(conn.getOutputStream());
int code = conn.getResponseCode();
...
この方法で無事に日本語の文字列をUTF8で送信することができましたが、urlは文字列で指定して、httpのリクエストのパラメータはバイト列で設定するというなんだかちぐはぐした感じがいやですね。
2005・03・10
javaのhttp関連のクラス
httpのリクエストを受信している箇所を見ていると、何故か同じリクエストを2回受信しているように動作していました。そこで、送信部分のコードを見てみると、
url = new URL(urlString);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
int code = conn.getResponseCode();
conn.disconnect();
if (code != 200) {
エラー処理
}
InputStream in = url.openStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(in, encoding));
レスポンスデータの読み込み
bufferedReader.close();
urlオブジェクトで接続を開いて閉じた後に、もう一度接続先へのストリームを取得してレスポンスデータを取得するという動作です。
最初にこのコードを見たときには、openConnectionでリクエストを送信して、レスポンスデータをローカルのバッファに格納して、openStreamは、そこへのストリームを開いているのかと思い、この処理を2回呼んでいるのではないかと、別の箇所を探してみました。
ところが、そのような箇所は見当たらなかったので、もう一度この部分を各々のメソッドの動作を詳細に調べて、ようやくopenStreamでもリクエストを送信していることに気が付きました。
一度のリクエスト送信で済ませるためには、openConnectionの接続を開いたまま、接続先へのストリームを取得して、レスポンスデータを取ってくればよくて、
url = new URL(urlString);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
int code = conn.getResponseCode();
if (code != 200) {
エラー処理
}
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(conn.getInputStream(), encoding));
レスポンスデータの読み込み
conn.disconnect();
のように変更するとうまく動作しました。
最初からopenStreamを呼んでもレスポンスデータを取れると思いますが、エラー処理の精度が落ちる気がします。openStreamはその辺を気にしない場合に使用するメソッドなのでしょうか。
2005・02・23
Stringクラス
いま、新しく来た学生バイトの人にJavaを教えています。自分もJavaは始めてから3ヶ月くらいなので、教える立場にない気もしますが、バイトさんはJavaが初めての言語だということだそうで、なんとか教えています。
そんなとき、Stringのsplitメソッドを使うことになったので、spulitの使い方を教えるために、APIを見てもらいました。ところが、APIの読み方がわからないというので、splitで教えようとしたのですが、これは引き数に正規表現の文字列を取るメソッドです。正規表現を知らないということなので、とりあえず別の簡単そうなAPIで教えることにしました。
さっとAPIを一通り見てみると、引き数を取る形のものだと、なかなか簡単なものがありません。charAtはクラスの内部構造を説明しないといけないし、compareToは戻り値が説明しにくいし。equalsなら簡単に説明できそうだと思ってみてみたら、引き数がObjectです。。。
結局、少しごまかしてequalsでAPIの見方を説明して、splitを実際に使ってもらいました。しかし、equalsで説明があいまいになったのと正規表現を引き数にとったりするのが原因で、案の定splitのサンプルコードもすぐにはうまく書いてもらえませんでした。
基本的なクラスのStringがこんなAPIを提供しているのに、Javaから学習する人はどうやって言語を学んでいるのでしょうか。
もっと読む...
ファイルの読み込み
Javaで日本語のファイルの読み込みをやってみました。そのとき、まず、J2SEのクラス一覧を見てみて、FileReaderというそれっぽいクラスがあったのでとりあえずそれを調べてみました。APIを見るとchar単位でファイル読み込みを行っているようで、Cと同じ要領でファイルのハンドリングができそうだということで、最初に見つけたそのクラスを使って実装してみました。
ところが、String型にはcharの配列を指定してStirngオブジェクトを作成する場合には、文字コードを指定するようなコンストラクタが用意されていません。そのため、読み込んだcharの配列をそのままUnicodeの文字列として扱う形になってしまい、日本語文字列がうまく扱えませんでした。
なんとかこの方向で、正しく日本語の文字列オブジェクトを作ろうとしましたが、なかなかうまくやる方法が見るからないので、途中であきらめて別の方法でやることにしました。StringのAPIを見ると、byteの配列ならデコード用の文字コードの指定もできるようなので、ファイルをbyte単位で読み込むFileInputStreamクラスを使用してみました。
すると、あっさりうまくいってしまいました。いろいろ試したあとに気がつきましたが、Javaでは、char型が16bitのようでCとは違うようです。それに、FileReaderの方がファイルを読み込むのに直観的な名前をしていたので、こちらを先に使ってしまいました。char型を8bitと勘違いしたのと、クラスの機能を直観だけで判断してしまったのが、面倒の始まりでした。
別の言語を利用するときに今まで使っていた言語の感覚でやってしまうとなかなかうまくいかなくなることがあるという体験でした。
もっと読む...
2005・02・21
簡単な関数?
Javaで、文字列の部分比較をしようとして、String型の
public String substring(int beginIndex, int endIndex)
という関数を次のように使用してみました。
final String SUB = "sub";
String unknownLength = "...";
if (unknownLength.substring(0, SUB).equals(SUB)) {
...
}
すると、unknownLengthの文字列長がSUBより長い場合はうまく動作しますが、unknownLengthの文字列長がSUBより短い場合は、IndexOutOfBoundsExceptionという例外が出てうまく動作しません。API一覧の箇所には、送出する例外の型が書いてなかったので、文字列長が足りない場合は、元の文字列でも返してくれるのかと期待していましたが、APIの詳細を見るとそのような場合は、IndexOutOfBoundsExceptionが送出されるとしっかり書いてありました。簡単そうなAPIも説明を読まないときちんと使えないものだと思いました。
2005・01・27
2.コピーコンストラクタ
コピーコンストラクタは、以下のような場合に呼ばれます。
・自分と同じ型または、継承関係で下流にある型のオブジェクトを、コンストラクタ引き数に一つだけ渡した場合
・実体を受け取る関数に、その型か継承関係で下流にある型のオブジェクトを引き数に渡した場合
注意点
・関数にオブジェクトを引き数として渡した場合、関数内で、暗黙のうちにコピーコンストラクタが呼ばれる。
・関数に、仮引き数として宣言されている型の継承関係で下流にあるオブジェクトを渡しても、宣言されている型のコピーコンストラクタが呼ばれる。関数内で確保されるメモリと、使用できるメソッドも宣言した型のインスタンスのみ。
・returnでオブジェクトをコンストラクタで直接返すようにした場合、呼び出し側のスタック上にその戻り値を格納すると、コンパイラの最適化によって、呼び出し側のスタック領域が使用され、関数内のスタック領域が使用されない。このときは、呼び出し側でコピーコンストラクタを呼び出しているような状態になり、関数の呼び出し終了時点では、デストラクタが呼ばれず、生存期間は呼び出し側に用意したインスタンスの生存期間に委任される。
以下、サンプルコードです。
もっと読む...
2005・01・08
1.初期化と代入の違い
C++では、初期化と代入を似たような呼び出しで実行しますが、組み込み型の変数及びポインタ、参照、クラスから生成されるインスタンスの3つについて初期化と代入の意味がそれぞれで異なります。以下のような相違があります。
・組み込み型の変数及びポインタ
初期化:メモリ上に右辺に指定された値を設定します。
代入:初期化と同じ。
・参照
初期化:どのインスタンスを参照するかを決定します。明示的に初期化する必要があります。
代入:参照先の、クラスTから生成されたインスタンスのT::operator=が呼ばれます。
・クラスTから生成されるインスタンス
初期化:コンストラクタが呼ばれます。
代入:T::operator=が呼ばれます。
次に初期化と代入が行われるタイミングを列挙します。
・組み込み型の変数及びポインタと参照
初期化:宣言時に変数に対して"="で値を指定した場合。クラス内に宣言されたものは初期化リストで明示した場合。関数の引き数に指定されているものは関数が呼び出されたとき。
代入:宣言時以外に"="で値を指定した場合。
・クラスTから生成されるインスタンス
初期化:インスタンスを宣言した場合。インスタンス宣言時にコンストラクタを明示的に指定した場合。インスタンス宣言時に"="で値またはコンストラクタを指定した場合。クラス内に宣言されたインスタンスはそのクラスのコンストラクタが実行される前にデフォルトコンストラクタで初期化される(初期化リストに指定すると明示的に初期化できます)。関数の引き数に指定されているインスタンスは関数が呼び出されたとき(コピーコンストラクタによって初期化されます)。
代入:宣言時以外に"="で値を指定した場合。
続きでサンプルコードを挙げます。
もっと読む...
2004・12・17
C++備忘録
まだC++のコードを大した量は書いてないので、テストフェーズになったりしてC++のコードをしばらく書かないでいると、細かいところは元より重要なところもいろいろ忘れてしまいがちです。
そんなときに備忘録として使えるようなものがあると便利なので、いろいろな切り口からまとめてみることにしました。まずは、単一のpublic継承を使用するときに理解しておくとその辺の見通しが良くなりそうなトピックについてまとめてみようかと思います。大きな項目としては以下のような感じでしょうか。
1.初期化と代入の違い
2.コピーコンストラクタ
3.ポインタと参照の違い
4.関数の呼び出し
5.継承
6.継承におけるクラス宣言の意味
7.抽象クラス・デストラクタ
これらの項目について何回かに分けてまとめていく予定です。
2004・08・26
昼間から
休日ともなると昼間から飲み始めます。暑いときに焼酎を飲むと余計に暑くなって汗がでてくる始末。しかし、その暑さを耐えれば心地良い涼しさへと変わります。そんな状態で寝転がって晴れた空でも眺めていると気持ちがいいもんです。
そんな焼酎の最高峰のひとつに、森伊蔵というものがあります。直接購入するのはやたら高い倍率と聞く代物ですが、あっさり2度目の抽選で当たってしまいました。原価購入に加え、なにより蔵元直送ということです。これで飲んで美味ければ文句なし。
というわけで、着くなり早速飲んでみました。ストレートで飲んでも、アルコール度数の高さを感じさせない力強いお酒。非常に美味しいです。
あんまり飲むともったいないので、惜しみながら冷蔵庫にしまいました。少し前に買った善知鳥と並んでいる姿を見ると安っぽい冷蔵庫も神々しく見えてしまいます。壮観。
2004・08・24
なかなか進みません
以前から書き直しているプログラムですが、最近暑いせいもあってなかなか進みません。別に他にすることがあるわけでもないんですが、ビールを飲んだり、日本酒を飲んだり、焼酎を飲んだり。。。
さて、そんな進まないプログラミングですが、地道にやってはいるわけで、ようやくプログラマーからすると中だるみ的な箇所を抜け出して佳境に突入した感じです。7割程度出来た感じでしょうか。
そろそろ暑さも収まりそうなので、面白さにつられて順調な方向に向かいそうです。
2004・07・23
休んだときのお話2
6/26も勉強会を休みました。この日は友人と家の近くにある行きつけの和食割烹屋へ飲みに行きました。元々予定は入っていたんですが、先日の合格発表を受けてお祝いの席になりました。大学院を卒業したとき以来のそうした席になると思いますが、なかなか希薄な人生です。
ほとんど開店してから、閉店するまで居すわってしまい、5時間程飲み食いしてしまいました。それだけの時間食べ続ければ、いろいろ食べるわけですが、前もって食べようと思っていたのが、日本の三大珍味です。高くて滅多に食べられないので、割り勘できるときに一度に3つ食べようという魂胆です。
その中でもこのわたは初めて食べてみましたが、形がないので、2人で分けて食べるのが大変でした。味は、酒飲みには嬉しいものでした。
その他のものもおいしく頂いて、店を出ました。また、行きたいものです。
2004・07・10
休んだときのお話
アリエルでは、毎週土曜日に勉強会をやっています。大抵出席していますが、4/10と4/17に珍しく2連続で休みました。そのときのお話です。
4/18はIPAのソフトウェア開発技術者試験というのがあって、それを受験してきました。4/10と4/17はその追い込みの勉強をするために休んだわけです。
さて、試験日当日、試験会場は電車と徒歩で1時間ほどのところでした。試験会場の方面にはまだ行ったことがなかったので、どんなところなのか楽しみにしながら電車に揺られていると、試験会場に近づくにつれ、田園風景が広がってきました。なかなかその風景が終わりそうにないので、昼ごはんをちゃんと調達できるのか不安になりつつ、長い道のりを経て最寄駅に到着。着いてみれば、途中の景色とは打って変わって昼ごはんの調達には困らなそうな街並みになり一安心。
駅を出て、会場方面への一群の流れがあったので、それに追従。数分程歩いてようやく会場に到着、と思ったら会場が結構広くて席に着くまでもう3分程歩くはめに。席に着く頃には、試験開始まで10分程度。大分余裕を持って出たと思っていたのですが、初めて行くところではなかなかうまくいきません。
試験は、午前、午後I、午後IIという区分で行われます。お昼が混みそうなので、午前の試験は一足先に出ました。会場を出てすぐのコンビニで弁当を購入し、お昼も無事に完了。その後午後Iが開始され、少し時間が足りなかった感もありましたが、充分な手応えを感じて終了。最後に午後IIを受けて、帰路につきます。全体的に良くできた感触だったので気分良く帰宅。
がらにもなく2週間程禁酒していたので、帰るなりさっそく居酒屋へ直行。久しぶりのビールはおいしいです。
それから2月程して試験結果の発表。見事合格していました。この試験を受けるのは大学時代以来の2度目。当時は大分合格には遠い感じでした。入社して2年目ですが、約1年程度の実務経験で大分成長していたようです。
先日報告したときは間が悪くて言いそびれましたが、この場を借りてお礼申し上げます。これも一重に開発の皆様の日ごろのご指導及び毎週の勉強会の賜物と存じます。ありがとうございます。これからもご指導ご鞭撻の程よろしくお願いします。
2004・06・18
ビルドのコスト
先日から、昔書いたコードを作り直していますが、大体半分くらい作り直したところで、新しい方のリビルドが終わるまでに、以前のものよりもワンテンポ多く待つような気がしました。
ちょっと気になったので、手元の時計で計測してみたところ、以前のものが約13秒、新しいものが約16秒かかっていました。ビルドの時間に影響しそうな要素の変遷は次のような感じです。以前のものの分量を1として、新しい方は半分くらい書き直した時点のものを、見た目で比較して出してます。この表の比はかなりいい加減です。
以前 新
リビルドの時間 13秒 16秒
コードの長さ 1 0.3
クラス内の変数の数 1 0.5
関数の数 1 2
派生クラスの数 1 8
オーバーライドした関数の数 1 15
クラスの数 1 2
インポートしたリソースの数 1 0.4
以前のものは、制御クラスだけあるような感じで、ほとんどCで書いたものと変わらず、新しい方はC++的なものです。コードの長さが3分の1くらいなのに、リビルドにかかる時間が2割増し。なんだか損した気分です。表からすると、継承関連のところで大きく時間がかかるんでしょうか。(ただ都合の良い表を書いただけかも知れませんが)
コードの量が増えて、全体のビルド時間が増大すると、この差は無視できないですね。全部書き直した頃にどれくらいの差がでるか楽しみです。