ちょっとまったour

http://www.geocities.jp/ky_webid/perl5/025.html

○our変数

my と local に続いて、our変数という変数を説明しておきます。Perl にはこの3つの変数が用意されています。

our変数自身は、レキシカルスコープを持ちます。この変数は、他の変数のスコープが内側にあろうとも、必ず外側にある変数をアクセスしようとします。


#!C:/Perl/bin/perl

use strict;
use warnings;


my $num = 500;

function();
print "$num\n";   # 500 を出力




sub function{
    my $num = 100;

    # ここに新しいスコープを作る
    {
        our $num = 200;    # 一番外側にある $num に 200 を代入
        print "$num\n";    # 200 を出力
    }
    
    print "$num\n";  # 100 を出力
}


出力結果は次のようになります。

200
100
500


function関数の内部に、{ } を使って新しいスコープを定義しています。こういう手段を使うことは可能です。この中で our変数を使っています。

our 変数は、一番外側にある変数を隠してしまうような、別の同名変数を無視して、外側の変数にアクセスできるようにします。関数の外に $num があり、function関数の先頭にも $num があるので、普通なら、内側にある $num しかアクセスできないはずですが、our変数を使えば、外側の $num を触れるという訳です。

ここで注意して見て欲しいのは、出力結果の最後に 500 があることです。our変数を使って、一番外側の $num に 200 を代入したはずですが、最後には 500 に戻っていることが分かります。これは、our変数自身がレキシカルスコープを持っているためです。our変数のスコープを抜けたとき、外側の $num の値は元に戻ります。

これ読んだらよくわかんなくなった。
この場合のスコープの中のourってmainパッケージ?

http://d.hatena.ne.jp/yupug/20070222/1172172836

([意]訳)
"my"は、変数( $a )のためにメモリに領域を確保し、
変数( $a )がその領域を指し示すよう割り当てておくが、
"our"は、現在のパッケージのパッケージ変数( $Foo::a )を、
変数( $a )が指し示すように割り当てる。

つまり、 "our"はレキスカルスコープであるという点は"my"と同じであるが、
かならずしも、変数を新たに作るわけではない。

ということは、さっきの例でいえば

        our $num = 200;    # 一番外側にある $num に 200 を代入

これは

my $num = 500;

こいつじゃなくて、mainパッケージにレキシカルな$numを作ってそれに200をセットしてourがそのレキシカルな$numを参照してるよ、ってことじゃないのかなあ。
というわけでやってみる。

#!/usr/bin/perl
use strict;
use warnings;


my $num = 500;

function();
print "$num\n";   # 500 を出力

print "scope out $main::num\n";



sub function{
    my $num = 100;

    # ここに新しいスコープを作る
    {
        print "scope in $main::num\n";
        our $num = 200;        # 一番外側にある $num に 200 を代入
        print "$num\n";        # 200 を出力
    }
    
    print "$num\n";  # 100 を出力
}
C:\MyWorks\Perl\our>perl our5.pl
Use of uninitialized value in concatenation (.) or string at our5.pl line 20.
scope in
200
100
500
scope out 200

あってた(多分)
復習すると

#!/usr/bin/perl
use strict;
use warnings;


# ローカル変数
my $num = 500;

function();

# ローカル変数の$num
print "$num\n";   # 500 を出力

# パッケージ変数はまだ生きてる
print "scope out $main::num\n";



sub function{

    # subの中のローカル変数
    my $num = 100;

    # ここに新しいスコープを作る
    {
        # この時点ではourしてないのでパッケージ変数がない
        print "scope in $main::num\n";

        # mainパッケージに$numのパッケージ変数作成
        our $num = 200;        # 一番外側にある $num に 200 を代入

        # パッケージ変数を表示
        print "$num\n";        # 200 を出力
    }
    # スコープを抜けたので完全修飾名なしでパッケージ変数は使えなくなる
    
    # ここはsubのローカル変数
    print "$num\n";  # 100 を出力
}

ということだと理解したけどどうだろう。

local

というわけでourを理解してからのlocal再び。

localよ、私は帰ってきた!

http://d.hatena.ne.jp/perlcodesample/20080309/1205078496

# localの役割は、パッケージ変数を一時的に保存して、
# 後で、復元することにある。

# 他言語のローカル変数とは、何の関係もない。

