Hash tables -- how do you return them from a Function?

Welcome Forums General PowerShell Q&A Hash tables -- how do you return them from a Function?

This topic contains 4 replies, has 5 voices, and was last updated by

 
Participant
3 months, 3 weeks ago.

  • Author
    Posts
  • #109838

    Participant
    Points: 194
    Rank: Participant

    I am missing something as to the nature of hash tables in relation to parameter passing of functions in Powershell (PS).

    I understand that the PS hash table is by its nature, a reference type and not a value type.  So when I call a function and pass it a hash table, the use of [ref] has no meaning.  So I am tacitly assuming — and perhaps incrrectly – that calling a function and passing it a hash table as a parameter will necessarily have to be by value, which is the PS default.   I note that when I call the function I have in mind, it starts out with an empty hash table.

    
    $ht = $Null
    
    $ht = @{}
    
    Func $ht
    
    

    But what if I have a function whose job it is to build a hash table that will vary in content according to other input parameters?  How do I "return" the constructed hash table at the end of the function?  E.g.,

    
    Function Func ([hashtable]$arg) {
    
    # ... build hash table
    
    }
    
    $myht = $Null
    
    $myht = @{}
    
    Func $myht
    
    # ... upon return from Func, how do I access $myht?
    
    # can I just write :
    
    $a = $myht.key
    
    

    Any tips, advice or clarifications would be highly appreciated.

  • #109843

    Participant
    Points: 5
    Rank: Member

    Ramon,

    I don't think the issue here is really about a hashtable. It is about function parameters and return values regardless of type.  Recommend reading about_functions and about_return.  You can use ctrl+j in ISE for simple code snippets to get syntax examples as well.  Here is an example of basic syntax for a function in PowerShell.  I'll return a hashtable to illustrate.

     

    function MyFunction ($animal)
    {
        switch ($animal)
        {
            'dog' {
                @{
                    scientific = 'Canis lupus familiaris'
                    higher = 'Canis'
                }
            }
            'cat' {
                @{
                    scientific = 'Felidae'
                    higher = 'Feliformia'
                }
            }
        }
    }
    
    $myanimal = Myfunction -animal 'dog'
    
    $myanimal.scientific
  • #109849

    Participant
    Points: 195
    Helping Hand
    Rank: Participant

    It can be easy and it can be less easy depending on the input, e.g. if you have nested hashtables.

    If you have a simple hashtable you can use .clone() straight away.
    E.g.

    Function Func ([hashtable]$arg) {
    
    # ... build hash table
    
    $workTable = $arg.Clone()
    $workTable.Add("Text2", "Test2")
    
    $workTable
    
    }
    
    $myht = $Null
    
    $myht = @{}
    $myht.Add("Text", "Test")
    
    $output = Func $myht
    

    In the above $myht and $output will differ.

    If you have nested hashtables you would need to recurse through the hashtable and clone each nested hashtable.
    At the end of this blog post you can find an example.
    https://kevinmarquette.github.io/2016-11-06-powershell-hashtable-everything-you-wanted-to-know-about/#copying-hashtables

    A cleaner way of doing nested hashtables clones is to use the .Net libraries.
    https://stackoverflow.com/questions/7468707/deep-copy-a-dictionary-hashtable-in-powershell

    Edit:
    Just to clarify, the above is if you don't want to change the hashtable that you use as input to the function.
    In your example $arg will reference $myht, so by updating $arg it will also update $myht.

  • #109853

    Participant
    Points: 297
    Helping Hand
    Rank: Contributor
    function Do-Thing {
      $ht = @{}
      $ht.Add('Key1',12)
      $ht.Add('Key2',11)
    
      $ht # write hashtable to output
       
      #  alternates:
      #  Write-Output $ht
      #  return $ht 
    }
    
    $NewHashtable = Do-Thing # store function output
    
    $NewHashtable['Key1'] # outputs 12

    That's the idea. In a function, you either drop things to output by putting it on a line by itself or using Write-Output, in general, and you capture that by assigning a variable to the output of the function.

    It's not necessary to pass the hashtable into the function to do this. You are correct in that hashtables are generally passed by reference. However, making sure that your function does not alter the input data and instead creates its own data to pass along will save you a lot of headaches down the line.

    If you have 4 functions that all might alter the input data amongst themselves and something doesn't quite work right, you will spend forever chasing that annoying little bug. If you have the same 4 functions that are crystal clear in where they take input and where their output goes, you will have a much easier time. 🙂

  • #109994

    Participant
    Points: 894
    Helping Hand
    Rank: Major Contributor

    I hope you have got tips, advice and clarifications here. The power of community.
    I suggest you to go with return keyword as it adds a kind of documentation as well.

The topic ‘Hash tables -- how do you return them from a Function?’ is closed to new replies.