ラベル light wight language の投稿を表示しています。 すべての投稿を表示
ラベル light wight language の投稿を表示しています。 すべての投稿を表示

2011年10月22日土曜日

そーいや、WEBの世界には「セッション」が有ったなあ

他の記事を書いた後、他の人ってどうなんだろうと検索してみたら、

http://d.hatena.ne.jp/kwatch/20100613/1276385931
PHPは唯一、セッション管理を内蔵してる(意訳)

という主張がありました。言われてみればその通り。

pythonについては、先日pythonカンファレンスに出てみましたが、「フツーwsgi」らしいです。cgiの話なんか誰もしません。そういう状況ではPHP/Perlにしちゃうのでしょうか。cgi.pyの存在は知らない人の方が多いかもしれませんね。って言うか筆者はpythonでCGIを作る気がないので存じませんでした。

この記事を最後まで書いちゃってから気づいたのですが

  • PHPはmod_php
  • しかしpythonはcgi.py
  • しかしrubyはcgi.rb
それぞれ前提条件が違うので、比較にならないですね。
比較するなら、
  • PHPはmod_phpを
  • pythonはmod_pythonを
  • rubyはmod_rubyを
が筋でしょう。

筆者はperl5で、クッキー&セッションを自作して、酷い目にあったクチなんで、PHPの$_SESSIONには感涙したものです。しかも、クッキーが使えなかったら、表示する筈のHTMLタグに介入して、PHPSESSID=とかパラメタを勝手に付加する。というのも画期的ですね。これで助かってるガラパゴスケータイゲーム業者も多いはず。

筆者は、公私共に、appengineで色々運用していますが、セッションが無くて困ったことがありません。何でだろな、と思ったら、ユーザ認証ベースで作ってるからですね。そういう案件だから、ってのはその通り。

セッションが必要な典型的なケースは、ショッピングバスケットでしょうか。ユーザ認証があれば大丈夫ですよ。って言おうとしたら、未登録の人が未登録のまま買い物をするケースが結構ありますね。買い物客としては筆者もよくやります。そういう時にはセッションは有った方が良い。

appengine/wsgiのお作法では、セッションはデコレータとして実装して、後付けした方が美しい気がします。それが出来るのがpythonの利点ですし。

うまく行ってるか判りませんが、まさしくデコレータで自作した人は居るらしい。
https://sites.google.com/site/yomusu/googleappengine/oresession
http://d.hatena.ne.jp/coiledcoil/20110212/1297491800

mod_pythonにはセッション機能があるようですね。
http://www.python.jp/doc/contrib/modpython/pyapi-sess.html

djangoもセッション機能を内蔵してるらしい。
http://www.djangobook.com/en/2.0/chapter12/
ただしdjangoは、mod_python/wsgiの2択らしいんで、cgi.pyは使ってませんね。

総論としては、pythonでcgi.pyを使ってる人は変態。

perlとは心中しません

筆者は、perl5には結構お世話になってます。10年は前。それこそCGIの時代ですね。

C++を眺めてても、参考書をいくら読んでも全然判らなかった「オブジェクト指向」。perl5では、それを連想配列とパッケージでエミュレーションしてる訳ですが、その切り口によってオブジェクト指向の何たるかが腹に落ちました。機構から入ったという訳です。

残念ながら?それ以降、徐々に仕事はPHPに遷移します。何故ってperlの業界はCPAN前提みたいなとこあります。それは良いのですが、レンタルサーバだと後から入れるのは骨です。みたいな話は別途してます。

オープンソースでは仕方ないのでCPANのライブラリ群を配布ファイルに同梱しちゃった例もあります。あった有ったFreeStyle Wikiだ。ほうらこんな感じで大変な事に。
http://sourceforge.jp/projects/fswiki/svn/view/fswiki/trunk/fswiki/lib/?root=fswiki

そんな訳で、筆者がperl5と離れた理由は
  • 構文が気持ち悪いと思い始めた
  • 各種記号の使い分けが面倒。というか気持ち悪い。
    • 連想配列と単純配列の使い分け方法が「記号」だったりとか
      • %と@
      • []と{}
  • かと言って、dieとかmyとかlocalとか変なところで英字予約語を使う。
    • その予約語のネーミングセンスも独特。
  • 括弧を使うのか使わないのかハッキリしてほしい。
  • 中括弧の使い方が気持ち悪い。時がある。
  • 連想配列ベースのプログラムにちょっと疲れた。
  • 参照と実体の使い分けで、構文が違うので面倒臭い。
  • CPANを多用すると後(運用環境に設置する時)が面倒。しかし使わないと今(開発時)面倒。
  • dieで例外投げ、evalでキャッチ。という方法論が気持ち悪い。使ったことないけど。え?使いませんよ。だって例外が必要な案件で、perlを使う方が間違ってる。
その辺りの葛藤に負けたためです。善悪とかの話ではありません。好き嫌いです。議論の余地はありません。故に突っ込みはお控えください。それに当時の筆者としては、perlよりもPHPの構文の方が「美しく見えた」からです。今でもその認識はあまり変わってません。PHPはJavaの真似ですからね。※PHPは「その他」が駄目なわけですが

最近では、perl5ベースでも、「Modern Perl」と銘打って、真オブジェクト指向で作りましょうよ。な感じらしいです。use Mooseにより、実際見違えるほど見やすくはなりますね。
http://www.slideshare.net/bluefeet/modern-perl
じゃあMoose使えば良いじゃん。と言うかもしれない。これは条件付きで同意します。ただし、欲しいのはMooseだけなのに、色々なファイルが付いてくる。正直、CPANのこの風潮は辞めてほしい。
  • Moose自体が構成ファイルが多い。2万7千行
  • 別のCPANに依存してる。Class::MDPとか。
    • Class::MDP自身も他のCPANに依存してる。してるよね?
Mooseにはもうフレームワークというしかない規模です。え、フレームワークに決まってるだろって?済みません。認識不足でした。

筆者は大型フレームワークは嫌いなので、その点でMooseも除外対象です。

結論として、perl5+フレームワークで、ようやく汎用プログラムが書きやすくなる。それなら別の言語を使った方が早くね? プログラム言語は目的ではありません。手段です。故にperlだけに固執する理由は全く有りません。

そんな筆者は、Pythonとtclが好きです。関数型もいいらしいんですが40過ぎてからは頭が付いていきません。無理。


dankogaiさんもperlは嫌いらしい。本当か??吊りか???
http://twitter.com/#!/dankogai/statuses/452038972

2011年9月18日日曜日

狙い目の判りにくい言語Opa

知らない間に、またしても新しい言語が出ていたようです。
その名もOpa
http://opalang.org/#slides=1

初見の印象は

ネタもとのmoongiftの記述から解釈するなら
http://moongift.jp/2011/09/20110913/
目的は、WEBサービス実装のバイナリパッケージングが目的なのかと思ったのですが。

