スポンサーサイト
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
まちがってたら恐縮なのですが、
ポリモフィズムって、
Hoge.pm
package Hoge;
use strict;
use warnings;

sub new {
my $self = shift;
bless {}, $self;
}

sub say {
print 'Hogeだよ' . "\n";
}

1;


Foo.pm
package Foo;
use strict;
use warnings;

sub new {
my $self = shift;
bless {}, $self;
}

sub say {
print 'Fooだよ' . "\n";
}

1;


main.pl
use Hoge;
use Foo;
use strict;
use warnings;

my @array = (Hoge->new(), Foo->new());

$_->say() for @array;

結果:
Hogeだよ
Fooだよ

こんな感じに書くもんだと、思ってたら、


use strict;
use warnings;

my ($c, $d);
$c->{'hoge'} = sub { print "hoge1だよ" . "\n" };
$d->{'hoge'} = sub { print "hoge2だよ" . "\n" };

my @arry = ($c, $d);

$_->{'hoge'}->() for @arry;


結果:
hoge1だよ
hoge2だよ

こんな感じのソースを見た。



まあ、もうなんでもありだよね。
use strict;
use warnings;

for (
sub { print '1' . "\n" },
sub { print '2' . "\n" }
){
$_->();
}

1
2

オブジェクトがねーじゃん、これじゃ。とか言われそうだけど。



よくよく考えたら、一番はじめの
「Hogeだよ
 Fooだよ 」
の例もまったく別のオブジェクトのメソッドだな。

Humanからサラリーマンと、教師をつくってー とか やってないね。
まあ、いいか.....
スポンサーサイト
色んな言語で、Rubyをみてみよう。
名前付き引数っぽいことをしてみる。

[Ruby]
def f(a)
p a[:hoge]
end

f :hoge=>1, :bar=>2


[Perl]
sub f {
my $c = shift;
print $c->{hoge};
}

f { hoge=>1, bar=>2 };


[JavaScript]
(function(a){ alert(a.hoge) })({hoge:1, bar:2});

上記3つの結果:
1




Rubyのyieldを他の言語で見てみる
[Ruby]
def f
yield
end

f do puts 'Hoge' end


[Perl]
sub f {
my $c = shift;
$c->();
}

f sub { print "Hoge" . "\n"; };


[JavaScript]
(function(f){ f() })(function(){ alert("Hoge") });

上記3つの結果:
Hoge


