スポンサーサイト
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
クロージャの使いどころ
Perlで定数を使おうと思うと、あるモジュールを use しないといけなかったりしますが、クロージャを使えば、自前で作れたりします。

僕は、値を書き換えないように決めの問題(ルール)にしてしまえばいいと思うので、ハッシュテーブルか設定ファイルで済ませますが、以下のソースでクロージャによる定数(のようなもの)が作れます。

use Data::Dumper;

sub make_const {
  my $o = { %{$_[0]} };        # こいつに隠し持つ
  return sub { $o->{$_[0]} };  # この関数によってしかアクセスできないようにする
}

my %h         = ('a'=>1, 'b'=>2);
my $h_const   = make_const(\%h);

print $h_const->('a') . "\n";
$h{'a'} = 10;
print $h_const->('a') . "\n";

$h_const->('a') = 9;             # 文法エラー:関数呼び出しに代入は不可能

# 無名ハッシュでかっこ良く生成する方法
my $n_const = make_const({'c'=>2, 'd'=>3});  


なお、この方法はJSでも使えそうです。


よくかんがえたら、隠し持つのは { } と、無名ハッシュでかぶせる必要なかったなぁ。
sub make_const {
  my %o = %{$_[0]};          # こいつに隠し持つ
  return sub { $o{$_[0]} };  # この関数によってしかアクセスできないようにする
}
スポンサーサイト
解決
http://bingobingobingo.blog49.fc2.com/blog-entry-861.html

の問題ですが、

@c = readline $fh{'b.txt'};

で、解決しました。
<>は ファイルの中身を読み込む readline と、
グロブを扱う、 glob の2通りにとれてしまうので、
ファイル読み込んでほしいときは、 readline と明示してあげればよいのでした。
Perlの無名シリーズ
Perlで、
無名配列、無名ハッシュ、無名関数の作り方を紹介するよ。

無名配列は、
 [ ]  
で作れるよ。
[1,2,3] こんな感じ。

無名ハッシュは、
 { } 
で作れるよ。
{'a'=>1, 'b'=>2} こんな感じ。

無名関数は、
 sub { } 
で作れるよ。
sub { print "Hello World" . "\n"} こんな感じ。


無名シリーズは、リファレンスが返ってくるんだよ。
だから、次のソースの$cは同じ意味だよ。

無名配列:
$c = [1,2,3];

# ↑ 同じ ↓

@a = (1,2,3);
$c = \@a;


無名ハッシュ:
$c = {'a'=>1, 'b'=>2};

# ↑ 同じ ↓

%a = (a=>1, b=>2);
$c = \%a;


無名関数:
$c = sub { print "Hello World" . "\n" };

# ↑ 同じ ↓

sub a { print "Hello World" . "\n" };
$c = \&a;



無名配列の使いどころとしては、いろいろあるけど、こんな感じだよ。
sub a {
 $hoge = shift;
 $foo  = shift;

 for(@$foo){
  print "$hoge" . " $_" . "\n";
 }
}

a("Hello", [1,2,3]);


無名ハッシュの使いどころとしては、いろいろあるけど、こんな感じだよ。
sub a {
 $hoge = shift;

 print "$hoge->{'foo'}" . "\n";
 print "$hoge->{'bar'}" . "\n";

}

a({'foo'=>1, 'bar'=>2});


無名関数の使いどころとしては、いろいろあるけど、こんな感じだよ。
sub a {
 $hoge = shift;
 $foo  = shift;

 for(1..3){
  $foo->($hoge);
 }
}

a("Hello", sub{ $bar=shift; print "$bar" . "\n"; });

上記の例は、use strict; 使ってないけど、皆はちゃんと use strict; 使わないとダメだよぉ。
あー Perlのファイルハンドルわけわかんない
参考資料:
http://d.hatena.ne.jp/dayflower/20080605/1212652674
http://www.ipa.go.jp/security/awareness/vendor/programming/a04_02_main.html

思った通り動く:
use Data::Dumper;
use IO::Handle;

open $fh{'b.txt'}, 'b.txt' or die;

chomp (@c = $fh{'b.txt'}->getlines);
print Dumper \@c;

思った通り動かない:
use Data::Dumper;

open $fh{'b.txt'}, 'b.txt' or die;

@c = <$fh{'b.txt'}>;
print Dumper \@c;

Perl は 行入力演算子 <> でファイルの中身を読み込める。
でも、glob関数ってのも <> というまったく同じ書式。
glob関数は glob() ともかける。
よって、後者のソースは glob(fh{'b.txt'}) とみなされちゃってるもよう.....