コンパイルすると、単一ファイルになってしまうらしい。サーバ側に置いて実行すると、WEBアプリケーション入りWEBサーバとして動作し、HTML及び必要なjavascriptを生成するらしい。これだけ聞くと便利そうに見えます。


http://doc.opalang.org/manual/A-tour-of-Opa
サーバ側実装と、クライアント側実装を混在して記述できるらしい。普通に作るとjQueryやら$_REQUESTやらでどうにかする訳ですが、Opa上ではタダの関数呼び出しとして表現できるというなら、開発効率は確かに上がるかも知れません。

クライアント&サーバで、記述言語を統一する。という意味ではサーバサイドjavascriptが選択肢に入る気はしますが、プロダクトが3つしかないみたいですね。
  • Node.js
    V8エンジン上で実行する環境
  • Rhino
    JavaVM上で実行するJavaScriptの言語処理系
  • Aptana JaxerAptana社によって2008年1月からオープンソースライセンスで配布されている環境
ちょっと興味が沸いたので、言語仕様を眺めてみると、どうも関数型言語の香りがしますね、と思ったらOcaml bindingとか言い出しました。
http://doc.opalang.org/manual/Hello--bindings----Binding-other-languages/Binding-Ocaml-and-Javascript
ひょっとして、「コンパイル」の先はOcamlなのか?

http://opalang.org/see.xmlt
色々、サンプル?実装があるみたいですが、おっとソースを見ることも出来ますね。githubに居ました。
https://github.com/venator/OpaWiki/blob/master/src/min_chat.opa
どうなんだろうコレ。
思ったよりはるかに読みにくいなあ。

moongiftはともかく、日本国内の反応はかなり冷やかですね。
http://developers.slashdot.jp/story/11/08/30/1123203/Web%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E9%96%8B%E7%99%BA%E5%B0%82%E7%94%A8%E8%A8%80%E8%AA%9E%E3%80%8COpa%E3%80%8D

2011年8月23日火曜日

「動的言語で安全なソフトは作れないのか」

まあ、ぶっちゃけ、どの言語を使おうが、バグは出ますよね。

動的言語の代表と言えばPHPでしょう。残念ながらね。
しかしこれはバグの出やすい言語の代表格である。
暗黙のキャストが邪悪だったり、
であるにも関わらず0とFALSEを混同する組み込み関数が多数だったり。

一方、静的言語の代表格といえばJavaでしょう。これも残念ながら。
筆者の解釈では、「言語仕様側から、バグを減らす努力をした言語」。
public classを使うときは、ファイル1個に1クラスしか書けないとか、
機械的にチェックが可能な事柄で、ガチガチに締め上げた。
しかし、それこそがEclipseの様な優れたIDEを必須にしてしまった。
面倒臭すぎる。人力でリファクタリングとかあり得ません。

ただし、それでバグが減ってるかというと、それはやはり製作者依存なのです。
メソッドにHashMapを入れてたら、知らない間にパラメタを捻じ込まれてて、
忘れた頃に、別のメソッドでそのパラメタを使ってるとか。
乱暴な奴は、何の言語を使おうが、乱暴なことをやります。
#HashMapを使ったのが悪い。というツッコミは間に合ってます。
#静的言語で、動的考え方をしてるのが間違ってる。とも言える。かな。

一般論としてはどうなのだろうと検索してみたら、酷いスレ発見。

やっぱり動的言語では安全なソフトは作れない 3
http://logsoku.com/thread/hibari.2ch.net/tech/1308499587/

基本的には高尚な議論なんだけど、uy氏の逆ギレっぷりが見苦しい。
頭は良さそうなんだけど、自分より相手が下だと見るに一転挑発モード。
なんだろうなこういうの。

本題に対しての、筆者の個人的にな意見は、最初の1行目に尽きますが。

YESであり、NOである。とも言えるでしょう。

型チェックをやろうがやるまいが、それを通り抜けるバグは必ずあります。
テストが減る。というのには反論しませんが、要らなくなる訳じゃない。

そういう考え方でいえば、関数型の定義が究極なんだろうか。
あの界隈よく判りません。

ですので、「何を使っても、安全なプログラムはあり得ない」ということになる。
なにしろ、作ってるのが人間ですから。
コンピュータは人間が間違えた通りに間違えるだけ。
それがNO。

故に、「間違えない様に作ろう」=「安全に作ろう」というのは自然な流れでしょう。

努力次第でYESに近づけることは出来るでしょう。

本論は、基本的には、プログラム内部を通り抜けるデータの話に終始してますが、大規模プログラミングには、名前空間があればどうにでもなると思っています。具体的にはJavaにもC++にも有りますよね。静的言語の代表格です。#ようやくPHPにも入りましたが。バックスラッシュって何なのよ。

2011年4月18日月曜日

PHP 2次元配列の転置

2次元配列==2段配列の中身を転置する。
機会は少ないと思いますが、やるとそこそこ面倒な処理。

筆者も流石に、馬鹿正直に2重ループで実装するところでしたが、

別件の調査中で、なかなか素晴らしい実装を発見しました。
http://blog.supermomonga.com/articles/php/array-to-transverse-matrix.html
実際試して見ましたが。動きますね。挙動が判りません。なんで?

余りにも判らなかったので、簡単なテストスクリプトを書いて試してみました。
https://gist.github.com/2472007b35430b6d71da

call_user_func_arrayが構文としてキモいので、判りにくくなってますが、

  • array_mapの
  • 第1引数のcallbackにnullを
  • 第2引数以降に、配列の2次元目を展開して、複数の配列として
可変長引数をサポートしている言語であれば、もっと美しく書けてるところでしょう。

オフィシャルのドキュメントすら「callbackにnullを入れる」という諸行の解説がありませんので、ほとんど裏技でしょう。
しかも、それにより、callback関数の引数に入れるはずだったモノがそのまま出てくるらしい。

結果的に、どうやらarray_map標準の機能しか使ってないということになります。
http://jp2.php.net/array_map
文中で「にいさん」と呼んでるお方は、PHPマスタークラスと思われます。

2011年3月1日火曜日

perl6が大変な事になってる件

「CGI言語」として、一時期は一斉を風靡したperlですが、
perl6に至って、迷走を繰り返しているようです。

端的にいって、
2000年に始めます、と言ってから、
2011年現在、未だに正式リリースできてないというのです。

当時のプレスリリースでも有れば良かったのですが、
見当たりません。
とりあえず、perl6.orgは2003年辺りから稼働しているもよう。
http://web.archive.org/web/20031007002655/http://www.perl6.org/

2000年からの歴代の議論は追えるっぽい。
http://perl6.cz/wiki/Perl_6_and_Parrot_links#Articles.2C_Blogs.2C_Discussions

迷走は構文にも現れています。
究極は「ハイパー演算子」。ネーミングで既に怪しいですが、構文がヤバい。
http://perl6advent.wordpress.com/2009/12/06/day-6-going-into-hyperspace/
http://d.hatena.ne.jp/uasi/20100108/1262951364

