6

As I learn about how Perl and PowerShell differ, I'm trying to pin down differences between passing and updating lists by reference. I think I get the idea now, PowerShell-wise.

Pass a hash table by reference:

When the function is called: It isn't necessary to precede the table's name with [ref]. Within the function: The table's name in the param list can be preceded simply by [hashtable], not [ref] — (because "as received" it is already a reference; so it was explained to me). If the hash table is to be updated within the function, .Value is not needed when [ref] hasn't been used. IOW: call the function this way: MyFunction $MyHashTable. The function contains:

param([hashtable]$HashNameWithinFunction)

$HashNameWithinFunction.Add('x', 'y')

Pass an array by reference:

Both when the function is called and in the function's param() list: the array's name must be preceded by [ref]. When the array is to be updated by reference, .Value must be used. The function is called this way: MyFunction ([ref]$MyArray). The function contains:

param([ref]$ArrayNameWithinFunction)

$ArrayNameWithinFunction.Value += 'something new'

Is my understanding correct? I've tested the above and I know both work. But is there any potential for some subtle error in doing it those ways?

Adding this following reply from Chrstian:

function UpdateArray {
    param([ref]$ArrayNameWithinFunction)
    $ArrayNameWithinFunction.Value += 'xyzzy'
}
$MyArray = @('a', 'b', 'c')
UpdateArray ([ref]$MyArray)
3
  • sorry but.. what is the array that you are using that has the property value? Commented Nov 16, 2012 at 12:44
  • The named variable that denotes the reference to the array (within the function). I'll update the question with a short example. Commented Nov 16, 2012 at 18:25
  • After your correction the value paramereter have more sense without the need of your example! Commented Nov 16, 2012 at 19:54

1 Answer 1

7

Your understanding is correct. A little addition: you are passing hashtables by value, because you will be adding to it, and hashtables support adding natively. Arrays are immutable in regard to their size (+= actually recreates the array behind the scenes), so if you are planning to add, you will need to recreate it, hence the need for ref.

Keep in mind though, it is best to avoid passing arguments by reference. At some point you may forget it's done like that, and spend more time debugging your code. If you need to change the array, better return the new one on the pipeline.

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks. Interesting. I had thought (mistakenly) that as "received" by the function, the hash becomes a reference (and thus isn't passed by value). Re: returning the updated array on the pipeline: can you recommend either a site -- or possibly one of the PoSH books -- that provides some syntax examples of that? Thanks again.
@marst12017: for your example - arrays - just put a return $yourArray statement when the new array is ready to be returned. For more complex situations, you can just put $yourAnotherObject and it will be returned to the pipeline, while your function continues processing. So you can return multiple objects raw - without a need for an array or hashtable. Then pack them into a high-level object later, if you need to. You can read about output in Powershell here.
My approach with functions in Perl scripts: write to scalars or lists by reference; the function returns false if there were serious errors of some sort (file not found, etc.etc.). The calling statement then "knows" if it should continue or halt, send mail about the error, etc. The article (thanks for that) suggests I should think about this in entirely different ways. I want calling statements to "react" depending on what happened. (An array or hashtable being empty, "post-function," might not be an error.)
@marst12017: you could use both approaches, it's just the one I described is more OOP and so more recommended when using Powershell. If you want to error, you can use exceptions, for a pure .NET experience. Then it would be not just true or false, but also type of the error returned within an exception object. For example FileNotFoundException.
I realize this is a four-year-old thread, but regarding handling errors: this is exactly what throwing exceptions is for. :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.