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}
}