# lacal の後にくる変数は、パッケージ変数であって、レキシカル変数ではない
# localは、一見、変数宣言のように見えるが、変数宣言ではない。
# 変数宣言に使えるのは、Perlでは、my と our だけである。

おさらい。

#!/usr/bin/perl
use strict;
use warnings;

our $myour = 10;

print "$myour\n";

# scope
{

    local $myour = 20;

    print "main::-> $main::myour\n";
    print "scope-> $myour\n";

}

print "$myour\n";
C:\MyWorks\Perl\local>perl local1.pl
10
main::-> 20
scope-> 20
10

あたりまえだけどパッケージ変数自体を覗いてもちゃんと20になってる。

サブルーチンをまたいでも大丈夫。

#!/usr/bin/perl
use strict;
use warnings;

our $myour = 10;

print "$myour\n";

fnc1();

sub fnc1
{

    local $myour = 20;

    print "main::-> $main::myour\n";
    print "fnc1-> $myour\n";

    fnc2();

}

sub fnc2
{

    print "main::-> $main::myour\n";
    print "fnc2-> $myour\n";

}

print "$myour\n";
C:\MyWorks\Perl\local>perl local2.pl
10
main::-> 20
fnc1-> 20
main::-> 20
fnc2-> 20
10

というわけでlocalは大体理解した、と思う。

our


前回のlocal妥協に伴い、いろいろ調べていくうちにlocalより先にourやったほうがわかりやすいんじゃないかと思ったので先にourから。

our


http://d.hatena.ne.jp/perlcodesample/20080311/1205249391

### パッケージ変数の宣言
# ・パッケージ変数の宣言は、our で行う。
# ・パッケージ変数の宣言により、
# 1. パッケージ変数が生成され、
# 2. 完全修飾名を、修飾されない変数名で参照できる。
# ( $SomePackgae::var を $var で参照できるということ。)

パッケージ変数


http://d.hatena.ne.jp/perlcodesample/20080308/1204953841

# パッケージ変数
# ・パッケージ変数とは、名前空間に属するグローバル変数である。
# ・つまり、パッケージ変数は、修飾名(パッケージ名)を持ち、
# ソースコードのどの位置からでも参照できるということです。

名前空間


http://d.hatena.ne.jp/perlcodesample/20080615/1213501216

Perlでは、すべてのサブルーチンは、名前空間に属します。Perlでは、名前空間のことをパッケージと呼びます。

パッケージ


http://www.geocities.jp/ky_webid/perl5/036.html

明示的にパッケージを使わなくとも、暗黙のうちに main という名前のパッケージが使われています。通常、これを意識する必要はありませんが、明示的に書くこともできます。

mainパッケージ


http://d.hatena.ne.jp/perlcodesample/20080313/1205429891

mainパッケージ

* パッケージの宣言が行われない場合、ourで宣言されたパッケージ変数は、mainパッケージに属する。

Perlの変数の種類

* Perlには、グローバル変数は、存在せず、パッケージ変数とレキシカル変数しか存在しない。
* グローバル変数のように見えるものは、実は、mainパッケージに属している。

ourへ戻る

#!/usr/bin/perl
use strict;
use warnings;
 
our $global = "abc";
 
print "$global\n";
 
# scope1
{
	print "in scope1 = $global\n";
}
 
print "$main::global\n";

C:\MyWorks\Perl\our>perl our1.pl
abc
in scope1 = abc
abc


おさらいすると

  • パッケージを省略した場合はデフォルトでmainパッケージになる
  • ここでの$globalはmainパッケージのグローバル変数
  • パッケージの中にいるときは修飾名なしでアクセスできる


ということでいいのかな。

パッケージを指定してやってみる。

#!/usr/bin/perl
use strict;
use warnings;
 
package pkg;
my $pkgmy = 10;
 
print "pkg:: $pkgmy\n";
 
our $pkgmy;
 
package main;
 
print "main->pkg:: $pkg::pkgmy\n";

Use of uninitialized value in concatenation (.) or string at our2.pl line 14.
pkg:: 10
main->pkg::


初期化されてないときた。

pkg:: 10
main->pkg:: 10

というのを想定していたがならなかった。なぜか。
単純にmyとourを理解していなかった。

