Variable scoping in modules

This topic contains 0 replies, has 1 voice, and was last updated by  Forums Archives 5 years, 11 months ago.

  • Author
    Posts
  • #5271

    by davidski at 2012-11-12 21:03:45

    I'm very confused with some variable scoping behavior I'm experiencing. Take the following sample module:

    $script:intTemplate = 1

    [xml]$script:xmlTemplate = @"




    "@

    function getvar {
    $myint = $script:intTemplate
    $myint++
    Write-output "Myint is $myint while intTemplate is $intTemplate"

    $myxml = $script:xmlTemplate
    $e = $myxml.CreateElement("MyChildElement")
    $myxml.SelectSingleNode("/test").AppendChild($e) |Out-Null
    $myxml.Innerxml.tostring()
    $script:xmltemplate.Innerxml.tostring()
    }

    Importing that module and running getvar gives the output:

    PS C:\Windows\system32> getvar
    Myint is 2 while intTemplate is 1


    Further runs of getvar continue to add more and more child elements to $xmlTemplate while $intTemplate remains the same. How $xmlTemplate is getting changed with no assignment functions and how is scoping (or XML) giving me an unexpected opportunity to demonstrate my ignorance?

    Very confused and grateful for any guidance,
    David

    by nohandle at 2012-11-14 07:57:38

    If you assign the integer value to another variable a copy of the value is made not a reference so the changes are not reflected in the second cariable.

    see this example code to learn the differnece in the behaviour.
    $hash = @{name = 'john'; surname = 'smith'}
    $first = New-Object -TypeName psObject -Property $hash
    $second = $first
    $first
    $second
    "---"
    $first.name = 'Daniel'
    $first
    $second

    $a = 10
    $b = $a
    $a
    $b
    "---"
    $a=11
    $a
    $b

    by davidski at 2012-11-14 08:15:11

    Very interesting...and also rather weird. While I'm still new to PowerShell, one of the theme's I've heard again again is that "everything is an object." It sounds like some objects are more object-y than others. In this case, $a and $b are both Int32 objects, but get passed by value while $first and $second, as PSCustomObject's, get passed by reference. Is there some documentation that indicates which objects get passed by value versus passed by reference?

    I understand what's going on, just not the reasoning that will help me determine if a future object assignment will be done as a valuation or reference operation.

    David

    by nohandle at 2012-11-14 08:28:22

    To be more descriptive there are two categories of types in powershell immutable and mutable (or value and reference types).
    The immutable are passed by value – that means that every assignment or change to the value creates new "instance" that is passed and that is not bound to the original one.
    The mutable are passed by reference – unless you create a .clone() of the object you pass just reference to the one shared object.
    Most of the primitive types (int, double, string, ??singleton classes?? etc.) are immutable and the other classes, array and hashtable are not.

    Not sure how to detect the two types though. Because is .isValueType is false for string but true for int

    by nohandle at 2012-11-14 09:01:02

    [quote="davidski"]I understand what's going on, just not the reasoning that will help me determine if a future object assignment will be done as a valuation or reference operation.[/quote]
    Frankly I needed to differentiate between these two once or twice so far. If you refactor your function to two functions pass the values as arguments and output them, you avoid the passed by value/reference dilema 🙂

You must be logged in to reply to this topic.