Perl/関数

出典: フリー教科書『ウィキブックス(Wikibooks)』
ナビゲーションに移動 検索に移動

プログラミング > Perl > Perl/関数


関数とは[編集]

Perlにかぎらずプログラミングでいう「関数」とは、処理をひとまとめにして名前をつけたものです。

その関数の名前を呼び出すなどの簡易な方法により、その関数の(長い)処理を実行させることができます。


Perlにかぎらず、プログラミングでいう「関数」には、

ユーザーが自分で作成できる「ユーザー定義関数」と、

いっぽう、それとは別に、

プログラム言語やOSなどにより、あらかじめ準備されている「組み込み関数」、

とがあります。

ユーザー定義関数を造る場合にも、最終的には、プログラマーの手により「組み込み関数」をくみあわせて作成することになります。


たとえば、前の節で紹介した print などの関数は、組み込み関数です。

このように、組み込み関数は、名前を呼び出すだけで使えます。


いっぽう、ユーザー定義関数は、名前をつけるだけでなく、さらに処理の内容もプログラマーが作成する必要があります。


組み込み関数[編集]

print命令のように、ユーザーが定義しなくても、プログラム言語が最初から用意してる関数のことを「組み込み関数」と言います。

つまり、print命令も関数です。

基本的な関数[編集]

print[編集]

コード例
print "Hello, World\n";
print "Hello, Perl\n";
機能

orint関数は、print以下の引用符などで囲まれた文字を画面出力します。

print関数は、けっして自動では文末で改行しないので、もし改行をしたい場合にはエスケープシーケンス(上記コード例の「\n」)で改行を指定する必要があります。

say[編集]

Perl 5.01000 以降から導入されたsay 関数を使うと、文末で自動的に改行してくれるので、いちいちエスケープシーケンスで改行を記述する手間が省けます。

ただし、下記コードのように 「use 5.010;」またはそれ以上のバージョンを使用前に宣言する必要があります。

use 5.010; 

say "Test";
say "Hello, World";
say "Hello, Perl";


なお、2020年現在、Perlの最新バージョンは 5.30.2 (2020年3月14日) なので、5番台にしておくのが安全です。(20206月3日に6番台でFedora32で試したところ、エラーになり実行できない。)

ネット上には「use 5.010;」の例が多くありますが、下記のようにそれ以降のバージョンでも普通に動作します。

use 5.30.2;

say "Test2";
say "Hello, World";
say "Hello, Perl";
(※ 2020年6月3日に Fedora 32 で確認ずみ。)


length[編集]

length は文字列の長さを返します。(後述のリファレンス一覧にも、lengthの説明はある。)

コード例
$hensu = "aiueo";
$temp = length $hensu ;
print "$temp \n" ;
表示結果
5
※ 注: 二重引用符の中では変数は使用可能です。もし引用符の中で変数を無効にしたい場合、(二重引用符ではなく)一重引用符 ' ' を使います。


「aiueo」は5文字なので、上記コードを実行すると「5」が出力表示されます。

「aiueo」の部分を他の文字列に変えてみたりして、いろいろと試してみましょう。


数学関数[編集]

初等的な数学関数[編集]

平方根などの数学計算をする関数が用意されていますい。

コード例
$temp = sqrt(2) +50;

print "$temp \n";
表示結果
51.4142135623731 

なお √2 は 約 1.141 です。

三角関数など[編集]

三角関数などの高度な関数を使用するには、use宣言を使って Mathモジュールを導入することで、三角関数などが使用可能になります。

use Math::Trig;

$temp = cos(pi ) ;
print "$temp \n";
(※ 2020年6月3日に Fedora32 で動作を確認ずみ。)
表示結果
-1
備考

なお、pi は円周率 3.141(以下略)のことです。mathモジュールを導入した際に、自動的に円周率も導入されます。

Perlの三角関数の角度の単位はラジアン単位です。

タンジェントを計算する関数は用意されていないので、タンジェントを計算する場合には sin と cos から計算で求める。


時間関係の関数[編集]

現在の日時や時刻などを表すには、time関数およびlocaltime関数を使います。

コード例
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);  
$year += 1900;
$mon += 1;
print "いま西暦 $year 年 $mon 月 $mday 日です。\n";
(※ 2020年6月3日に Fedora32 で動作を確認ずみ。)