> lsay (1, 2, 3, 4) <<+>> (3, 1, 3, 1)
[4, 3, 6, 5]
> lsay (1, 2, 3, 4) >>+<< (3, 1, 3, 1)
[4, 3, 6, 5]
どう見てもアスキーアートです。有難うございました。

正直、これっぽっちの記号群に、「意味」を持たせすぎで、
サンプルを見てすら、何が起こってるのか判りません。

こんなもんじゃないです。不等号を使ってるのには理由があります。

> lsay (1, 2, 3, 4) >>+>> 2
[3, 4, 5, 6]
> lsay 3 <<+<< (1, 2, 3, 4)
[4, 5, 6, 7]

逆向きキター。

結論から言うと、どうやら行列演算であったらしい。
普通は、ライブラリで用意してよいレベルでしょう。

なんで記号で頑張っちゃうかなあ。
言語仕様に色々取り込みすぎるから
いつまで経ってもリリースできないのかと。

合体ロボに、ビームライフルを付けるか、
核酸粒子砲を付けるかで揉めてるようなもんですよ。

これが、非オブジェクト指向言語の末路か、と思わざるを得ません。
(関数型を否定しているわけではないので念のため)

[1,2,3,4].add(2)
こっちの方が、解りやすいですよね。

perlは、昔から記号類を積極的に使う言語で、
具体的には、変数を使う構文では$,%,@の使い分けが必要です。
配列だろうが、連想配列だろうが、単純変数だろうが、
プログラマに構文を使い分けさせるのは

昨今のオブジェクト指向を鑑みるに、これは時代遅れだと思われます。

その一方で、sayとかdieとか、英単語の中途半端な導入が気になります。
ステートメントだから英単語。な訳ではありません。
演算子にも、記号群と、英単語群が混在しています。

例えば、比較演算子は、 <=> と cmpとの使い分けが必要です。
いまだに、どっちが文字列用で、どっちが数値用か覚えられません。
#これはPHPにも伝わっちゃってる、悪しき遺伝子ですね。

perl族は、配列操作が豊富、っていう意見も見かけましたが、
例えば配列スライスはpythonにもあるし、
行列演算とか、何に使うんだ?と正直思います。

かく言う筆者も、perl5のmapとgrepに凝ったことがありましたが、
第3者にソースを見せるときには、ぶっちゃけ評判悪かったですね。
pythonでは内包表記とかを使って、人間に優しく記述できます。

perl5までは例外がない。というか、catchする方法が無いわけですが。
evalで例外をキャッチできます。という記事も見かけましたが、
http://www.geocities.jp/ky_webid/perl5/040.html
これは頓知の領域でしょう。
livedoorクリップで、この記事へのツッコミを見かけましたが、間違っちゃいけません。evalが補足するのはエラーであって例外ではありません。だって例外をプログラマが任意に投げる方法って、無いでしょ? dieを使うの? dieはエラー終了ではありません。正常終了です。それを「例外として使ってます」ってだけです。
故に「evalで例外処理のエミュレーションが出来る」というなら判る。がそれは何処まで行っても「例外処理」とは言いません。まあ頑張りたいならもちろん個人の自由なので止める理由はありませんが、例外が必要な案件でそもそもperlを使うのが間違ってます。というのが筆者の見解。ちなみにJavaは別の理由で反対です。 
ちなみに「evalで例外処理」を正しく実装しているのは、筆者の知る限りtclだけです。筆者はtclの言語仕様を美しいと思っています。
言語本体に手を入れずにMooseとか、
エミュレーション手段が出てきたのはperl自体の底力を感じさせるものですが、

この辺り、perl6ではどうなんだろうと思っていたのですが
筆者は知らなかったんですが、perl6|rakudoは例外を実装したらしい。
だたし、「その他」の切り口が、気持ち悪いものが多いので、
業務とかに使うかどうか、というと正直判らないですね。って言うか使わない。

perl族は、短い記述をめざしている感がありますが、
その手段として記号を使ったり、暗黙の挙動を盛り込んだりと、
かなり慣れが必要。逆に機構は複雑になってると思います。
こんな問題が出てくるくらいだから。
http://d.hatena.ne.jp/gfx/20110301/1298944990
昔からどうやらperlとrubyは、世の中のgeekな方々に人気っぽいのですが、perl6の事をどう思っているのだろうか?と思ったら、弾氏は、特になんとも思ってなさそうですね。http://blog.livedoor.jp/dankogai/archives/51493739.html
筆者はgeekでは無かったんですかそうですか。

2010年12月28日火曜日

仕事で使う言語の条件(1)

似たようなエントリは何度か書いてますが。

出稼ぎでの実装やら、今までの後始末経験を踏まえて、
「仕事」での理想の言語を考えます。

  • 未定義変数をいきなり参照する(代入式の右辺で使う)とエラー(例外)が出なければならない。
    • 極めて当たり前の話の筈が、PHPではNotice
  • 関数の内側から、グローバル変数を使うには、特殊な宣言がなければならない。
    • 勝手に外部スコープを参照しちゃうのは読みにくい。
    • 非オブジェクト指向での実装を助長している気がします。「カプセル化」に逆行する挙動。
  • クラス関数(メソッド)内部で、クラス変数(プロパティ)を使うには、this経由でなければならない。
    • 勝手に外部スコープを参照しちゃうのは読みにくい。
    • グローバル変数への参照と区別が付きにくい。「判るに決まってるだろ!」とか言わないように。
  • mixinのための多重継承。http://ja.wikipedia.org/wiki/Mixin
  • 動的型付け。
  • 関数が第1級オブジェクトでなければならない。http://ja.wikipedia.org/wiki/%E7%AC%AC%E4%B8%80%E7%B4%9A%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88 
    • create_functionとかあり得ない。
  • 関数の可変長の引数の受け渡しを、自然な構文で運用できなければならない。
    • func_get_argsとかva_argsとか駄目だと思うわけですよ。
  • 必要であれば、バイトコードの保存/利用も可能であること。
  • 例外処理のサポート。
  • Unicodeサポート。
    • 機能が使える、だけじゃ無意味。プログラマが意識せずとも、任意バイト文字をそれぞれ同じように扱えないと困る。
      • PHPでは変数の中身をプログラマが区別して運用しなければならない、シングルバイト文字はstrlenで、マルチバイトはmb_strlenで、エンコーディングはmb_languageでとか、テンでバラバラ)
    • 比較的理想に近いのはpythonのstr及びunicodeオブジェクト。両者、同じ操作メソッドを持つし、相互変換も容易。
ハイ、聡明な皆さんならもう判りましたね。pythonの宣伝です。

pythonは所謂スクリプトなので、というわけではないのでしょうが、protected/privateとかが有りません。これらは「カプセル化」って奴で、「オブジェクト指向」で重要ってことになってるファクタです。ただし小生はカプセル化を重要視してません。

2010年9月12日日曜日

PHP5.3の名前空間がイケてない

名前空間の実装は、コンパイラ実装者にとっては悩みの種でしょう。
そういう事にしてください。

散々悩んで、PHP5.3みたいな有様になってしまうケースもままあります。

