Peter M.
Peter M.

Reputation: 856

How to pass an array argument to a function

I have implemented a simple merge sort function in PowerShell like so

function Merge-Sort
{
  param($a)
  if ($a.Length -gt 1)
  {
    $m = [Math]::floor($a.Length / 2)
    [Int[]]$l = $a[0..($m-1)]
    [Int[]]$r = $a[$m..($a.Length)]

    Merge-Sort $l
    Merge-Sort $r

    $i = $j = $k = 0

    while ($i -lt $l.Length -and $j -lt $r.Length)
    {
      if ($l[$i] -lt $r[$j])
      {
        $a[$k] = $l[$i]
        $i++
      }
      else
      {
        $a[$k] = $r[$j]
        $j++
      }
      $k++
    }

    while($i -lt $l.length)
    {
        $a[$k] = $l[$i]
        $i++
        $k++
    }

    while($j -lt $r.length)
    {
        $a[$k] = $r[$j]
        $j++
        $k++
    }
 }
}

The functions does what it should and sorts an array of integer values:

 $arr = @(22,44,55,11,66,11,77,99,33,88)
 merge-sort $arr

The output is: 11 11 22 33 44 55 66 77 88 99

But when I define the function parameter as [Int[]] to make clear that it should be an array of integers instead of object something went wrong and the array stays unsorted:

 function Merge-Sort
 {
    param([Int[]]$a)
    ...
 }

The output is: 22 44 55 11 66 11 77 99 33 88

My question is:

Why does the correct way to define the function parameter leads to an incorrect result (the array does not get sorted)?

Upvotes: 1

Views: 2639

Answers (1)

ArcSet
ArcSet

Reputation: 6860

When the object $arr is created since it wasn't defined as a int array [int[]] it was created as a [array]. When passed to the function originally before [int[]] was added. It passed the reference and changed the data. If you Added a addition object to the array it would have not returned anything ether since that would have created a new array object.

When you added the [int[]] to the parameter it created a brand new int array [int[]] object named $a and changed the data there. Since $a is never return the variable is killed at the end of the function.

If you passed a int array it would have manipulated that array.

Lets looks over a few examples

This will change the first value at index 0 to 5. Since no object was added to the array and the array can be any object in the parameter it allowed the reference to index 0 to be changed instead of a whole new object needing to be returned

function TestFunction($a)
{
    $a[0] = 5
}
$TestVar = @(2,3,1)
TestFunction -a $TestVar
$TestVar

output 5,3,1

Since the orignal object is type Array and the parameter is type int array. the function will create a new int array based on the input array. Since the function needs to return the new int array and there is no return it will be garbage collected.

function TestFunction([int[]]$a)
{
    $a[0] = 4
}
$TestVar = @(2,3,1)
TestFunction -a $TestVar
$TestVar

So in your case we can do

function TestFunction([int[]]$a)
{
  $a[0] = 4
}
[int[]]$TestVar = @(2,3,1)
TestFunction -a $TestVar
$TestVar

since the parameter is looking for a int array and the input is a int array and no new objects are being added or subtracted from the array it will change the value correctly.

Upvotes: 2

Related Questions