2006年05月12日 17:00 [Edit]

Perl Monger の質問 - AUTOLOADって他でどうやるの?

PerlのOOにおける強力な機構の一つに、AUTOLOADがあります。

具体的に他の言語でAUTOLOADを実現する方法にはどんなものがあるでしょうか?


たとえば、こんなことをしてほしいClassを考えます。

use strict;
use warnings;
use Unicode::Char;

my $u = Unicode::Char->new;
binmode STDOUT, ":utf8";
# 小飼弾と表示
print $u->u5c0f, $u->u98fc, $u->u5f3e, "\n";

Perlでは、以下で出来ます。

package Unicode::Char;
use strict;
use warnings;
use Carp;
our $DEBUG = 1;

sub new {
    my $pkg = shift;
    return bless \eval{ my $scalar }, $pkg;
}

sub DESTROY{} # so AUTOLOAD will not handle this

sub AUTOLOAD{
    my $self = shift;
    my $method = our $AUTOLOAD;
    $DEBUG and carp $method;
    $method =~ s/.*:://o;
    $method =~ s/^u_?//o;
    return chr(hex($method));
}

1;

あるいは、AUTOLOAD()を以下のように書き換えて、AUTOLOADは最初の一回目の呼び出し時のみに使われるようにも出来ます。

sub AUTOLOAD{
    my $method = our $AUTOLOAD;
    $DEBUG and carp $method;
    $method =~ s/.*:://o;
    $method =~ s/^u_?//o;
    no strict 'refs';
    *{$AUTOLOAD} = sub {
        my $self = shift;
        return chr(hex($method));
    };
    goto &$AUTOLOAD;
}

要は動的にかつeval()に頼らずにメソッドを生成しているわけです。

これって他のLLではどうやってやるんでしょう?

さらに詳しいことを知りたい人は、↑のAdvanced Perl Programmingを読みましょう。

Dan the Perl Monger

追伸:

rubyco(るびこ)の日記 - メソッド名自動生成
Danさんからお題が出ていたのでRubyで書いてみました。(Danさんのこのエントリ、なぜかトラックバックもコメントもできない…)

へ?と見てみたら、trackbackの設定のところで「する」にも「しない」にもradio buttonが付いてないというちょっと奇妙な事態になっていました。再構築したらなおったので皆さん改めてTBくださいませ

というか、こちらからTBとばしちゃいます。

回答編(順不同):
Ruby
rubyco(るびこ)の日記 - メソッド名自動生成
PHP
p4lifeのメモ - 「Perl Monger の質問 - AUTOLOADって他でどうやるの?」:PHP編
Gauce (scheme)
shiroさんによるコメント参照
Squeak (smalltalk)
sumim’s smalltalking-tos - 起動すべきメソッドが見つからないメッセージに対処する
Python
パパパパパイソン - メソッド名自動生成
へいきちさんのコメント参照
TCL
shiroさんのコメント参照

これでLLの主なところは揃ったのだけど、常にmissing methodが呼ばれるものばかりで、perlのgoto &$AUTOLOADに相当するものがまだにゃいなあ....


この記事へのトラックバックURL

この記事へのトラックバック
 Perl5にはAUTOLOADという機能があります。Perlじゃなくてもありま...