myはスコープ内でローカルという意味で、パッケージの下に書いたとしてもこの場合はファイルスコープのmy、つまりmainパッケージのmyということ。
で、ourはmyをパッケージ変数に変換してくれると勝手に勘違いしていた。

というわけでやり直し。

#!/usr/bin/perl
use strict;
use warnings;
 
package pkg;
our $pkgour = 10;
 
print "pkg:: $pkgour\n";
 
package main;
 
print "main->pkg:: $pkg::pkgour\n";

C:\MyWorks\Perl\our>perl our3.pl
pkg:: 10
main->pkg:: 10


まあこんなコード書いても何が便利なのかわからないけど、おそらくクラスのプロパティとかで使うのかなあというわけで書いてみたが

package pkg;
{
	our $pkgour 10;
}
print "main->pkgour:: $pkg::pkgour\n";


こんなの書いたら豪快にエラーがきた。
JavaScriptだとこれでいけるのにPerlはダメらしい。

{
	package pkg;
	our $pkgour 10;
}
print "main->pkgour:: $pkg::pkgour\n";


こう書くといける。
となると疑問があって、メソッドなんか書く場合

http://d.hatena.ne.jp/perlcodesample/20080612/1213415372

  • サブルーチンは、スコープの影響を受けません。
  • 一見すると、fucnは、スコープの外では、見えないものと思ってしまいがちですが、そうなりません。
  • サブルーチンの定義は、コンパイル時に、シンボルテーブルというものに登録されます。シンボルテーブルは、プログラムのどこからでも参照することができるため、サブルーチンも、プログラムのどこからでも参照できます。( スコープの影響を受けないということ )


と書いてるところをみると、1つのファイルスコープ内でパッケージに属するメソッドって書けないようにみえるがパッケージの場合は特別なんだろうか。

というわけでやってみる。

#!/usr/bin/perl
use strict;
use warnings;
 
{
	package pkg;
	our $pkgour = 10;
	my $pkgmy = 20;
 
	sub pkgsub
	{
		print "$pkgmy\n";
	}
}
 
print "main->pkgour:: $pkg::pkgour\n";
pkgsub();

C:\MyWorks\Perl\our>perl our4.pl
Undefined subroutine &main::pkgsub called at our4.pl line 17.
main->pkgour:: 10


ちゃんとエラーでた。

#!/usr/bin/perl
use strict;
use warnings;
 
{
	package pkg;
	our $pkgour = 10;
	my $pkgmy = 20;
 
	sub pkgsub
	{
		print "$pkgmy\n";
	}
}
 
print "main->pkgour:: $pkg::pkgour\n";
pkg->pkgsub();

C:\MyWorks\Perl\our>perl our4.pl
main->pkgour:: 10
20


というわけで

http://d.hatena.ne.jp/yupug/20070222/1172172836

最初はこれ読んでまったく理解できなかったが概ね理解できた、と思う。

sub

http://d.hatena.ne.jp/lolstep/20080624/1214315830

これなんだけど

最後のやつはクロージャと一緒なのでわかるんだけど、スコープの中の関数を外からいじれるのがいまいちよくわかんないけど、関数はスコープの階層は関係ないってことなのかな。

ちゃんと書いてあった。

サブルーチンの定義はスコープの影響を受けないことを理解する

http://d.hatena.ne.jp/perlcodesample/20080612/1213415372

謎は解けた。

my local our

やっとここにきた。

ここでスコープをおさらい。

http://d.hatena.ne.jp/perlcodesample/20080310/1205162964

my

まずはmyから。

http://www.geocities.jp/ky_webid/perl5/025.html

変数の宣言時にいつも付けている「my」は、変数のスコープを基本的に { } の内部に限定します。そのため関数内で宣言すると、関数の { } がスコープとなります。このスコープ外からはアクセスできない(見えない)のです。

要は、JavaScriptでいうlocal変数ってことかな。

#!/usr/bin/perl
use strict;
use warnings;


# my
my $num = 10;
print "num = $num\n";

# スコープ
print "スコープ1\n";
{
	my $num2 = 20;
	print "num = $num\n";
	print "num2 = $num2\n";
}

print "スコープ2\n";
{
	my $num2 = 30;
	print "num2 = $num2\n";

	sub scope2sub
	{
		return $num2;
	}
}

