Why do I need to have my functions written first in my PowerShell script?

Reorder your script

PowerShell is a script, not a compiled language. Therefore, it goes through the script line-by-line, top to bottom, (after tokenizing the script) and evaluates each command along the way. If it hasn't gotten to the definition of a function yet and you're already attempting to invoke that function, PowerShell will throw an error.

Therefore, in this case you must move the function definitions before the switch statement - as you've discovered.

Forward declarations

Even some compiled languages behave this way, most notably C/C++, and require forward declarations to work around this issue.

Other compiled languages like C# do multiple passes over the code during compilation so that forward declarations aren't required.


Remember that in general, what works in a script should work at the command line.

This was not true in CMD. GOTO and FOR %I IN (...) DO %%I are two examples.

In PowerShell, I can run commands at the command line until I get the result I want, then paste the history in to a script, then edit out the extraneous bits.

Also, I can take a script that isn't working correctly, paste it in to an interactive shell, and study the resulting state.

At the interactive command line, there's no way you could write this:

F
function F { "Hello, World!" }

However, when reading a script, I want to read the top-level code first, and then see more detail as I scroll down. One approach is:

function Main 
{
    F
}

function F
{
    "Hello, World!"
}

Main

You can also source your function definitions from a separate file:

Steps-Lib.ps1

# Since this is just function definitions it is safe to source
function Step1 { 
    'Step 1' 
    Step2 
} 
function Step2 { 
    'Step 2' 
    Step3 
} 
function Step3 { 
    'Step 3' 
    'Done!' 
}

Steps.ps1

# This sources the Steps-Lib.ps1 so that the functions are available
. "./Steps-Lib.ps1"

$stepChoice = read-host 'Where would you like to start.'

switch($stepChoice)
{
    1{Step1}
    2{Step2}
    3{Step3}
}

Tags:

Powershell