💾 Archived View for pwshnotes.flounder.online › gemlog › 2022-09-01-anonymous-function.gmi captured on 2024-08-24 at 23:56:22. Gemini links have been rewritten to link to archived content
⬅️ Previous capture (2023-01-29)
-=-=-=-=-=-=-
A function is a collection of program statements bound to a function name. Then, when the function name is invoked, the statements are run with any provided input.
In principle, anonymous functions are functions without names. Here, the statements are used immediately. For example, this can be useful for something like a mouse click where a particular action is associated with the mouse click. The same action is not used elsewhere. And a function name is not necessary.
I maintain a list of bookmarks for my file system. This is a hash table of strings.
$bookmark = @{ journal = "/data/Michael/Journal" powershell = "/data/Michael/PowerShell" }
We can use these strings as input for the Set-Location cmdlet. Issuing the command below will change the current directory.
Set-Location -Path $bookmark.powershell
Editor's Note: Since I'm mixing commands and output below, I include the prompt symbol > before the commands I typed. If you copy these commands, omit the leading >. ^C indicates where I pressed Ctrl-C which normally stops execution. Here, I use Ctrl-C to skip lines with comments.
One problem with my process is that if I mistype the key name for the hash table, the command fails silently. So, I am in the habit of checking where I am.
> # Mistyped name. ^C > Set-Location -Path $bookmark.powershel > Get-Location Path ---- /home/michael > # Correct hash table key name. ^C > Set-Location -Path $bookmark.powershell > Get-Location Path ---- /data/Michael/PowerShell
This process could be improved in two ways:
For the first point, I would prefer to use only the hash table and key without any proceeding cmdlet.
> # Example ^C > $bookmark.journal > Get-Location Path ---- /data/Michael/Journal
I would need to store anonymous functions in the hash table values for this to work.
No.
PowerShell can store code in script blocks. Script blocks are objects.
Specifying an object on the command line outputs a value:
> $a = Get-ChildItem > $a Directory: /data/Michael UnixMode User Group LastWriteTime Size Name -------- ---- ----- ------------- ---- ---- drwxr-xr-x michael michael 9/1/2022 05:02 4096 Journal drwxr-xr-x michael michael 9/1/2022 15:33 4096 PowerShell
In the case of script blocks, specifying a script block on the command line prints the commands without executing the code.
Here, I use semicolons ; to explicitly terminate my statements.
> $b = { Set-Location ~ ; Get-Location ; } > $b Set-Location ~ ; Get-Location ; > # Literal string output. ^C
The closest you can get to an anonymous function in PowerShell is to execute the contents of a script block.
You can use the call operator &
> $c = { Set-Location ~ ; Get-Location ; } > & $c Path ---- /home/michael
Note that since I intend to use a hash table later, I use the variable $c in the example above. But the variable is not required. You can invoke script blocks directly.
> Get-Random 866754637 > { Get-Random } Get-Random > & { Get-Random } 1481025786
Use the Invoke() method on the script block:
> $d = { Get-ChildItem ; } > $d.Invoke() Directory: /home/michael UnixMode User Group LastWriteTime Size Name -------- ---- ----- ------------- ---- ---- drwxr-xr-x michael michael 8/30/2022 05:26 4096 Desktop drwxr-xr-x michael michael 12/23/2021 07:14 4096 Documents drwxr-xr-x michael michael 8/29/2022 17:32 4096 Downloads
You can use Get-Member to discover the Invoke() method if you forget.
The Invoke method name will appear under the Name column. And the MemberType will be Method.
> $e = { Get-Process ; } > $e | Get-Member TypeName: System.Management.Automation.ScriptBlock Name MemberType Definition ---- ---------- ---------- CheckRestrictedLanguage Method void CheckRestrictedLanguage(System.Collections.… Equals Method bool Equals(System.Object obj) ... Invoke Method System.Collections.ObjectModel.Collection[psobje…
Remember to include the trailing parentheses () on method calls.
> # This returns the method definition. ^C > $e.Invoke OverloadDefinitions ------------------- System.Collections.ObjectModel.Collection[psobject] Invoke(Params System.Object[] args) > # This invokes the code. ^C > $e.Invoke() NPM(K) PM(M) WS(M) CPU(s) Id SI ProcessName ------ ----- ----- ------ -- -- ----------- 0 0.00 22.46 3.10 764292 …22 vim 0 0.00 21.59 4.51 860098 …30 vim 0 0.00 316.77 341.40 838982 …54 vivaldi-bin --enable-crashpad 0 0.00 36.67 0.00 859799 …54 vivaldi-bin --type=broker
After researching script blocks in PowerShell, I updated my bookmark hash table with script blocks { ... }
$bookmark = @{ journal = { Set-Location -Path "/data/Michael/Journal" -PassThru } powershell = { Set-Location -Path "/data/Michael/PowerShell" -PassThru } }
Now, I can change directory by placing the call operator & before the hash table. The -PassThru parameter outputs the current location; now I know if my command succeeds. And, if I mistype a key name, I receive an error.
PassThru is a parameter of Set-Location.
> $bookmark = @{ >> journal = { Set-Location -Path "/data/Michael/Journal" -PassThru } >> powershell = { Set-Location -Path "/data/Michael/PowerShell" -PassThru } >> } > & $bookmark.powershel InvalidOperation: The expression after '&' in a pipeline element produced an object that was not valid. It must result in a command name, a script block, or a CommandInfo object. > & $bookmark.powershell Path ---- /data/Michael/PowerShell
Hash Tables | PowerShell | Microsoft Docs
Set-Location | PowerShell | Microsoft Docs
Script Blocks | PowerShell | Microsoft Docs
Get-Member | PowerShell | Microsoft Docs
Running Executables | PowerShell | TechNet Wiki
Appending Text on Multiple Lines | Vim Help
Created: Thursday, September 1, 2022
Updated: Thursday, September 1, 2022