print "スコープ2の中のnum2 = " . scope2sub() . "\n";
C:\MyWorks\Perl\mylocalour>perl my1.pl
num = 10
スコープ1
num = 10
num2 = 20
スコープ2
num2 = 30
スコープ2の中のnum2 = 30

最後のやつはクロージャと一緒なのでわかるんだけど、スコープの中の関数を外からいじれるのがいまいちよくわかんないけど、関数はスコープの階層は関係ないってことなのかな。

local

http://d.hatena.ne.jp/perlcodesample/20080309/1205078496

# localの役割は、パッケージ変数を一時的に保存して、
# 後で、復元することにある。

# 他言語のローカル変数とは、何の関係もない。

# lacal の後にくる変数は、パッケージ変数であって、レキシカル変数ではない
# localは、一見、変数宣言のように見えるが、変数宣言ではない。
# 変数宣言に使えるのは、Perlでは、my と our だけである。

http://www.geocities.jp/ky_webid/perl5/025.html

local変数は、外側のスコープに同じ名前の変数があるとき、その値を記憶したまま、別の値を割り当てます。

#!/usr/bin/perl
use strict;
use warnings;


my $num1 = 50;
print "num1 = $num1\n";
{
	local $num1 = 100;
	print "num1 = $num1\n";

}

print "num1 = $num1\n";
C:\MyWorks\Perl\mylocalour>perl local1.pl
Can't localize lexical variable $num1 at local1.pl line 9.

なんでエラーでんのかなあと思ったら

# lacal の後にくる変数は、パッケージ変数であって、レキシカル変数ではない
# localは、一見、変数宣言のように見えるが、変数宣言ではない。
# 変数宣言に使えるのは、Perlでは、my と our だけである。

パッケージ変数ってなんぞって思って調べたら

http://d.hatena.ne.jp/perlcodesample/20080308/1204953841

# パッケージ変数
#     ・パッケージ変数とは、名前空間に属するグローバル変数である。
#     ・つまり、パッケージ変数は、修飾名(パッケージ名)を持ち、
#       ソースコードのどの位置からでも参照できるということです。
#
#     ・パッケージ名を含めて記述した変数名を完全修飾名と呼びます。
#       ( 完全修飾名 $SomePackage::package_var1 )
#
#      ・パッケージ名は大文字ではじめる。単語の区切りも大文字にする。

なんでグローバル変数を使ってるのか理解できた。
というわけで、パッケージ変数とやらを作ってみたけども

#!/usr/bin/perl
use strict;
use warnings;

package pkg;
$pkg::num1 = 50;
print "num1 = $pkg::num1\n";
{
	local $num1 = 100;
	print "num1 = $num1\n";
}

print "num1 = $pkg::num1\n";
C:\MyWorks\Perl\mylocalour>perl local1.pl
Variable "$num1" is not imported at local1.pl line 9.
Variable "$num1" is not imported at local1.pl line 10.
Global symbol "$num1" requires explicit package name at local1.pl line 9.
Global symbol "$num1" requires explicit package name at local1.pl line 10.
Execution of local1.pl aborted due to compilation errors.

エラーが出るのはいいんだが、なぜエラー出るのかが理解できないので、とりあえず先に進むためにここは妥協&後回し。

#!C:/Perl/bin/perl

#use strict;
#use warnings;


$num = 500;
print "$num\n";

func();

sub func
{
	local $num = 100;
	print "$num\n";
}

print "$num\n";
C:\MyWorks\Perl\mylocalour>perl local1.pl
500
100
500

やってみればわかるんだけど、これって何のために使うのかがよくわからない。
関数の引数で値渡しするのと同じイメージしか思い浮かばないんだけどどうなんだろうなあ。
とりあえず今のレベルでは使い道が思い浮かばないのでそれまでは使わない方向で。


ということで時間切れ、ourは次回ということで。

sort

前回のこれで

http://d.hatena.ne.jp/lolstep/20080621/1214043186

$a, $bが定義されてないのにエラーが出ないのは謎いと書いたところ、いつもみてるid:perlcodesampleさんからコメントで教えてもらったのでおさらい。

http://perldoc.jp/docs/perl/5.8.4/perlfunc.pod

use strict している場合、$a と $b をレキシカルとして宣言しては いけません。これはパッケージグローバルです。つまり、main パッケージで以下のように書いた場合:

@articles = sort {$b <=> $a} @files;

$a と $b は $main::a と $main::b (または $::a と $::b) を意味しますが、FooPack パッケージ内の場合、これは以下と同じになります:

@articles = sort {$FooPack::b <=> $FooPack::a} @files;

というわけで使うなと。

sortの書き方は以下の3つ。

  • sort SUBNAME LIST
  • sort BLOCK LIST
  • sort LIST

sort LIST

SUBNAME や BLOCK を省略すると、標準の文字列比較の順番でソートが行なわれます。

#!/usr/bin/perl
use strict;
use warnings;


# 配列定義
my @array = ( "1", 2, 3, 4, "5", 10, "11", "A" );

# sort
my @result = sort @array;

for (my $i = 0; $i < @result; $i++)
{
	print $result[$i] . "\n";
}
C:\MyWorks\Perl\sort>perl sort1.pl
1
10
11
2
3
4
5
A

配列の個数取得がわからなくて2分はまったがこれみて把握。

http://d.hatena.ne.jp/perlcodesample/20080114/1200305034

こんな方法もあるようだが

http://www.ksknet.net/cat34/post_12.html

配列の個数を参照するには$#変数名を参照すればよい。

$#array;

なんかしっくりこないので$num = @arrayのほうを使うことにする。

sort SUBNAME LIST

SUBNAME を指定すると、それは、リストの要素をどのような順番に並べるかに応じて、負、ゼロ、正の整数を返すサブルーチンの名前であると解釈されます。

いまいち意味がわからないんだけども、どう解釈したらいいのかが不明すぎる。
サンプルみると

http://chaichan.web.infoseek.co.jp/src/perl07.htm

sub number {
  if ($a < $b) {
    return -1;
  } elsif ($a == $b) {
    return 0;
  } elsif ($a > $b) {
    return 1;
  }
}

こう書いてあるが、確かに負、ゼロ、正の整数を返すサブルーチンであることは理解できるけども、これって要素を1個づつ隣に進むイメージになってるんだろうか。

サブルーチンのプロトタイプが ($$)の場合、比較する要素は通常のサブルーチンと同じように @_ の中にリファレンスとして渡されます。これはプロトタイプなしのサブルーチンより遅いです。この場合は比較のためサブルーチンに渡される 2 つの要素は、パッケージのグローバル変数 $a と $b で渡されます (次の例を参照してください)。後者の場合、レキシカルに $a と $b を宣言するのは普通逆効果になります。

プロトタイプが$$ってのをググると、要はスカラーが2個の引数ってことみたいなんだけども、どうなってんのかなあ。
てことで、意味がよくわからないのでprint文をはさんでみる。

#!/usr/bin/perl
use strict;
use warnings;


# 配列定義
my @array = ( "1", 2, 3, 4, "5", 10, "11", "20" );

# sort
my @result = sort number @array; 

sub number
{
	if ($a < $b)
	{
		print "$a < $b\n";
		return -1;
	}
	elsif ($a == $b)
	{
		print "$a = $b\n";
		return 0;
	}
	elsif ($a > $b)
	{
		print "$a > $b\n";
		return 1;
	}
}

print "\nresult\n";
for (my $i = 0; $i < @result; $i++)
{
	print $result[$i] . "\n";
}
C:\MyWorks\Perl\sort>perl sort2.pl
1 < 2
3 < 4
5 < 10
11 < 20
1 < 3
3 > 2
5 < 11
11 > 10
1 < 5
5 > 2
5 > 3
5 > 4

result
1
2
3
4
5
10
11
20

なるほどね、これでよくわかった。ソートもマージソートを使ってる模様。

Perl 5.6 以前ではソートの実装にクイックソートアルゴリズムを使っていました。このアルゴリズムは安定せず、2 乗の時間が掛かる 可能性があります 。 (安定した ソートは、比較した時に同じ要素の入力順が保存されます。クイックソートの実行時間は、長さ N の全ての配列の平均では O(NlogN) ですが、入力によっては O(N**2) という 2 乗の 振る舞いをすることがあります。) 5.7 では、クイックソートによる実装は、最悪の場合の振る舞いも O(NlogN) である、安定したマージソートアルゴリズムに置き換えられました。しかし、入力とプラットフォームによっては、ベンチマーククイックソートの方が速くなります。 5.8 ではソートを限定的に制御できる sort プラグマがあります。この、アルゴリズムの直接的な制御方法は将来の perl では引き継がれないかもしれませんが、実装に依存しない形で入力や出力を性格付ける機能はおそらくあります。 sort を参照してください。

