Help us understand the problem. What is going on with this article?

PowerShell・再帰・トランポリン

More than 1 year has passed since last update.

ネタ元

JavaScript・再帰・トランポリン

PowerShellで似たようなことをやってみたくなったので、やってみた。

バージョン

PowerShellでスタックオーバーフローを起こしたいなら黙ってv2を使うんだ。

PS C:\> $PSVersionTable.PSVersion.ToString()
2.0

スタックオーバフローが起きる関数

filter countDown ($num)
{
  if ($num -eq 1) {return 1}
  if ($num % 200 -eq 0) {Write-Host $num}
  countDown ($num - 1)
}
PS C:\> countDown 1000
1000
800
600
400
200
呼び出しの深さのオーバーフローのため、スクリプトが失敗しました。呼び出しの深さが 1001 に達しましたが、最大値は 1000 です。
    + CategoryInfo          : InvalidOperation: (1001:Int32) []、ParentContainsErrorRecordException
    + FullyQualifiedErrorId : CallDepthOverflow

評価が遅延されるように、関数を定義し直す。

filter countDown2 ($num)
{
  if ($num -eq 1) {return 1}
  if ($num % 200 -eq 0) {Write-Host $num}
  New-Trampoline $function:countDown2 ($num - 1)
}

filter New-Trampoline
  ([ScriptBlock] $ScriptBlock, [Object[]]$ArgumentList)
    {$ScriptBlock | Add-Member NoteProperty ArgumentList $ArgumentList -PassThru}

トランポリン

filter Invoke-Trampoline
{
  while ($_ -is [ScriptBlock] -and ($_ | Get-Member ArgumentList))
    {$_ = Invoke-Command $_ -ArgumentList $_.ArgumentList}

  $_
}

確かにスタックオーバーフローは起こらなくなる

PS C:\> countDown2 1000 | Invoke-Trampoline
1000
800
600
400
200
1

おもしろ~い

おわり

yumura_s
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away