Acme::Bleach を読んでみた。
Acme::Bleach を読んでみた。
(※ Acme::Bleach に関しては http://e8y.net/mag/010-acme-bleach/ )

わからないところも多いが、
見よう見まねで次のソースを書いてみた。

[Nakusu.pm]
package Nakusu;
sub to_white { my $a = unpack "b*", $_[0]; $a =~ tr/01/ab/; $a; }
sub to_org { my $a = shift; $a =~ tr/ab/01/; pack "b*", $a; }
open 0;
(my $str = join "", <0>) =~ s/.*^\s*use\s+Nakusu\s*;\n//sm;
if( $str =~ /ab/ ){
eval to_org($str);
exit;
}
open 0, ">$0";
print {0} "use Nakusu;\n", to_white($str) and exit;


これを、

[hoge.pl]
use Nakusu;
print "Foo!!" . "\n";

このように使う。

このhoge.pl を一度実行すると、hoge.pl の中身は次のようになる。
なお、ab.... となっているところは、
見やすいように改行してある(本来は1行である)。

[hoge.pl]
use Nakusu;
aaaabbbaabaabbbabaababbaabbbabbaa
ababbbaaaaaabaaabaaabaaabbaaababbb
babbabbbbabbabaaaabaabaaaabaaabaaa
baaaaaaabaaabbbabaaaaaaabaaabaaabaa
aabbbabaabbbabbaabaaabaabbabbbaaab
abaaaa

さて こうなった、 hoge.pl をもう一度、実行すると、

Foo!!

と表示される。




ポイントは、
■ open 0
で、自分自身のファイルを開いているところ。

■ eval to_org($str);
と、 eval で評価しているところ。

■ exit;
で、巧妙に、処理を終了しているところだろうか。


参考資料:
http://search.cpan.org/dist/Acme-Bleach/lib/Acme/Bleach.pm
リフレクションを使えば、privateなメソッドを呼び出せる
Javaでprivateなメソッドを呼び出す。


getDeclaredMethod()

setAccessible(true)
のコンボで可能となる。

サンプルソースはこちら
import java.lang.reflect.Method;
class F {
private void f(){ System.out.println("ffff"); }
}

public class H {
public static void main(String[] args) throws Exception {
Class cl = Class.forName("F");
Method method = cl.getDeclaredMethod("f", null);
method.setAccessible(true);
method.invoke(cl.newInstance(), null);
}
}



参考資料:
http://bingobingobingo.blog49.fc2.com/blog-entry-774.html
http://www.ne.jp/asahi/hishidama/home/tech/java/reflection.html



ちょっとPerlで遊んでみよう。 part2
sub b { print 'b'; return \&c; }
sub c { print 'c' }

(sub { print 'a'; return \&b; })->()->()->();


もういっちょ
map 1+(sub{ print "$_[0]" . "\n" })->($_), 1..100;




leopard での cpan install
それほど、 leopard つかってないのだが、

env LANG=C sudo -H cpan


でインストールするのがよさげである。


http://kawa.at.webry.info/200602/article_10.html
http://chain.main.jp/weblog/archives/2005/06/cpaninstall.html
http://bingobingobingo.blog49.fc2.com/blog-entry-761.html


CPANにあるモジュールのソースを読むには
CPANにあるソースを読みたいと思ったときどうすればよいのでしょうか?
Date::Simpleを例に考えていきたいと思います。

まず、CPANで欲しいモジュールのページを探すには
CPAN サーチへいくのがよいでしょう。

http://search.cpan.org/

ここで、Date::Simple と打って検索してみましょう。
http://search.cpan.org/~yves/Date-Simple-3.02/lib/Date/Simple.pm
へたどりつけたでしょうか?

左上のほうに、 Source というリンクがあると思います。
ここをクリックするとソースが読めます。
http://search.cpan.org/src/YVES/Date-Simple-3.02/lib/Date/Simple.pm


さて、このソースのテストはどうなっているのでしょうか?
すこし興味がわきませんか?
ソースのあるディレクトリから階層を上がってみましょう。
http://search.cpan.org/src/YVES/Date-Simple-3.02/

CPANにあるテストは t という名前のディレクトリにあるのでここを見てみることにします。 date.t というのがありましたね。 これがテストのソースになります。


このテストのソースはとても参考になります。
たとえば、Date::Simple の引き算が閏年にちゃんと対応できているか気になったとしましょう。 date.t を参考に私なりにコードを書くとこうなりました。
use strict;
use Date::Simple;
use Test::More qw(no_plan);

foreach (
[2008, 3, 1, 1, '20080229'],
[2008, 3, 1, 2, '20080228']
)
{
my $d = Date::Simple->new(@$_[0,1,2]);
is( $_->[4], ($d - $_->[3])->as_d8, '引き算のテスト' );
}


内部クラスから呼び出し元の this にアクセスするには
内部クラスから呼び出し元の this にアクセスするには 呼び出しもとクラス名.this
public class H {

interface F{ H f(); };
public static void main(String[] args) {
new H().h();
}

public void h(){
new F(){ public H f(){ System.out.println("Java.."); return H.this; } }
.f()
.g()
.g();
}

public H g(){ System.out.println("..Nanntoiu"); return this;}

}


読みにくし......


結果:
Java..
..Nanntoiu
..Nanntoiu
Javaの逆コンパイル
http://www.atmarkit.co.jp/fjava/javatips/073eclipse025.html

こいつを試してみた。

jadの
Readme.txtを軽く読んでやってみると
.jad というファイルができあがるので、これを cat などでみてみると逆コンパイルされているのがわかる。
スパムのコメント消してたら
羊からのコメント消してしまった。
ごめんなーさい。
ちゃんと 確認はしてます。
ソースフィルタで俺的日本語プログラミング言語を作ってみる
次のソースはPerlプログラムである。
use Bingo_Nakanishi;
厳格にいくよ;
UTF8を使うよ;


宣言 $変数だよ = 'なにかしゃべるよ';
言う "$変数だよ";

上記を実行すると、
なにかしゃべるよ

となる。

これは、ソースフィルタを使ったからである。
早い話が、実行される前にソースを書き換えちゃうのである。
(間違ってたらごめんなさい)

参考資料はこちらである。
http://search.cpan.org/~rgarcia/perl-5.10.0/pod/perlfilter.pod

気になる Bingo_Nakanishi.pm であるが、
package Bingo_Nakanishi;

use Filter::Util::Call;

sub import {
my ($type) = @_;
my ($ref) = [];
filter_add(bless $ref);
}

sub filter {
my ($self) = @_;
my ($status);


if( ($status = filter_read()) > 0 ){
s/厳格にいくよ/use strict/;
s/UTF8を使うよ/use utf8; binmode(STDOUT, ":utf8")/;
s/宣言/my/;
s/言う/print/;
}

return $status;
}

1;

となってます。
参考資料から、要りそうなところだけ、使って書き換えました。


ちなみに、まだ、
http://search.cpan.org/~pmqs/Filter-1.34/Call/Call.pm
を読んでません.....
JavaをJSライクに
public class H {

interface F{ F f(); };
public static void main(String[] args) {
new F(){ public F f(){ System.out.println("f"); return this; } }
.f()
.f();
}

}

結果:
f
f


new 親クラス という書き方で、無名クラスを作れる。
ということでいきなり実装して呼び出せる。
プログラムの途中のデータをあとで使う方法
Perl には Data::Dumper というものがあります。
これは、変数の中身をいっきに表示してくれる、とっても心強い味方です。
使い方をみてみましょう。

use Data::Dumper;

print Dumper [1,2];

結果は、
$VAR1 = [
1,
2
];

これは、つぎのようにして、プログラムの中でもう一度使えます。
my $VAR1 = [
1,
2
];
print @{$VAR1};

結果は、
12

このData::Dumperで出力した値をファイルへ出力すると文字列として
データの状態を保存できます。

Perlには文字列をプログラムとして実行するevalというのがありますので、
my $str = '$VAR1 = [
1,
2
]';

