PowerShellの基本的なことがわかってなかったシリーズ第三弾です。
内容としては、牟田口さんのブログの
で書かれていることそのまんまです。
なので詳しいことを知りたい方はそちらをご覧いただければ十分かと思います。
今回わざわざパクリエントリを書くのは上のエントリを紹介したかったから+自分の備忘録のためになります。
はじめに
以下の超簡単なFunction、Func
を例に説明します。
Function Func(){ Write-Output "1+1は?" return 1 + 1 }
このファンクションを実行するとコンソールには
PS C:\> Func 1+1は? 2
と表示されます。
この時Func
の戻り値は何か?という話しになります。
私はつい最近までこのFunc
の戻り値は2
だけだと勘違いしていました。
Func
の実行結果を変数$Result
に設定して調べてみると以下の様になります。
PS C:\> $Result = Func # $Result の型は Object[] PS C:\> $Result.GetType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True Object[] System.Array # 要素数2 PS C:\> $Result.Count 2 # $Result[0]は String型の値 "1+1は?" PS C:\> $Result[0] 1+1は? PS C:\> $Result[0].GetType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True String System.Object # $Result[1]は Int型の値 2 PS C:\> $Result[1] 2 PS C:\> $Result[1].GetType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True Int32 System.ValueType
実際にFunc
から戻される値は最初のWrite-Output
の結果を含んだString
とInt32
の混ざったObcet[]
型の配列となっていることがわかります。
PowerShellの戻り値の評価について
about_Returnにこのへんのことが詳しく記載されています。
In Windows PowerShell, the results of each statement are returned as output, even without a statement that contains the Return keyword.
Languages like C or C# return only the value or values that are specified by the Return keyword.
PowerShellの基本として、戻り値の評価は式文(statement)ごとに行われます。
最初の例で言うと、Write-Output "1+1は?"
とreturn 1 + 1
両方が戻り値の評価対象となります。
これは先の牟田口さんのブログで記載されている様にパイプライン連携のための仕様です。
先ほどのFunc
を少し修正したFunc2
と簡単なフィルタFilter1
を例に動作を確認してみます。
Function Func2(){ Write-Output "1+1は?" Write-Host ("{0:HH:mm:ss.ffffff} | -------- 切り取り線 --------" -F (Get-Date)) return 1 + 1 } Filter Filter1(){ Write-Output ("{0:HH:mm:ss.ffffff} | パイプラインから {1}型 の {2} がきたよ!" -F (Get-Date), $_.GetType().Name, $_ ) }
Func2
をFilter1
にパイプラインで渡してみると、
PS C:\> Func2 | Filter1 20:06:22.488594 | パイプラインから String型 の 1+1は? がきたよ! 20:06:22.497391 | -------- 切り取り線 -------- 20:06:22.499652 | パイプラインから Int32型 の 2 がきたよ!
となり、文の評価ごとにパイプラインに結果が渡されていることがわかります。
この仕様については正直どうよ?って思うところも無きにしも非ずですが、個人的な感覚としては、
なんつーか、"式を評価して最終的な値を返す"ってより、"式を評価して随時値をストリームに放流する"って感じがしっくりくる。 (当時のTwitterでのツイートより)
なのかなぁと思いました。
また、.NET系の言語で例えるとPowerShell全体のストリームという巨大なループに対して随時yield returnしているというのがイメージ的に近いかもしれません。
ちなみに値を返したくない場合は式ごとに[void]
でキャストしてやる必要があります。
また、値の代入は戻り値無しとして扱われます。
# 代入は戻り値無し扱い。 # ※戻り値がないので当然コンソールには何も表示されない PS C:\> $Value = Write-Output "1+1は?" # これは変数を評価するので String型の戻り値が返される # ※戻り値があるのでコンソールには "1+1は?" と表示される PS C:\> $Value 1+1は? # 戻り値を返したくない場合は[void]でキャストする PS C:\> [void]$Value
補足として、PowerShellの言語仕様書の7章(Expressions)に記載されている例をすこしだけ紹介します。
# 代入なので値は返されない $a = 1234 * 3.5 # ()でくくると$aが評価されるので 4319 が返される ($a = 1234 * 3.5) # インクリメントは代入扱い ++$a # ()でくくると値が返される (++$a()) # 値は返されない $($i = 10) # 10が返される $(($i = 10))
Returnについて
return
文はあくまでも制御を呼び出し元に戻すだけの構文となります。
about_Returnにも書かれていますが、
return $a
と
$a return
は等価であり、戻り値に特別な影響を及ぼすことはありません。
【2017/03/20追記】クラス内でのReturnについて
PowerShell 5.0からクラス構文が提供され、PowerShellでクラスの定義ができる様になっています。
クラスではメソッドが定義可能で、メソッド内でreturn
文を使用することができます。
クラス内で使用するreturn
についてはC#等のreturn
と同じ挙動となりますので注意してください。
【改訂新版】 Windows PowerShell ポケットリファレンス
- 作者: 牟田口大介
- 出版社/メーカー: 技術評論社
- 発売日: 2013/02/23
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (3件) を見る