pythonの厳密には「モジュール」があり、その内側で「名前空間」に近い概念が使えますが、
非常に洗練していて、矛盾がありません。
その根幹は、名前空間ですら「オブジェクト」であるからです。
具体的には、module型。らしい。

  • Pythonのmodule型では
    • 1ファイル中で、名前空間(的なもの)を切り替えることは出来ない。
    • 変数や関数群は、単に実行中のmoduleのプロパティの一つに過ぎない。
    • importは、module型オブジェクトを、同名の変数に取り込む。
    • クラス定義(オブジェクト)とインスタンスは、収録している変数が違う筈なので、混同のしようがない。

javascriptも、これに近い運用ができますね。
端的に言えば、「別の名前をつける筈」なので、「「名前空間名と、クラス静的メソッド等を混同する」ような作り方はしない」

故に、これが、「名前空間専用の、階層区切り文字の設置」の理由にはなりません。
こんな理由が、バックスラッシュの理由で、まかり通っちゃ如何でしょう。
PHP関係者が、如何に他の言語畑とくらべて緩いのか。
言語側から、これを強制できなかったのは、PHP5.3の大失敗の一つでしょう。

PHPの名前空間の区切りがバックスラッシュになったのはそんな理由だったのか

誰かさんの記事ですから、また聞きですが

http://blog.ohgaki.net/php_5_3_namespace

何故このようなエントリを書くかというと、Software Design(技術評論社)の11月号にPHPの最新情報としてα版PHP 5.3を紹介しているからです。入稿後に仕様変更があったので最新号の記事ですが既に内容が古くなってしまいました。
# とは言ってもまだ新しい仕様のPHPは無いですが
α版なので仕様や機能が大きく変更される事もありますが大きな変更がありました。見本誌が刷り上がった頃に名前空間の区切り文字が"::"だと静的にメソッドを呼び出す場合やクラス定数を呼び出す場合に困る場合がある、とPHP開発者のMLで議論になり始めました

マジで?
イヤイヤ、その反論はオカシイデショウ。(リンク先の方に反論している訳ではありません)
という反論は誰かがしているはずだと思いたい。

よく読んでないけど、さらにそれの反論が、これかな。英語なんだよなー。

http://www.sitepoint.com/blogs/2009/08/13/are-php-namespaces-bad/

「静的メソッド&静的クラス変数を呼び出す時に困る。」
そうならないための名前空間じゃないのかと。

もしくは、作り方が下手なんじゃね?
もしくは、「困る」なら、その人にとっては要らない機能なんじゃね?

名前空間とクラスが、どうやら完全に別物だと考えちゃってるのだけど。
pythonを経験すると、決してそうではないということが解る。

やはりそもそもの失敗が、変数と、定数とで、それぞれ構文が違っちゃってるところ。
(まさかその時にも、「○○の時に困る」とか誰か反論したんじゃないでしょうね?!)
コンパイラが継ぎはぎだらけなのは明白です。
さらにそれに、名前空間のために、新しい「継ぎはぎ」を加えたのでしょう。

2010年9月11日土曜日

pike、結構速いぞ?!

結構な昔からありますが、pikeというスクリプト言語があります。マイナーです。
http://pike.ida.liu.se/

そして、これまたマイナーなroxenというwebサーバの、
http://www.roxen.com/products/cms/webserver/
サーバサイドスクリプト言語でもあります。

pikeはC++/Cに似た感じの言語ではあるので、
そういう人々にwebの仕事をしてもらうのに都合が良いかと思っていたのですが、
だいたいそういう方々にはjava/PHPをやってもらっちゃうご時世です。

しかし、PHPは、スクリプト言語としてはどうやら遅い方らしい?

そこで思いだしましたpike。しかしマイナー過ぎて性能情報がありません。
仕方がないので自分で試してみました。

ベンチマークは数ありますが、マンデルブロ集合のものがソース付きだったので、
pikeに移植して、同じ条件で比較してみることに。

オリジナルはここでhttp://www.timestretch.com/FractalBenchmark.html
例によってgistに貼りました。http://gist.github.com/574137http://gist.github.com/574135
結論から言うと、かなり早いです。驚きました。luaに匹敵する性能でした。
http://gist.github.com/raw/574260/f7ad985013a5538921de98a67aafba67b2e781d5/gistfile1.txt
pikeは言語的にはこんな感じなので、
http://gist.github.com/raw/574137/a0d678929dc08cbc034ff9584fb7cebce16c84aa/mandel.pike
C++/Cの人に、PHP/python/luaをやらせるよりは現実的じゃないでしょうか?

http://gist.github.com/raw/574135/48624475858c4cd37fe488c320d7ae5ddaf8bc50/mandel.c
ほうらソックリ。
例によって、全自動スクリプトも作ったので、皆さんも自分の目でお試しを。http://gist.github.com/574260

2010年9月4日土曜日

hiphop for PHPで頑張れない

出稼ぎ先の事情で、hiphopを試そうとしました。
facebook御謹製の、php/C++トランスレータです。
http://github.com/facebook/hiphop-php

結論から言うと、トランスレートまでは何とかテストできたのですが、
それのコンパイルで挫折しました。

  • まずは、facebookとしてはcentosを推奨しており、筆者の環境(ubuntu lucid(10.04))で動かすには意外と骨が折れたこと。cmakeとやらが全然通らず、仕方がないのでCMakefile.txtを修正したりとか。
  • 64ビットlinux専用。この為に、64bit ubuntuに入れ直した。
  • PHPのinclude_pathを参照しないので、フレームワーク群を多用しているソースは、正常に変換できないこと。
  • コンパイル時点で解決できない外部includeは、一応はincludeのままで残るが、挙動としてはhtmlの表示しか使えなさそう。
  • 「変換」したcppソースのbuildには、hiphop自身のincludeファイル群を必要とすること。
  • クラス群の「変換」では、クラス変数やクラス関数群に全てユニークIDを振っており、どうやらそれは「変換」したソースにも現れる。
  • クラスメソッド呼び出しは、クラスの問い合わせ関数に、メソッド名を指定している。何もかもcall_user_funcを使う感じ。オーバーヘッドが凄そう。


総合して、hiphopに向いた書き方が必要で、赤の他人が別のプロジェクトに適用するにはまだ辛いかなと。

特に、ユニークIDと問い合わせ関数はどうかなと思った。これは変換とは言えない。「展開」ですね。

native C++に変換しながらも、PHPより2倍、としか言えてないところも、
オーバーヘッドが大きいことに起因しそうです。