こっちも動く:
use Data::Dumper;
use IO::File;

$fh{'b.txt'} = new IO::File "b.txt";
chomp (@c = $fh{'b.txt'}->getlines);
print Dumper \@c;
$fh{'b.txt'}->close;
Perl で2次元配列
相方が、ファイルの中身を2次元配列に入れたい。
みたいなことを言ってたんだけど、こんなのしか書けない。
こんなのワンライナーでいけるのだろうか。

use strict;
use Data::Dumper;

my @c = map { chomp; split /r/ } <DATA>;
my $d;
for(my $i=0; $i < int @c; $i++){
   $d->[$i] = [split /n/, $c[$i]];
}

print "$d->[0]->[0]" . "\n";
print "$d->[0]->[1]" . "\n";
print "$d->[1]->[0]" . "\n";

print Dumper $d;

__DATA__
AAAnBBBr
CCCCnDDDDnEEEr
FFFnGGGr

いけて、このあたりかなぁ。
use strict;
use Data::Dumper;

my $d;
my $i=0;
$d->[$i++] = [split /n/] for map { chomp; split /r/ } <DATA>;

print "$d->[0]->[0]" . "\n";
print "$d->[0]->[1]" . "\n";
print "$d->[1]->[0]" . "\n";

print Dumper $d;

__DATA__
AAAnBBBr
CCCCnDDDDnEEEr
FFFnGGGr

use strict 使わないなら、1行かなぁ。
use Data::Dumper;

$d->[$i++] = [split /n/] for map { chomp; split /r/ } <DATA>;

print "$d->[0]->[0]" . "\n";
print "$d->[0]->[1]" . "\n";
print "$d->[1]->[0]" . "\n";

print Dumper $d;

__DATA__
AAAnBBBr
CCCCnDDDDnEEEr
FFFnGGGr


なんか、
print "$d->[0][0]" . "\n";
print "$d->[0][1]" . "\n";
print "$d->[1][0]" . "\n";
矢印、省略できたぁ。

んじゃ、次の表記で、C言語っぽい表記になるなぁ
use Data::Dumper;

$d[$i++] = [split /n/] for map { chomp; split /r/ } <DATA>;

print "$d[0][0]" . "\n";
print "$d[0][1]" . "\n";
print "$d[1][0]" . "\n";

print Dumper \@d;

__DATA__
AAAnBBBr
CCCCnDDDDnEEEr
FFFnGGGr
JSのオブジェクトの作り方 色々
({ f:function(i){ this.a = i; return this } }).f(3).a
new function(i){ this.a = i; return this }(4).a
new function(){ var a=5; this.a = a }().a
Perlのコンテキストを判断する基準
Perlというものには、コンテキストという概念があって、慣れるまでは非常にやっかいである。
コンテキストというものは何なのかということをPerlで考える前に、日本語で考えてみよう。

1 はしで食べる。
2 はしを渡る。

両者ともに「はし」という単語を使っているが、
1つ目の例は「箸」であることがわかるし、2つ目の例は「橋」であることがわかる。

これは、文脈によって、「はし」の違いを判別できたのである。
このようにPerlでも文脈により、プログラムを処理してくれるのだ。

次のソースを見ていただきたい。各行のコメントに左辺の値にどのような値が入るのか示してある。

  1 use strict;
  2 
  3 my $c    = (5,6,7);          # スカラーコンテキスト    7
  4 my @cs   = (5,6,7);          # リストコンテキスト      (5,6,7)
  5 
  6 my @ds   = (1,1,1,1);        # リストコンテキスト      (1,1,1,1)
  7 my $d    = @ds;              # スカラーコンテキスト    4
  8 
  9 my $e    = '1' + '1';        # +演算子が数値とみなし    2
 10 my $f    =  1  .  1;         # .演算子が文字列とみなし '11'