eval $str;

print @{$VAR1};

こんな感じでデータを復元できます。

慣れてくると、
use Data::Dumper;

print @{(eval Dumper [1,2])};

こんな、意味のない書き方もできます。



aaa.txtに、
$VAR1 = [1,2];

こう保存されてるとすると、

pen my $f, '<', 'aaa.txt';
while( my $line = <$f> ){
eval $line;
}
print @{$VAR1};

こんな感じで復元できる。


http://d.hatena.ne.jp/minesouta/20070920/p1
を見るともっとうまく復元できるっぽいが、今はとくに復元する必要がないので、
必要になったときにもっと調べてみよう。

JavaScriptのthis  イベント駆動の場合
※環境:Firefox  prototype.js使用
onload = h;
function h(){ Event.observe($('id1'), 'click', function(){ alert(this) })};


結果は、
object HTMLDivElement

thisはクリックされたやつになっちゃうんですね。

そこで、bind
onload = h;
function h(){ Event.observe($('id1'), 'click',
function(){ alert(this) }.bind(this))};


結果は、
object Window



それではお次のソースはどうだろう。
onload = h;
function A() { this.b = 1};
A.prototype = {
my_alert : function(){ alert( this.b ) }
};
var a = new A();
function h(){ Event.observe($('id1'), 'click', a.my_alert)};

結果は、
undefined



では、どうすればよいのか。
onload = h;
function A() { this.b = 1};
A.prototype = {
my_alert : function(){ alert( this.b ) }
};
var a = new A();
function h(){ Event.observe($('id1'), 'click', a.my_alert.bind(a))};


結果は、
1

http://d.hatena.ne.jp/cloned/20070301
こちらにある通り、bind で thisになってほしいやつを与えなければならないらしい。
さらに、 bindAsEventListener というのを使うと、thisの件に加えて、イベントオブジェクトをブラウザ互換対応で渡してくれるとも載っていますね。

さらに、
onload = h;
function A() { this.b = 1};
A.prototype = {
my_alert : function(){ alert( this.b ) }
};
var a = new A();
function h(){ Event.observe($('id1'), 'click', function(){ a.my_alert() })};

でも、結果は
1
になるとありますね。

ということは、
onload = h;
function A() { this.b = 1};
A.prototype = {
my_alert : function(){ alert( this.b ) }
};
function h(){ Event.observe($('id1'), 'click',
function(){ new A().my_alert() })};

こんな風に 変数a を宣言しなくてもいけちゃうわけか。

次のように書いて、表示結果をみると
function h(){ Event.observe($('id1'), 'click',  
function(){ alert(this); new A().my_alert() })};

object HTMLDivElement
1

と, alert(this)の部分から、
this は呼び出しもとわかるが、 A() は new してるので
alert( this.b ) の this.b は prototype プロパティに登録された b を見つけられるというわけか。




参考までに全体ソースはこんな感じ
<html>
<head>
<script type="text/javascript" src="prototype.js"></script>
<script type="text/javascript">
onload = h;
function A() { this.b = 1};
A.prototype = {
my_alert : function(){ alert( this.b ) }
};
function h(){ Event.observe($('id1'), 'click', function(){ alert(this)})};
</script>
</head>
<body>
<div id="id1">aaaaaaaa</div>
<div id="id2"></div>
</body>
</html>

ちょっとPerlで遊んでみよう。
(sub { print 'h' . "\n"; })->();

(bless {})->m();

sub m {
print 'm' . "\n";
}

(bless {name => sub { print 'hello' . "\n"; }})->{'name'}->();
(bless {name => sub { print 'hello' . "\n"; }})->m();
whileとforの違い
Perlにおいてwhileとforはまったく違う。

whileの条件部分はスカラーコンテキストであるがforの条件部分はリストコンテキストなのである。
ブログ検索

プロフィール

ビンゴ中西
Perlが好きである。
プログラミング言語のほとんどは独学。独学の過程で多くのプログラム仲間にも色々教わりました。

FC2カウンター

カレンダー

05 | 2008/06 | 07
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 - - - - -

ブロとも申請フォーム

この人とブロともになる

| ホーム |
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。