「PHP/入門/関数とは」の版間の差分

削除された内容 追加された内容
Ef3 (トーク | 投稿記録)
→‎変数のスコープ: マークアップ修正
タグ: 2017年版ソースエディター
Ef3 (トーク | 投稿記録)
→‎再帰的呼出し: 関数は、自分の定義の中に自分を含めることができます。
タグ: 2017年版ソースエディター
69 行
:<syntaxhighlight lang=php>
<?php
function f(){
return 1;
 
$a = f();
 
echo $a;
 
function f(){
return 1;
?>
</syntaxhighlight>
84 ⟶ 85行目:
 
;解説
: 上記コードを実行すると、まずf()が呼び出され、f()から1が返され、その値が<code> $a = f(); </code>という代入命令より $a には 1が代入されます
: PHPの代入演算子は右結合かつ右辺の値を返すので、<code>$a = $b = 0;</code> は、<code>$a = ( $b = 0 );</code>と解され、<code>$a = 0; $b = 0;</code>と同じ結果となります。
 
なお、プログラミングでは代入命令の式は一般に、右辺から先に実行される。
 
 
;参考
103 ⟶ 102行目:
 
<code>pi()</code> は、円周率の数値を返す関数である。
 
 
=== 関数の引数と戻値 ===
176 ⟶ 174行目:
strict_types を 1 にセットすると、型宣言漏れをエラーにできます。
 
;例:<syntaxhighlight lang=php line highlight=6>
<?php
declare(strict_types=1);
418 ⟶ 416行目:
::このようキャプチャーを行う性質から、無名関数は、しばしまクロージャーと呼ばれます。
::: 無名関数の中で __FUNCTION__ を参照すると、<code>{closure}</code> となります。
 
=== 再帰的呼出し ===
関数は、自分の定義の中に自分を含めることができます。
 
;例:<syntaxhighlight lang=php line highlight=6 line highlight="9,17,22">
<?php
declare(strict_types=1);
 
function ipow(int $x, int $y) : int {
if ($y == 0)
return 1;
if ($y == 1)
return $x;
return $x * ipow($x, $y - 1);
}
 
echo 'ipow(2, 3) --> ', ipow(2, 3), PHP_EOL;
echo 'ipow(10, 9) --> ', ipow(10, 9), PHP_EOL;
 
function comma3(int $n) {
if ($n < 0) {
return "-" . comma3(-$n);
}
$num = intdiv($n, 1000);
$rem = $n % 1000;
if ($num) {
return comma3($num) . sprintf(",%03d", $rem);
}
return sprintf("%d", $rem);
}
echo 'comma3(ipow(10, 9)) --> ', comma3(ipow(10, 9)), PHP_EOL;
echo 'comma3(ipow(2, 32)) --> ', comma3(ipow(2, 32)), PHP_EOL;
 
?>
</syntaxhighlight>
;実行結果:<syntaxhighlight lang=text>
ipow(2, 3) --> 8
ipow(10, 9) --> 1000000000
comma3(ipow(10, 9)) --> 1,000,000,000
comma3(ipow(2, 32)) --> 4,294,967,296
</syntaxhighlight>
:整数の累乗を求める関数 <code>ipow()</code> と、整数を3桁ごとに ',' で区切ってた文字列を返す関数 <code>comma3()</code> を定義しました。
:2つの関数とも定義が再帰的なので、再帰的呼び出しで実装しています。
:再帰的呼出しは、終了条件を間違えると「無限再帰」に陥ってしまい、資源(この場合はスタック)を喰いつくすまで帰ってきません。
:アルゴリズムが再帰的な場合、再帰的呼出しを行う関数として実装するとコードは短くなりますが、PHPの処理系はtailrecのような最適化は行わないので、関数呼出しのオーバーヘッドが再帰の他に課金され、資源にも優しくないので、再帰で実装したあと回帰テストを書き、ループで実装しテストを通ることを確認するのがベターでしょう。
 
[[Category:PHP|にゆうもん かんすうとは]]