3行目であるが、この例が一番わかりにくいかもしれない。
これは左辺が$cであるため、(5,6,7)の一番最後の数字7が入っている。
7行目では、$dに配列の大きさが代入されている(こちらの方は、3行目よりやや理解しやすいであろう。

3行目、7行目ともにスカラーコンテキストなのであるが、それはどのように判断するのであろうか?

Perlでは$が頭につく変数は、スカラー変数である。
スカラーとはただ一つの値を持つものという意味である。
3行目と7行目はこのスカラー変数が左辺にきている。
つまり、この行の左辺は、ただ一つの値を欲しているのである。
3行目はただ一つの値として、7を、
7行目では、ただ一つの値として配列の大きさ 4を代入しているのである。

4行目と6行目はリストコンテキストである。左辺が配列になっているからだ。
配列には、複数の値を入れることができるので、右辺の内容が配列として保たれる。


このように、スカラーコンテキストであるのか、リストコンテキストであるのかは、その文が、「ただ一つの値」を欲しているのか、「複数の値」を欲しているのかで判断がつく。

また、9行目と10行目であるが、これは演算子が文脈を判断して処理を行っている例である。
Perlでは、

+演算子は数値を加算するもの。
.演算子は文字列を連結するもの。

と決まっているので、上記ソースのように処理が行われるのである。



ただ、
whileとforの条件部分のように、
パッと見では、判断しづらいコンテキストも存在する。
http://bingobingobingo.blog49.fc2.com/blog-entry-805.html
for in の罠
JavaScript の for in について。

配列を操作しようと思って、
次のように書いてもうまくいかない。
for(i in [1,'b']){ console.log(i) }
↑を実行すると

0
1

と表示される。


言い過ぎかもしれないが、JavaScriptというのは全部、ハッシュでできていると考えてよい。そこで、for in は、ハッシュのキーを取り出してくれるようにできている。JavaScriptの言葉で言うと、プロパティを取り出してくれる。
そこで、
a = [1,'b']
for(i in a){ console.log(a[i]) }
と、すると、

1
b

と、配列の中身を取得することができる。



でも、これではなにかうっとうしい。配列を一気に操作する良い方法はないだろうか?
ということで偉い人が次のような方法(each関数)を思いつきました。
Array.prototype.each = function(f){
   for(i=0;i<this.length;i++){
      f(this[i])
   }
};

[1,'b'].each( function(i){ console.log(i) } )


参考資料: http://d.hatena.ne.jp/amachang/20070202/1170386546
phpでクラスを書く
<?
class H { function f(){ print 'a'; return $this; } }
class R { var $a=1; }
class G { static $b=3;
          function b(){ return self::$b; }
          function add(){ self::$b++; }
        }

$h = new H();
$h->f()->f();
print "\n\n";
print "--------\n";

$r = new R();
print_r($r);
$r->a++;
print_r($r);
print "\n\n";
print "--------\n";


$g1 = new G();
$g1->add();
$g2 = new G();
print $g2->b();
print "\n\n";
?>


結果:
aa

--------
R Object
(
[a] => 1
)
R Object
(
[a] => 2
)


--------
4


Rubyでクラスを書く
@ はインスタンス変数を示すんだね。
class Hoge
 def initialize
  @a=1
  @b=2
 end

 attr_accessor :a, :b
end

class Foo
  def initialize
  @a=1
  @b=2
 end

 attr_accessor :a, :b
end

[Hoge.new, Foo.new].each{ |_|
  p _
}

結果:
#<Hoge:0x28c08 @a=1, @b=2>
#<Foo:0x28bf4 @a=1, @b=2>


@@ はクラス変数を示すんだね。
でも、なんかアクセスがうっとうし....
class Bar
 def initialize
  @@a=1
 end

 def plus_1_a
  @@a=@@a+1
 end

 def a
  @@a
 end

end

[Bar.new, Bar.new, Bar.new].each{ |_|
   _.plus_1_a
   p _.a
}

結果:
2
3
4


self は自分自身なんですね。
メソッドチェーンができますね。
class F; def f; p 'a'; self; end; end;

F.new.f.f.f.f;

結果:
"a"
"a"
"a"
"a"
Error.pm と Fatal.pm の合わせ技は
次のソースしか試していないのですが、 Error.pm と Fatal.pm の合わせ技はうまくいくようです。
use Fatal qw(open);
use Error qw(:try);

try{
  open my $f, 'aaaaaaaaa.txt';
}otherwise{
  print "とらえたぞ!!!" . "\n";
};

print "続行可能!!!" . "\n";


結果:
とらえたぞ!!!
続行可能!!!

「ユニークにする」 「重複しないものだけ選ぶ」
Perlです。

ユニークにする。
1,1,1,2,2,3,4 → 1,2,3,4
参考資料:
http://www.rfs.jp/sb/perl/02/04.html


重複しないものだけ選ぶ
1,1,1,2,2,3,4 →  3,4
参考資料:
http://q.hatena.ne.jp/1215150566
ブログ検索

プロフィール

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

FC2カウンター

カレンダー

08 | 2008/09 | 10
- 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ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。