解説

time関数で、ある時刻(多くのシステムで1970年1月1日0時0分0秒(UTC) )からの秒数を返します。

これだと人間にとっては使いずらいのです、localtime関数というものによって、西暦や日時や時分秒などに変換できるという機能があります。

localtime関数は、配列の形式で結果を返します。

コード中の

($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);  

の部分は、perl公式サイトにあるコードを、そのまま使っています。

さて、yearが1900年からの年数を報告する形なので、西暦で表示したい場合には

$year += 1900;

のように1900を足し算する必要があります。

また、月は 0,1,2,3,4,・・・ という0から数える仕組みなので、私たち人間の月の数え方に直すために

$mon += 1;

というふうに1を足し算する必要があります。

日にち および 時分秒は、足し算は不要です。(人間の時間の数え方と同じ結果になります。)

split関数[編集]

Perlには、文字列を分解して、配列に代入していく関数があり、split関数といいます。

書式は

split (/区切り文字/, $もとの文字列);

です。

分割後は配列に代入する必要があるので、

@配列名 = split (/区切り文字/, $文字列名);

のようになります。

コード例
$test = 'level: 43';
@temp = split (/:/, $test);
print "@temp[0] \n";
print "@temp[1] \n";

$keisan = @temp[1] + 10;   # 計算できるかのチェック
print "レベルアップ後 $keisan \n";
実行結果
level
 43
レベルアップ後 53


分割後の配列の要素数は、3つ以上でも構いません。

コード例
$test = 'of the people, by the people, for the people';
@temp = split (/,/, $test);
print "@temp[0] \n";
print "@temp[1] \n";
print "@temp[2] \n";
実行結果
of the people
 by the people
 for the people


ユーザ定義関数(サブルーチン)[編集]

関数のことを「サブルーチン」ともいいます。1980年代、BASICでは「サブルーチン」と言っていました。

Perl でも「サブルーチン」と言います。また、ユーザー定義関数を定義するさいの予約語も、Perlでは「sub」を使います。

書式
sub 関数名 {
    # ここに処理内容を書く。
    # 処理内容のつづき(中略)    
  return 返り値;
}

なお、関数名のあとのカッコ { } は、波カッコです。(PerlにかぎらずC言語でも同様に、ここは波カッコです。他の多くのプログラム言語でも、基本的にここは波カッコになります。)

C言語とは違い、整数型だの何だのといった型名は指定しません。そもそも Perl には整数型などの区別は無いです。(※ なお PHP や JavaScript でも同様、整数型などの指定しない。)


あらかじめPerlに準備されている「組み込み関数」の他に、プログラマが新しい関数(ユーザー定義関数)を準備して利用することもできます。


ユーザー定義関数を呼び出すには、コード中で

&関数名

のように、関数名の前にアンド記号 & をつける事で、呼び出せます。

ただし、実際は&記号をつけずにそのまま関数名だけを書いても、呼び出せます。(2020年5月17日に Fedora 32 で確認.)


コード例
sub test {
  $hensu = 5;
}

&test;
print "$hensu \n";
実行結果
5


このように、サブルーチンの内部で宣言した変数(上例では $hensu )は、サブルーチンの外でもそのまま使えます。

※ C言語の用語で言うなら、C言語と違ってPerlでは、関数の中でもグローバル変数を作成できます。

C言語では、関数の中で新しく宣言した関数は、その関数の中でしか使えませんでした(厳密には異なるが、省略)。

しかし、Perlでは、もっと自由です。


Perlにかぎらず、プログラミング用語で、変数の変数の宣言されたサブルーチンの内部でのみ有効な変数のことを「ローカル変数」と言います。

いっぽう、一度宣言すれば、どこで宣言していても、そのソースコードのファイル中のどこからでもアクセスできて利用できる変数のことを「グローバル変数」と言います。


Perlでローカル変数を宣言するには、my $hensu のように、変数の前に my 演算子をつけます。


コード例
sub test {
  my $hensu = 3;
print "サブの中では $hensu \n";
}

&test;
print "サブの外では $hensu \n";
実行結果
サブの中では 3 
サブの外では  