マージソートといえば、今日はてブでこれみたがすごい良いタイミング。

http://labs.cybozu.co.jp/blog/akky/archives/2008/06/animated-sorting-algorithm-demo.html

というわけで、これでは長いので

(このようなルーチンには、<=> 演算子や cmp 演算子が、たいへん便利です。)

となるわけだね。

てことで書き換える。

#!/usr/bin/perl
use strict;
use warnings;


# 配列定義
my @array = ( "1", 2, 3, 4, "5", 10, "11", "20" );

# sort
my @result = sort number @array; 

sub number
{
	print "$a <=> $b\n";
	$a <=> $b;
}

print "\nresult\n";
for (my $i = 0; $i < @result; $i++)
{
	print $result[$i] . "\n";
}
C:\MyWorks\Perl\sort>perl sort3.pl
1 <=> 2
3 <=> 4
5 <=> 10
11 <=> 20
1 <=> 3
3 <=> 2
5 <=> 11
11 <=> 10
1 <=> 5
5 <=> 2
5 <=> 3
5 <=> 4

result
1
2
3
4
5
10
11
20

sort BLOCK LIST

SUBNAME の代わりに、無名のインラインソートルーチンとして、BLOCK を書くことができます。

というわけで、どこみてもsortで探すと書いてある一般的?な構文のこれに行き着くわけか。

http://d.hatena.ne.jp/perlcodesample/20080114/1200305034

#----- 昇順に並べ替える --------------
my @ascend = sort { $a <=> $b } @numbers;
print "昇順に並べ替え : @ascend\n";

書き換えてみる。

#!/usr/bin/perl
use strict;
use warnings;


# 配列定義
my @array = ( "1", 2, 3, 4, "5", 10, "11", "20" );

# sort
my @result = sort { $a <=> $b } @array; 

for (my $i = 0; $i < @result; $i++)
{
	print $result[$i] . "\n";
}
C:\MyWorks\Perl\sort>perl sort4.pl
1
2
3
4
5
10
11
20

文字列比較をしたい場合は<=>じゃなくてcmpを使いなさいよってことで、とりあえずsortは大体把握した、と思う。

しかし、残業後にするとさすがに眠くなるな。

変数

思いとどまってmyより先に変数をやってから進む。

まず変数に型があるかということから。

Perlの型の概念。

http://d.hatena.ne.jp/perlcodesample/20080312/1205337470

### Perlにおける型の概念
# ・Perlの型の概念は、他の言語とまったく異なる。
# ・Perlは、整数型や不動小数点型や文字列型といった、
# 中に含まれるものの区別によって、型を区別するのではない。
# ・Perlは、変数の中に含まれる値の個数で、型を区別する

JavaScriptの変数は入れた値によって型がかわったけど、Perlの場合は格納された値の個数でかわるということか。

Perlでの型は以下の3つ。

スカラー

* スカラー型は、変数の中にたった一つの何らかの値を、含むことができる。
* $を変数名の前につけることで、スカラー型を表す。

配列型

* 複数の値を含むことができる。
* 配列型の各要素に含むことができるのは、スカラー型のみである。
* @を変数の前につけることで、配列型を表す。
* ハッシュ型に代入できるのは、リスト ( ) だけである。

ハッシュ型

* キーと値がセットになった複数の値を含む
* ハッシュ型の各要素に含むことができるのは、スカラー型のみである。
* @を変数の前につけることで、配列型を表す。
* ハッシュ型に代入できるのは、リスト ( ) だけである。

配列型とハッシュ型

* 配列型もハッシュ型も、その中身はどちらもリストであり、等価である。
* 配列型をハッシュに代入することで、ハッシュ型に変換したり、その逆もできる。

というわけでやってみる。
文字列の連結方法がわからず2分はまった。

#!/usr/bin/perl
use strict;
use warnings;

# スカラー型
$a = 1;
print "$a\n";
$b = 0123;
print "$b\n";
$c = 1.234;
print "$c\n";
$d = "aaaaa";
print "$d\n";