これだったら、最速と名高いlua(http://www.lua.org/)に「展開」する方が現実的か?とも思ったりします。

2010年8月19日木曜日

PHPが目指すもの

ここ最近、付け焼き刃的アンチPHP振りが恥ずかしくなってきたので、
今一度初心に帰って、PHPの目指すものを考察してみたいと思います。

筆者は、web業界としては古株で、それこそ「perlでCGI掲示板」からやってます。
pythonは既に存在していた筈ですが、日本ではまったく無名でしたね。

perlの頃は

実装については、CGI非専用言語なので、HTTPレスポンスヘッダを
自分で吐かなければなりません。これは初心者にはちょっと辛いかも。

また、レスポンスヘッダを作成するまえにエラーで落ちたりすると、
エラーメッセージがブラウザまで返って来ません。
これもデバッグが面倒でした。suexecやってたりすると更に面倒。

更にperlで中規模以上の開発をやろうとすると、問題になるのがCPAN。
CPAN自身が問題というよりは、大体稼働場所が「レンタルサーバ」なので、
新しいCPANは入れさせてもらえない。という事に成りがちです。

そこから行けば、PHPは天国です。

スクリプトでエラーが出ても、画面にペロっとメッセージが出てくれます。
厳密には、その設定はデフォルトoffだったりするのですが。

application/x-urlencodeの場合、ブラウザから送ってきた筈のデータは
既に「$_REQUESTに入ってる」。これは単純に、楽ちんです。

何処のレンタルサーバでも、概ね「全部入り」なので、
開発環境と稼働環境の統一に、あまり悩まなくて済みます。

また言語自体は、プラットフォーム依存は、あまり有りません。
#厳密には、アーキテクチャ依存はあったりしますが。

「サーバはWindows 20XX Serverです」とか言われると、ぶっちゃけ血の気が引きますが、
apache2とphpをインストールするだけで、
動いてくれるのは、軽量言語としては貴重です。

#サーバが、IISで、ActivePerlを入れて。とか。考えたくない。


忘れがちなのが、セッション処理を内蔵していること。筆者はperlでクッキーセッションを自力実装して、バグった事があります。クッキーを受け取らないブラウザでは、複数の人間が同じデータを参照してしまうというバグ。サービスサイトでは恐ろしい限りです。


総評として、

「perlより、そこそこ楽にweb開発をする言語」としては、優秀である。

とは言えましょう。

しかし、「その他」が駄目だった。

名前空間が有りません。
#perlには有ったのに。何で取っちゃったのか?

無いだけならまだよいのだが、前述の「全部入り」だと、
それだけ名前空間を食いつぶされるということでもあります。

array_*とか、ダサい関数名なら幾ら使ってもらっても構いませんが、
http://jp2.php.net/manual/ja/book.array.php
DirectoryIteratorとか、付けたくなるクラス名ですよね。
http://jp2.php.net/manual/ja/class.directoryiterator.php
#実際、php4から5の時に、それで動かなくなったスクリプトが有ります。

5.3で、ようやく名前空間を実装しましたが、
名前空間の区切り記号がバックスラッシュです。
http://jp.php.net/manual/ja/language.namespaces.nested.php
「サブ名前空間」?
名前空間に「サブ」ってどういうこと?
これ正直、気持ち悪いのですが。

#と思ったら、意外と受け入れられてるらしく、
http://blog.asial.co.jp/658

組み込み関数で、戻り値に整数型と論理型が混在してます。
混在するだけならまだ良いのですが、統一性がありません。
http://jp2.php.net/strpos
http://jp2.php.net/manual/ja/function.preg-match.php
falseの使い方に注目。

本質的な問題として、
バージョンアップで何かしら言語を拡張しようというときに、
「組み込みクラスを増やす」「組み込み関数を増やす」。それはまだいいのですが。
その他は「連想配列でなんとかする」という凄いポリシーを感じます。

この辺りの象徴は、call_user_funcに或る。と言えるでしょう。
http://jp2.php.net/manual/ja/function.call-user-func.php
1番めの引数には、「関数名」を「文字列」で渡します。

これだけでも気持ち悪いのですが、じゃあオブジェクトの場合はどうするのか?
array($classname, $methodname) これを入れろと言ってます。
前者は概ね、& $thisと書くべきでしょう。

$return = call_user_func( array( & $this, "method1" ), $param1 )

ナニコレ。気持ち悪いこの上なし。

総論に追加しなければなりません

しかし、中規模以上の開発に使うには難あり

理由は主に前述の通りですが、

一番の理由が名前空間が無いので、人間が「名前空間エミュレーションしている」。

ディレクトリ名はクラス名に前置するのが流行ってます。
Zend_Db_Table_Abstractとか。しかしこんなのは、完全に対処療法です。

必然、プロジェクトファイル群の構成として
長いクラス名と、
深いディレクトリ構造に、
大量の細かいファイル群を扱わなければなりません。

人間が手動で扱うのには無理があります。

統合環境を使わなければやってられません。

「お気楽言語であった筈」のPHPに、
「Javaの面倒くささ」を持ち込まざるを得なくなってしまったという。
本末転倒と言うか、ミイラ取りがミイラになるというか?
アレJavaがミイラ?

強調しておきますが、筆者は、統合環境にもJavaにも好意的ではあります。
Javaは「中規模未満の開発に使うには難あり」だと思ってますけどね。

2010年8月14日土曜日

「速い言語」とは何なのか?

先日、PHPは遅い的なエントリを書いたばかりですが、

プログラミング業界にとっては、
「書きやすく、しかも何を処理しても速い」言語が永遠のテーマです。
実際にはそれほど上手い話はあまり有りません。

多数の言語が存在していることが、
逆にその証明になってるでしょう。

優れた言語であっても、不得意分野が必ずあり、
そのための言語が必ず産まれます。

似て非なる話で、MS Windowsプログラムでは、
古来ではwin32 apiを直接呼んでいたりしてましたが、
ある時から、MFCとか言い出しました。
GUIの「複雑な実装」には「オブジェクト指向」の考え方を取り入れるしかなかったからです。と、筆者は考えていますが。
更にそれでもダメで、C#とか言い出した。まあC#の言語としての評判は悪くなさそうですが。

「何を処理しても速い言語」はどうやって探すのか?

言語の実効速度の比較には、「ベンチマークテスト」がありますが、それをやっているサイトは、多数あります。

http://shootout.alioth.debian.org/u32q/which-programming-languages-are-fastest.php

大抵は、「Cが爆速で、スクリプト言語は激遅」みたいな結論に落ち着きがちです。

その中身は、「エラトスネスの篩」だったりとか。

いや、悪いって言うんじゃなくて、
言語の一部の性能だけを見ているのは確かですね。

例えば、前述のエラトスネスの篩だと、
多回転ループ、長配列の処理ってことになりますが、
果たして、実際の実装で、そういうケースが有るのかどうか?

って言うか、ネエよ!
受注開発で「エラトスネスの篩を作ってください」とかネエよ!

言語の「設計思想ベンチマーク」とでも言うべきものなのかも知れません。

ドコゾの何かのアプリケーションで、ベンチマークモードとかあるとか聞いたような。コンパイラだったかな?

もっと「実際の摘要に即したベンチマークテスト」が必要なのではないでしょうか。

「速い言語」を探して何をするのかというと、
最近ではもう大体webアプリケーションサーバでしょう。
#一昔前はWindows MFC一択でした。いい時代です。

じゃあ何を使えば良いのか?

C/C++で書くのが「速い」のは判りきってる事ですが、
それは低級言語だからであり、コンパイラだからでも有ります。

しかしwebアプリケーションをC/C++で書く、
なんて話は聞いたことがありません。

webアプリケーションの処理は、
文字列を切ったり貼ったりが非常に多く、
それはC/C++では、不得意分野だからです。
所詮は、言語はプログラムの手段、道具なのですから、
適材適所でしかるべきです。

そして、何やら、爆速テンプレートエンジンが有るって言うじゃありませんが。

http://www.kuwata-lab.com/tenjin/
名前からして日本人の作かな?と思いましたが、
英語ページしかありません。

#テンプレートエンジンだから、Tenjin?
#日本人のセンスだよなあ。

テンプレートエンジンの実装として、馬鹿正直に考えると、
大抵は、◯◯クラスを定義して、
テンプレート文字列を切ったり貼ったりする訳ですが、

このTenjinとやらは、そうではないらしい。

内部では、完全な単体スクリプトに変換してしまうらしい。
http://www.kuwata-lab.com/tenjin/phptenjin-examples.html
軽量言語のみサポートしているのもそういう事なのでしょう。

バイトコンパイラの性能頼みですが、実際速いらしい。
http://www.kuwata-lab.com/tenjin/img/fig01.png

比較対象が、不利な実装になってる可能性は否定できませんが、
Tenjin自身がそれだけ速いのなら、使ってみようか、
という気にもなります。

似たようなコンセプトで、JavaにはJSPが有る訳ですが、
残念ながらJSPが遅いのは有名です。
http://d.hatena.ne.jp/kwatch/20100603/1275524286
何故か、を危うく書こうとしてしまいましたが、
知ったかぶりが露呈するので辞めておこう。

2010年5月21日金曜日

python elixir、しばらく使い込んでみました

python elixir。その後、しばらく仕事で使い込んでみました。
http://elixir.ematia.de/trac/

基本的に import * を推奨しちゃってる感じですね。
設計方針的に。

勝手に?暗黙に?処理する部分が結構あって、
エラーの出方に意表を突かれます。
それが馴染むか否かですね。

setup_all() とか、
現在の名前空間から、Entityの継承クラスを探して、
それぞれ「重要な何か」を仕込んでいるらしい。

リレーションしてる様なケースでは、普通はjoinするのが筋なんでしょうけど
#ついapp engineのつもりで、
他のEntityのqueryを作るようなメソッドを書いちゃったんですが、
いざ使おうとしたら、queryが居ません。みたいな。

発想は美しいような?妙にチグハグなような?
じゃあmetadata.bindは何をやってるんだ?的な憤りはままありますが。

elixirを使う場合は、Entityの実装はあまり小分けにしないで、
__all__をちゃんと書いた方が上手く回る。ということなんでしょう。
#アレ?それってpythonでは常識??

筆者は、名前空間を上書きしない主義。だったので、
抵抗というよりは、カルチャーショックでしょうか。

総評としては、elixir(引いてはsqlalchemyも?)は、
pythonマスターによる、pythonマスターの為の。
という感じでしょうか。

2010年5月12日水曜日

python elixir

appengineのdatastore実装が素敵過ぎて、他の案件でも使いたいのですが、
「顧客の要望」で「CGI環境」と言われちゃう事がままあり
そういうケースでは、djangoごと引っ張ってくるのは無理っぽい。

と思ってる人は多いはず。

筆者が試したのはelixirです。
http://elixir.ematia.de/trac/wiki

当時は0.6.0ぐらいだったと思います。

結論から言うと、悪くはないのですが、
sqlalchemyのwrapper的な生い立ちのせいか
微妙なところで変なアクが有りますね。


  • ModelというかEntityは、概ねdb.Modelの様な調子で書けます。
    • Field()への入れ子(?)宣言なのが何とも言えない。
  • 外部キー制約は、OneToMany(), OneToOne()で行けます。
    • 内部で、ReferenceProperty的挙動もやってくれます。
  • 定義したとおりのプロパティ名で、キーのリンク先データを引っ張ってくれます。
  • SQLに逐一送っちゃわずに、内部でトランザクションエミュレーションしてる模様。
  • setup_all()をやらないと、commit()でもデータを書き出してくれなかったとか。
  • 故に、データの書き出しは、Entityのsave()じゃなくて、session.commit()だったりとか。
    • # Entity.put = staticmethod(session.commit) #とかやっておくべきか?
  • setup_all()で、Entity.queryが沸いて出るとか。
  • Entityのquery.filer_by()関数で、新しいオブジェクトを返すので、それを変数に入れ忘れると、全件検索になっちゃうとか。
  • 複数カラムにまたがるインデックスを貼りたい場合は、sqlalchemyのクラスを引っ張ってくる必要が有っちゃったりとか。


その一方、実装は、pythonの限界に挑戦しちゃってる感があるので、参考になります。

pythonのテンプレートエンジンmako

最近は、pythonアリの発注(受注)が出てきて嬉しい限りです。

google appengineフレームワークには、
テンプレートエンジンが同梱しており、
これがなかなかの使い勝手。

サーバも含めてオマカセ案件では、
appengineにしちゃうのが最近の筆者の手口です。

非appengineのプロジェクトでも使いたいものですが、
納品先の事情でCGIベースでしか実装するしかない場合は、
他の選択肢を探さざるを得ません。

仕方なく、テンプレートエンジンを探す訳ですが、
色々比較してみて、結局 mako とやらで実装中です。

Mako Template of Python
http://www.makotemplates.org/

生pythonコードを埋め込めるタイプ。
構文もpythonそのものに酷似しています。
内部的にpython(しかもclassに)に変換しちゃってるらしい。

故に、他のテンプレートファイルを「継承」できるらしい。

例えば、ページのフッター&ヘッダーを差し込みたい場合。
それぞれ別ファイルを作って、includeするのが一般的だと思いますが。

ページ全体をヘッダー&フッター付きでデザインしておいて、
個々のページは内側だけ作って、inheritすれば済みます。しかも1回で。

記述のテイストがPHPに似ているので、
「テンプレートエンジン」として「ラクになってる感」は薄めですが、
継承はなかなか使いでがあります。


ライブラリの構成ファイル群は、
少ない部類に入るような気がします。
スピンアップが早そう。って事ね。
app engineで強引に使ってみるのもアリかもしれません。

2010年5月6日木曜日

app engine SDK では110過ぎの人の誕生日が扱えない?

app engineが、という、pythonのlinux版は、
datetime型は、1900より過去をサポートしません。

1899年生まれの人の誕生日を、strftimeとかすると、ValueErrorを喰らいます。

また悩ましいのが、strftimeの制限なので、
datetime自体は、1899以前を入れようがコンストラクト出来るのです。

例えば、datastoreに誕生日が入っていて、

SDKの _ah/admin/datastore でdatastoreを眺めようとすると落ちます。
うーん。

検索してて気づいたのですが、1900年って、昔懐かしい2000年問題の一部ですね。
http://ja.wikipedia.org/wiki/2038%E5%B9%B4%E5%95%8F%E9%A1%8C

strftimeの動作は、プラットフォーム依存らしいので、
http://www.python.jp/doc/2.5/lib/strftime-behavior.html#strftime-behavior
SDK的はどうにもならない模様。
と言うか、appspot.comでは、逆に1899年以前でも通ります。
本当に実装依存っぽい。

strftimeの内部で、これくらいやっちゃって欲しい。とも思う。

仕方ないので、パッチを当てるしかなさそう。


ネタが細かすぎて、パッチファイルを無くしそうなので、gistに貼りました。


2010年5月2日日曜日

pythonのselfとimportの関係

別エントリでも書いた通り、pythonは、クラスメソッド宣言の中で引数にselfが必要です。

まず前提条件として、プログラム言語には、「暗黙主義」と、「宣言主義」があると思います。いずれも筆者の解釈。

「暗黙主義」の代表は、PHPでしょう。

例えば、PHPは、クオートしてない大文字の単語を、勝手に文字列定数として使用します。変数のドルを忘れてたとしたら?バグります。しかも、連想配列のキーが未定義でも、シレっとnullが戻ります。

もしくは、折角define()したのに、タイプミスしちゃって、似た文字列をキーに使っちゃったりとか。

PHPでは、クラスメソッド内部では、$thisが暗黙で使えます。自動定義と言うべきかも知れません。しかも、クラスの壁を越えられます。クラスメソッド内部から、別クラスの別メソッドを、静的メソッド的に呼び出せます。しかも$thisがそのまま伝わります。

例えば

class one { function one(){ var_dump($this); } }
class two { function two(){ one::one(); } }
$aaa = new two;
$aaa->two();


継承してませんよ。

もう変数のスコープもヘッタクリもありません。

良いか、悪いか、と言ったら、悪い。と言えましょう。

pythonは、完全に「宣言主義」です。

前述のselfは、webを眺めてみると賛否両論。C/Java育ちの人には評判が特に悪いような。しかし別エントリでも書いた通り、クラスメソッドの呼び出し方が何通りも或るので、関数宣言段階でそれを明示することは有効です。

例えば、Javaだったら、静的メソッド呼び出しを使うにはstatic宣言が必要です。pythonのselfは、その逆宣言だと思えば良いでしょう。

デコレータの鑑みるに、どうやらクラスメソッドは通常関数のwrapper的に作用しているようなので、構造上selfが必要だったのかも知れませんが、筆者は結果オーライだと思っています。

「宣言主義」は、importにも現れています。

ディレクトリ名がパッケージ名になっちゃうのも賛否両論ですが、asで別名を振れるので、特に困ることはないはず。

importも含めて、関数もクラス宣言も、オブジェクトとして変数の中に入っちゃってるので、再定義が出来てしまう、という諸刃な側面もあります。

標準状態では、ほとんど何も出来ないのでimportを沢山書きます。ブログなんかで、面倒なのだろうけど、

from ナントカ import *

をやっちゃってる人は多いですが、意図しない置き換えが、発生する可能性があります。

要するに、

  • オレのモジュールの一部が、
  • ナントカの中身で書き換わる可能性がある。


面倒なのは判るけど、モジュール階層から呼び出すべきでしょう。

selfもimportも面倒だろうけど、伊達や酔狂で、ああなってる訳ではないよ。筆者の言いたいのはそういうことです。

2010年4月23日金曜日

pythonにはnew演算子がない

pythonでは、インスタンスの作成で、new演算子を使いません。
というか、「new演算子」という構文が存在しません。

PHPやJavaやらCやらの経験者からすると、
これはやや気持ち悪い。
具体的には小生がそうでした。

ただし、その方法論が腑に落ちると、「new「演算子」」のある言語が「オブジェクト指向言語」に見えなくなってきます。少なくとも小生はそうです。

順番に行きましょう

pythonでは、普通の言語でいうところの「クラス宣言」は有りません。
しかし、同等の機構はあります。クラスオブジェクトの作成です。

http://www.python.jp/doc/2.4/tut/node11.html#SECTION0011320000000000000000

下記の例で言うと、anyclass変数に、クラスオジェクトが入ります。
 class anyclass(object):  pass
インスタンスの作成はどうするかというと、作って有るはずの、クラスオブジェクトをcallしてるわけです。だからnew演算子を付けちゃいけません。「呼んでる」だけだから。
instance_object = anyclass()
これはpython的には、「class宣言は、type型インスタンスを作ってるだけで、それはcallableである」というところです。フツーの言語が、new演算子を起点にして、「コンパイル時」にやってることを、callableを経由して「実行時」にやってる。ここがpythonの肝です。

もちろんこんな空っぽのクラスは何の役にもたちません。とりあえずメソッドを足します。
class hasmethod(object):
 def method1(self): pass

pythonは、言語としては珍しく、メソッドの引数として「自分インスタンスオブジェクト」を第1引数に書かなければなりません。

インスタンスを作ると、クラスメソッドとインスタンスオブジェクトが結びつきます。
instance1 = hasmethod()
instance1.method1()

ここでのポイントは、

instance1.method1() と、hasmethod.method1() は別物である。

ということです。

  • 前者は、インスタンスに結びついたメソッドオブジェクト
  • 後者は、結び付いてないクラスメソッドオブジェクト。
後者は、「結びついてない」ので、
インスタンスオブジェクトをどうにかして渡す必要があります。

それで第1引数 self の出番というわけです。

前者は、「結びついてる」ので、pythonがselfを勝手に足してくれます。故に、インスタンス関数呼び出しでは、self 以外の引数だけを書くわけです。


instance1 == self
とは言え、この調子だと、普通の言語で言うところの、静的メソッドは?このままでは無理です。しかし方法は有ります。

class statichas(object):
 @staticmethod
 def method1(): pass

@staticmethodデコレータを挟むだけです。

フツーの関数宣言は、selfが必要ですが、今度は逆に、selfを入れると怒られます。pythonは、selfを引数に勝手に加えるのを辞めます。staticmethodは、そういうマーキングをやってるらしい。この状態では、method1を直接呼び出すことができます。 http://docs.python.org/c-api/structures.html#METH_STATIC

statichas.method1()

ただしこれでは問題が無くもありません。関数の中からは、クラスもインスタンスも解らないので、クラス内の他のメソッドも使えません。

#逆に、一人完結してます。というアピールに#@staticmethodを使うのは、筆者はアリだと思います。

前述のクラスメソッド表記で呼び出せなくもありませんが、クラスを継承する状況を想定すると、固定で書くのは避けたいですね。

ハイ。そこで出てくるのは、@classmethodデコレータです。フツーの言語の、静的メソッドに相当するのは、むしろコッチでしょう。
class statichas(object):
 @classmethod
 def method1(cls1):pass
引数に必ず1個入ります。わざわざclassmethodと付けたのは意味がもちろんあって、
「「インスタンスオブジェクト」で無いモノ」を付けてね」という意味です。らしい。http://docs.python.org/c-api/structures.html#METH_CLASS 前述のtype型インスタンスなので、歴史的&一般的にselfとは付けません。世間一般にはclsとだけ付けるっぽいですが、小生は3文字変数に辛い思い出があるので、"cls1"にしてます。
statichas.method1()
表面上は、さっきのstaticmethodと同じ使い心地です。しかし、cls1には、statichasクラスオブジェクトが入ってます。classmethod同士を呼び出す分にはこれで行けますね。

statichas == cls1

しかも継承すれば、継承後のクラスオブジェクトがcls1に入っている。

という寸法です。

面白い発想ですね。

具体的には、app engine python-SDKのgoogle.appengine.ext.db.Model.get がlassmethodです。小生は、この辺りの実装を眺めていて、感動すら覚えました。

class「定義」の構文は、フツーの関数定義を「メソッド呼び出しに変換する」処理であると考えれば、腑に落ちると思います。故に、$thisを暗黙で「渡さない」方が何かと都合が良いわけです。

これを利用して、定義済みクラスじゃなくてtypeオブジェクトに、メソッドを後付けできます。「class定義」がコンパイラの仕事じゃないから出きることですね。真の動的言語の何たるかを見た気がします。

そんな訳ですので、フツーのインスタンスメソッドから、classmethodを使うときにはどうするか?構文を区別する必要があります。
self.__class__.method1()
static::method1とか書くより解りやすい気がすると思うのですが、どうでしょう。ダブルコロンとかバックスラッシュとか要らないわけです。オブジェクトだから。

今まで、インスタンス作成、メソッド呼び出し、と色々述べましたが、

表記上の違いはほとんどありませんし、Python内部でのメカニズムの違いも殆どありません。 他の言語でいうところの「クラス定義」は、「タイプ型オブジェクト」でしかないので、「◯◯オブジェクトのメンバ関数を呼ぶ」という機構は統一できてるわけです。


  • インスタンスメソッドを呼び出す場合
    • instace1インスタンスオブジェクトのmethod1メンバをcallする。
    • 特にmethod1にマークは付いてないので、引数の先頭にinstance1を挿入する
  • staticmethodを呼び出す場合
    • class1タイプオブジェクトのmethod1メンバをcallする。
    • staticmethodマークが付いてるので、引数には何も足さない。
  • classmethodを呼び出す場合
    • class1タイプオブジェクトのmethod1メンバをcallする
    • classmethodマークが付いているので、引数の先頭にclass1を挿入する。



呼び出し可能なオブジェクト(特にcallableと呼ぶ)を、呼んでる(call)だけ。

これに付きます。


これが腑に落ちると、途端に「new演算子のあるオブジェクト指向言語」が駄目言語に見えます。

筆者はここまで徹底したオブジェクト指向を他に知りません。
#ご存知の方は、教えてくれなくてもいいです。長くなりそうなんで。

識者が言うところによると、pythonは、広義には関数型言語らしい。
haskelには気絶しそうになりましたが、大分判りやすくて助かります。

2010年4月12日月曜日

C/C++言語の反省

色々なエントリにバラバラに書いちゃったので
一旦纏めます。

21世紀現在に至っても、
世の中の手続き型プログラミング言語は、
どこかしらC/C++に似た部分があります。

言い換えると、C/C++言語の反省点を踏まえて
言語設計をしていると言えます。

C/C++言語の、筆者の考える反省点は次のとおりです。

  • boolean型が無い。
  • 関数の戻り値として、1個しか返せない。
  • 生ポインタ。
  • 故にメモリ管理が手動
  • (template)
  • プリプロセッサ
  • #include
  • (例外)
  • (名前空間)
  • (多重継承)
そもそもの話、C言語自体設計が古いので、
現状のメモリ事情やら、ソフトウエア技術やらに即して居ません。

象徴的なのが、「きめ細かいメモリ管理」を「人間がやる」ところ。

メモリが狭いって言ったって、携帯電話でもメガの単位はあります。
キロバイト単位を節約して、8ビットCPUを絞り出していた時代とは違います。
その証拠に、イマドキのケータイアプリは、概ねJavaです。

ポインタはC/C++の歴史的魔道と言えます。
メモリ管理方法が極めて少ないので、多重ポインタで実装するしかありませんが。
その中のどこかに構造体ポインタが挟まってたらもう駄目です。
この宣言がどエラい苦労します。
もはや呪いのアイテムです。

Cの時代は、メモリ確保と、その用法が完全に無関係なので、
何バイト確保しようが、それをいくらでも逸脱できます。
故に、バッファオーバーラン等の危険が常に付きまといます。
気をつけます、って言ったって、限界があるでしょうそりゃあ。

C++では、一応class宣言があって、new/deleteが有りますが、
deleteが手動だったりしますし。

プリプロセッサは、
プログラムソースを、コンパイラに入れるまえに書き換える。
コンパイラの機能があまりにも少ない故の、魔道具です。

「構造体宣言の前半の中括弧まで」を展開するマクロとか
ソースとマクロ定義のどっちを見ても、気持ち悪そうな実装が出来ます。

「関数の宣言に、特定のナニかを付け加えるマクロ」なんかは、
オープンソース業界の、軽量言語の実装では今でも散見します。

#includeは、
関数定義を、外部ファイルからサラリと読み込む方法がないので、
ソースプログラムを書いたら、*.c/cppと*.hの一組を書くのが「お約束」で、
「ウチの関数を使いたかったら#includeしてね?」って事になってますが、
その*.hは、利用のためだけじゃなくて、本体の実装のためでもあるので、
あちこち#includeを渡り歩いています。

これがまた面倒くさい。
多重include防止の為の #ifdef とか、もう生活の知恵の極致です。

#includeの向こう側が書き換わっちゃってると、
関数の引数とか、構造体の形が変わっちゃってるかもしれないので、
全てリビルドせざるを得ません。

そのためのmakeやらmakefileやらはもちろん或る訳ですが、
仕事を増やすための仕事に絶望した!

関数の戻り値が、1個しか戻せないのは、結構あちこちでハマリます。
構造体をnewしてreturnするとかは、C++ではあまりやりたくないので
1個だけreturnして、残りは引数に、参照渡しで入れ物を貰う。

C++では、「オブジェクト指向っぽいナニカ」が出きるようになりましたが、
多重継承という呪いのアイテムも付いてきました。

仮想関数やら、オーバーライドやらは、Cの延長線上では、
関数ポインタで実装するしかないわけですが、
ネイティブコンパイラであるが故に、「関数の順番」が非常に重要です。
#コンパイルしちゃった後は、オフセットでしか参照してないらしいので。

マイクロソフトも、MFCやらOLEやらで、七転八倒した形跡があります。
#そして、やっぱり辛くて、C#を産むわけですよ。

とまあ、反省することしきりですが、

筆者がC/C++を使わなくて済んでいるのは、
(例えば)python/PHPの作者がC/C++で実装しているお陰。

ありがたいことです。