上記コードの場合、サブルーチンの外ではローカル変数が無効になっているので、結果の数値の部分が空白になっているのです。


他のサブルーチンには、ローカル変数は、持ち込せないです。

コード例
sub test1 {
  my $hensu = 3;
  print "サブ1の中では $hensu \n";
}

sub test2 {  
  print "サブ2の中では $hensu \n";
}

&test1;
&test2;
print "サブの外では $hensu \n";
実行結果
サブ1の中では 3 
サブ2の中では  
サブの外では 


同名のサブルーチンであっても、変数の内容の持ち越しはできないです。

コード例
sub test1 {
  my $hensu ;
  print "サブ1の中では $hensu \n";
  $hensu = $hensu . "a" ; 
}

&test1;
&test1;
print "サブの外では $hensu \n";
実行結果
サブ1の中では  
サブ1の中では  
サブの外では  


コード
sub square {
  my $arg = $_[0];
  my $return = $arg * $arg;
  return $return;
}

print &square(5);
print square(5);
実行結果
25
25


関数(サブルーチン)を呼び出すときの square(5); のように丸カッコをつけると、引数として配列を渡したことになります。

たとえ、あとにつづく数字が「5」のように1個だけの数値でも、たまたま要素数が1個なだけの配列として処理されます。

このため、上記コードでは、関数内部のコードでは配列として受け取っています。


コード詳解
sub square { ユーザ定義関数 square を宣言します。
my $arg = $_[0]; ユーザ定義関数への引数が収納された配列 @_ の最初のスカラーを $arg に代入します。このスカラー変数 $arg は、my 関数によりユーザ定義変数 square の内部でのみ使われます(レキシカルスコープを持つ)。$arg = shift; と書いても、 @_ の最初のスカラーが代入されます。
my $return = $arg * $arg; my 関数によりレキシカルスコープを持ったスカラー変数 $return に、 $arg$arg を掛けた数を代入します。即ち、= の右の式の結果が、$return に代入されたということです。
return $return; スカラー変数 $return をユーザ定義関数を呼び出した式に戻します。Perlのサブルーチンでは、returnが無い場合は最後に評価された値が戻り値となるので、この場合returnは省略可能です。ただし、可読性を上げるため明示的に書かれることもあります。
} ユーザ定義関数の宣言のブロックが終ったことを示します。
print &square(5);
print square(5);
両者は同じ意味で、square 関数を呼び出します。&を明示的につけることにより、呼び出す関数をユーザ定義関数に限定します。下のほうは、ユーザ定義関数を呼び出す前に宣言してあることで使用できます。&square(5)とすることで、square 関数に 5 を渡し(引数)、実行結果が戻ってきます(戻り値)。戻り値は print 関数に渡され、 25 を表示するのです。

動作をわかりやすくしてみれば上のようになりますが、下のように書いても結果は同じです。一般に熟練したPerlのプログラマはある程度簡略化された記述を簡潔で直感的であるとして好むようです。

コード
sub square { $_[0] ** 2 }

print square(5);
実行結果
25

文法[編集]

引数・返り値とコンテキスト[編集]

関数が受け取る値のことを「引数」(ひきすう)と言います。

関数が、その関数の終了時などに、呼び出し元に送る値のことを「返り値」(かえりち)または「返却値」(へんきゃくち)などといいます。


wantarrayを使うと、サブルーチンが呼び出したコンテキストがリストコンテキストであるかどうかを調べることができます。

sub func {
    my @list = @_;
    my $scalar = $_[0];

    if (wantarray) {
        return @list;
    }

    else {
        return $scalar;
    }
}

@a = func(0, 1, 2); # (0, 1, 2)
$b = func(0, 1, 2); # 0

上記のように、リストコンテキストとスカラコンテキストで返り値を変更させたい場合に用いられます。


組み込み関数の一覧[編集]

スカラと文字列[編集]

index[編集]

指定した文字列を検索し、その文字列が冒頭から何文字目の直後にあるかを返します。


コード例
$str = "this is a pen.";
$temp = index $str,"pen" ;

print "$temp \n";
(※ 2020年6月3日に Fedora 32 で動作を確認ずみ。)
実行結果
10

pen の前にある"this is a "は空白も含めて合計で10文字なので、「10」が表示されます。