# 配列型
@array = (1, 2, "3");
print "$array[0]\n";
print "$array[1]\n";
print "$array[2]\n";

# ハッシュ型
%hash = ( "key1", 1, "key2", "aa" );
print $hash{"key1"} . "\n";
print $hash{"key2"} . "\n";
C:\MyWorks\Perl\variable>perl variable1.pl
Global symbol "$c" requires explicit package name at variable1.pl line 11.
Global symbol "$c" requires explicit package name at variable1.pl line 12.
Global symbol "$d" requires explicit package name at variable1.pl line 13.
Global symbol "$d" requires explicit package name at variable1.pl line 14.
Global symbol "@array" requires explicit package name at variable1.pl line 17.
Global symbol "@array" requires explicit package name at variable1.pl line 18.
Global symbol "@array" requires explicit package name at variable1.pl line 19.
Global symbol "@array" requires explicit package name at variable1.pl line 20.
Global symbol "%hash" requires explicit package name at variable1.pl line 23.
Global symbol "%hash" requires explicit package name at variable1.pl line 24.
Global symbol "%hash" requires explicit package name at variable1.pl line 25.
Execution of variable1.pl aborted due to compilation errors.

いきなりのエラー大量発生。
これはuse strictを付けたからというわけで外してやってみると通る。
まあ外す意味も無いのでエラーを修正。
ここでmyを付ければいいというわけだけど、気になるのが全部myを付けなければならないのならばなぜ$a、$bでエラーが出ないのかということ。
ちなみに$c, $dを$a, $bに変えるとエラー出ず。$a, $bを$aa、$bbに変えるとエラーが出る。謎い、謎すぎる。
特殊な変数なのかなと思ってググってみてもそんなのは出てこない。
とりあえずやむなくここは放置とする。

というわけでmyを付けてretry。

C:\MyWorks\Perl\variable>perl variable1.pl
1
83
1.234
aaaaa
1
2
3
1
aa

$bには0123と入れて83と出たところを見ると

http://www.mapee.jp/dproom/10perl.html

0で8進、0xで16進とJavaScriptとこの辺のリテラルは同じ。

次に、配列型とかハッシュ型のときに型宣言では@や%なのに要素アクセスではなんで$なのかと気になってたらちゃんと書いてあった。

http://perl-users.jp/modern_introduction_perl/variables.html

配列のsigilが「@」から「$」に変化するのがわかりにくいかもしれませんが、これはどのような変数にアクセスしているのか考えるとわかりやすいかもしれません。

配列として全体に対して操作する場合は「@」を使用します。

join(" | ", @list);

配列の要素一個一個はスカラーですので、要素一個一個にアクセスする場合は「$」を使用します。

print $list[ 0 ];

こう説明されるとわかりやすい。要素1つ1つはスカラーなので$を使えと。

そういえばJavaScriptでは変数に関数を入れられたけどもPerlではどうかというわけで試す。

#!/usr/bin/perl
use strict;
use warnings;


# 変数にサブルーチンを入れてみる
sub mysub
{
	print "hello world!\n";
}

my $sub = mysub();
C:\MyWorks\Perl\variable>perl variable2.pl
hello world!

結果は、入ったっていうか実行された。JavaScriptでは()を付けない限り格納されるだけだったが、Perlでは実行されるんだろうか。

そういえば無名関数はどうなんだろうということで調べてみる。

http://www.geocities.jp/ky_webid/perl5/028.html

無名配列や無名ハッシュが存在するように、無名関数(無名サブルーチン)というものもあります。名前が無いのですから、やはりリファレンスを経由してアクセスする以外の使い道がありません。無名関数は、次のように使います。

#!/usr/bin/perl
use strict;
use warnings;


# 無名関数
my $mysub = sub
{
	print "hello world!!!\n";
};

# 呼び出し1
$mysub->();
# 呼び出し2
&$mysub;
C:\MyWorks\Perl\variable>perl variable3.pl
hello world!!!
hello world!!!

リファレンスってなんぞと思って調べてみたら、昔ほんのちょこっとだけやったことがあるCでいうアドレスと同じ概念ぽい。

  • >ってのもCっぽい感じ。

というわけで変数は概念的なことはわかった、と思う。