Common LispでPerl5のAUTOLOADを実現【八発白中】at 2010年12月22日 22:08
Perlでもgotoを使えば、本当の継続(continuation)が可能であることを示す。 継続ってなんのことだかさっぱりわからない一は、以下にあらかじめ目をとおしておいていただきたい。 なんでも継続 なんでも継続、Perl で。 : torus solutions! 404 Blog Not Found:継...
perl - to goto or not to goto, that's the continuation【404 Blog Not Found】at 2007年04月18日 06:51
各言語での未定義メソッドの呼び出し&メソッド動的定義。ふむふむ。ちょうどこの前「method_missingってPerlでどうやるんだろ?」と思って調べたところでした。 メソッド名自動生成&メソッド動的定義(Ruby)の「オブジェクトごとにメソッドを定義する」の別解。 class As
[ruby] Perl Monger の質問 - AUTOLOADって他でどうやるの?【daily gimite】at 2006年05月19日 11:51
JavaScript でもメソッド名自動生成はできる……といっていいんだろうか? JavaScript の一実装に過ぎない SpiderMonkey の独自拡張機能にあるだけで ECMAScript はもちろん JScript でもできないから
JavaScript でメソッド名自動生成【Days on the Moon】at 2006年05月18日 04:17
Perl Monger の質問 - AUTOLOADって他でどうやるの? http://blog.livedoor.jp/dankogai/archives/50491359.html Python版がまだ、ということなので書いてみました。こんなかんじ。 class UnicodeChar: def __getattr__(self, attr): attr = attr.replace(”u”,””) return...
[python]メソッド名自動生成【パパパパパイソン】at 2006年05月14日 00:30
 Perl Monger の質問 - AUTOLOADって他でどうやるの?ってのがあったのですが、僕はwantarrayに相当するものが分からなくて困ったことがあります。 (PerlのモジュールをPHPとかRubyに移植してて)
wantarrayって他でどうやるの?【浅倉卓司のログ】at 2006年05月13日 18:30
意外にも「CPAN汁」という声がmailで上がってたので、いくつかの機能をまとめてUnicode::Char 0.01 を Releaseしました。CPANの更新を待てない人はこちらから。 404 Blog Not Found:Perl Monger の質問 - AUTOLOADって他でどうやるの?たとえば、こんなことをしてほし....
perl - Unicode::Char 0.01 released!【404 Blog Not Found】at 2006年05月13日 15:15
404 Blog Not Found:Perl Monger の質問 - AUTOLOADって他でどうやるの? 以下は,PHP による「Perl の AUTOLOAD」実装のメモ. <?php class Unicode_Char { function __get($v) { return pack('n', hexdec(preg_replace('/^u(.*)/i', '$1',
「Perl Monger の質問 - AUTOLOADって他でどうやるの?」:PHP編【p4lifeのメモ】at 2006年05月13日 13:04
この記事へのコメント
↑インデントがなくなってるし、バックスラッシュが ? になってる。
これではダメですねorz.
? はバックスラッシュってことで。

import sys, codecs
class my_unicode:
..def __getattr__(self, attrname):
....return (lambda: unicode('??' + attrname, 'raw-unicode-escape'))


if __name__ == '__main__':
..(e,d,sr,sw) = codecs.lookup('utf-8')
..sys.stdout = sw(sys.stdout)
..u = my_unicode()
..print u.u5c0f() + u.u98fc() + u.u5f3e()
Posted by へいきち at 2006年05月14日 00:41
pythonで書くとこんな感じですかね。

import sys, codecs
class my_unicode:
def __getattr__(self, attrname):
return (lambda: unicode('??' + attrname, 'raw-unicode-escape'))


if __name__ == '__main__':
(e,d,sr,sw) = codecs.lookup('utf-8')
sys.stdout = sw(sys.stdout)
u = my_unicode()
print u.u5c0f() + u.u98fc() + u.u5f3e()
Posted by へいきち at 2006年05月14日 00:34
この機能はautoloadというより、他の言語でmissing method handlerに相当する機能のように思えます。Rubyでは確かmethod_missingだったような。

Gaucheでは

(define-class <unichars> ())
(define-method slot-missing ((c <class>) (u <unichars>) name)
(ucs->char (string->number (string-drop (x->string name) 1) 16)))

としておけばスロットアクセスで文字を返せます:

(define u <make <unichars>)
(ref u 'u5c0f) => #\小

でもLisp系の場合、素直に手続きにする方が使い勝手が良さそうです。

Tclは確かトップレベルで未知の手続き名が参照されるとunknownという手続きがかわりに呼ばれるというメカニズムがあったので、オブジェクトなど介さずに [u5c0f] などと書いたら文字になる、というものを書くことができそうです。


Posted by shiro at 2006年05月13日 06:54
PHP はこんな感じになりました.
http://d.hatena.ne.jp/p4life/20060512/1147455438
Posted by moyashi4life at 2006年05月13日 03:01