書式
index (STR, SUBSTR, [POSITION])
詳細

文字列 STR の中から、検索文字 SUBSTR を探し、その位置を返します。検索文字が見つからない場合には、返り値はゼロ以下の値 (通常は -1) となります。省略可能引数、POSITION には、検索開始位置を指定します。

位置情報が 0 から始まることに留意しましょう。 0 は文字列の左端を表します。厳密には文字数ではなくバイト数の指定なのでマルチバイト文字の取り扱いには注意を要します。

       0   1   2   3   4   5   6   7   8   9  10  11
     | H | e | l | l | o |   | W | o | r | l | d | ! |

rindex[編集]

rindex (STR, SUBSTR, [POSITION])

indexと同じですが、末尾からの位置を返します。

substr[編集]

substr (EXPR, OFFSET, [LENGTH], [REPLACEMENT])

文字列 EXPR から、OFFSET 目以降のバイト列を返します。取り出す長さ LENGTH をバイト単位で指定できますが、省略した場合は文字列の最後まで取り出します。なお、utf8プラグマが有効な場合は、バイト単位ではなく文字単位で取り出すことができます。

位置情報 OFFSET は上述のとおり 0 から始まりますが、LENGTH は容量なので通常は 1 以上の値を指定します。

文字列 REPLACEMENT を指定すると、取り出される部分を REPLACEMENT で置換します。

$str = "Hello, world!";
substr($str, 7, 5, "Japan"); # $str は "Hello, Japan!" になる

uc[編集]

uc ([EXPR])

文字列 EXPR を大文字にして返します。EXPR を省略すると、$_ が使われます。

ucfirst[編集]

ucfirst ([EXPR])

uc と同じですが、先頭1文字を大文字にして返します。

lc[編集]

lc ([EXPR])

uc と同じですが、小文字にして返します。

lcfirst[編集]

lcfirst ([EXPR])

ucfirst と同じですが、小文字にして返します。

chomp[編集]

chomp VARIABLE
chomp (LIST)

変数 VARIABLE の末尾の $/(デフォルトは "\n")を削除します。変数のリストを渡された場合は、各変数について同じ処理を行います。VARIABLE を省略すると $_ が使われます。

chop[編集]

chop VARIABLE
chop (LIST)

chomp と同じですが、末尾1文字を無条件に削除します。

chr[編集]

chr [NUMBER]

文字セットで NUMBER 番目に割り当てられている文字を返します。NUMBER を省略すると $_ が使われます。逆の操作を行うには ord を使います。

crypt[編集]

crypt PLAINTEXT, SALT

C ライブラリの crypt(3) をエミュレートします。

hex[編集]

hex [EXPR]

十六進数 EXPR を十進数に変換して返します。EXPR を省略すると $_ が使われます。

length[編集]

length [EXPR]

文字列 EXPR の長さを返します。bytes プラグマが有効な場合(デフォルト)はバイト数を、utf8 プラグマが有効な場合は文字数を返します。EXPR を省略すると $_ が使われます。

oct[編集]

oct [EXPR]

八進数 EXPR を十進数に変換して返します。EXPR を省略すると $_ が使われます。

ord[編集]

ord [EXPR]

文字列 EXPR の文字セット上でのコード位置を返します。EXPR を省略すると $_ が使われます。逆の操作を行うには chr を使います。

pack[編集]

pack TEMPLATE, LIST

LIST を TEMPLATE に従ってバイナリデータに変換します。

q[編集]

q/STRING/
qq/STRING/
qr/STRING/
qx/STRING/
qw/STRING/

シングルクォート、ダブルクォート、正規表現、バッククォート、単語クォート。詳細は演算子の章を参照。

reverse[編集]

reverse LIST

リストコンテキストでは LIST の順番を逆順にしたリストを返します。スカラコンテキストでは LIST の順番を逆順にし、各要素の文字列を反転したリストを返します。

my @array = qw( ABC DEF GHI );
print reverse @array; # GHIDEFABC
print scalar reverse @array; #IHGFEDCBA

sprintf[編集]

sprintf FORMAT, LIST

LIST を FORMAT に従って整形して返します。

tr[編集]

tr///

1文字を対応する1文字に置換します。詳細は演算子の章を参照。

y[編集]

y///

tr///と同義。