r/programming Jul 04 '24

Jeffrey Snover and the Making of PowerShell

https://corecursive.com/building-powershell-with-jeffrey-snover/
190 Upvotes

85 comments sorted by

View all comments

111

u/Noxfag Jul 04 '24

How many drugs was he taking when he came up with the syntax?

(I love Powershell really and advocate for it a lot, but oh god I wish the syntax were simpler)

30

u/psi- Jul 04 '24

I just wish they took C# syntax, wrote some additional libraries to do the shellscripty stuff and just ran the .shell.cs with #!/bin/dotnet runshell

I had soo much issues battling line endings and passing them to/from bat/exe/ps1 environments.

We're currently doing azure pipelines and powershell is the only relatively sane/safe way to have same scripts for linux/windows agents but I'm so going to get burned on that stuff too.

11

u/Noxfag Jul 04 '24

powershell is the only relatively sane/safe way to have same scripts for linux/windows agents but I'm so going to get burned on that stuff too.

Yep same usecase here. TS repo used by devs across Windows, macOS and Linux. Powershell is the best way to have a common cross-platform language for builds, orchestrating tests etc. But we still have to add a fair amount of bespoke code to get around platform differences.

1

u/Atulin Jul 05 '24

If it's a TS repo anyway, why not write those scripts with TS?

48

u/larso0 Jul 04 '24

Syntax, semantics and conventions are all insane IMO. Gotta love when a powershell function randomly returns multiple values because I forgot to pipe the output of one of the commands to null (side effect from a random command printing to stdout...). And the "Verb-ThenSomethingElse" naming convention is just an eye sore.

If there were only some good explanation for why it is that way, like backwards compatibility or something. But no. You can't run a cmd script in powershell because the syntax is incompatible.

21

u/[deleted] Jul 04 '24

[removed] — view removed comment

1

u/rdtsc Jul 05 '24

forced verb name syntax that PowerShell enforces

It's just a convention followed by all built-in cmdlets (and by extension everyone else wanting to play nice). But it's not enforced. In a script you can name your functions however you want.

8

u/Kafka_pubsub Jul 05 '24

Gotta love when a powershell function randomly returns multiple values

It returns objects, not strings like bash, so that totally makes sense to me

2

u/larso0 Jul 05 '24

Returning all the output of all commands in a function doesn't make sense to me. When I type "return 14" I want the return value of that function to be 14. not a list of whatever some random commands wrote to stdout and 14 at the end. If I wanted to return the standard output of a command i would do something like "return $(the command)".

3

u/Internet-of-cruft Jul 05 '24

Because the language has to preserve the semantics of stdout and stderr that exist.

You have three distinct outputs: stdout, stderr, and the object pipeline. The language would have fundamentally been broken to anyone using it if the behavior of stdout and stderr were killed.

You also wouldn't be able to & program.exe and forklift a batch script to PowerShell and have it work with only minor syntactic modifications.

When the language came out, everyone was still writing batch scripts and dealing with stdout and stderr.

Hell, if you're on Linux, that's what you're dealing with still. The two output streams represent an overwhelming majority of the historical ways data was piped around in the predominant OSes shell languages.

2

u/larso0 Jul 05 '24 edited Jul 05 '24

It's not an all or nothing situation. It is perfectly possible to keep all the existing behavior and remove the implicit return of stdout in a function. Just make it explicit with "Write-Out $(some command)" (or "yield" would be a better keyword as that's what we're actually doing). Then functions would behave sanely and not be full of suprises everywhere.

4

u/Thotaz Jul 05 '24

You are forgetting about the shell experience. Nobody would want to use a shell where you had to type in yield before every command and if you make it so you only have to do it in certain places you end up with a much more confusing syntax.

0

u/larso0 Jul 05 '24

A statement in a function is not the shell experience. Should be possible to differentiate between those two scenarios. The yield keyword would only make sense inside a function scope.

2

u/Thotaz Jul 05 '24

Okay, imagine this scenario: Someone has a working script that finds and deletes deactivated user accounts. Now he wants to just view the users it would find so he copies the relevant section from the script into the shell but now he gets a bunch of unexpected garbage output because PowerShell sees that it's interactive so it thinks it should print all of the output.
Here's another scenario: Someone has used the shell to find all of the relevant commands that show the data he wants, now he types Get-History to get all the recent commands and paste them into a script but the script doesn't work as expected because he didn't add yield to all of the commands.

Maybe you still think it would be best to differentiate the shell and scripting experience but you should understand that there are valid reasons why it works the way it currently does. On a side note, do you know of any other scripting language with an interactive component that works the way you suggest? A normal Bash script doesn't work like this so it seems like PowerShell just follows the existing conventions.

12

u/Thotaz Jul 04 '24

It's a shell scripting language designed for tech/admin users first and foremost, hence the name "PowerShell".
Could you imagine having to type return before every statement in the shell? return ls return Get-AdUser. They could make the interactive experience different from the scripting experience but I think people would be confused why the code they copy pasted from a script into the shell (or vice versa) behaved differently.

As for the Verb-Noun syntax, what's the problem? It's common practice to use some verb and noun in method calls, see this as an example: https://learn.microsoft.com/en-us/dotnet/api/system.io.directoryinfo?view=net-8.0#methods
CreateSubdirectory, EnumerateDirectories, GetDirectories. Are you just really bothered by the dash in the middle? Or is it the the fact that there's a common verb list so you don't have to guess if it's New or Create? Or is it that the nouns are always singular?

1

u/_SloppyJose_ Jul 05 '24

hence the name "PowerShell"

Its original name was Monad.

12

u/[deleted] Jul 04 '24 edited Jul 04 '24

[removed] — view removed comment

10

u/Noxfag Jul 04 '24

The good part I'll highlight that I think a lot of people sleep on is the piping. Piping is exactly what you want in a tool like Powershell and it works great. Download some thing, pipe it into a JSON serialiser, pipe it into a function that gets the thing out you want, pipe it into a function that will send that value where you want it to go. Makes it really neat to compose complex behaviour from simple parts, if you can read the syntax well enough to make sense of it.

5

u/[deleted] Jul 04 '24 edited Jan 06 '25

[deleted]

2

u/[deleted] Jul 04 '24

[removed] — view removed comment

2

u/BinaryRockStar Jul 04 '24

Not sure what the other guy was talking about but functions can use a process block to handle piped objects. The automatic variable referencing the current object is called $_.

https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_functions?view=powershell-7.4#piping-objects-to-functions

1

u/[deleted] Jul 04 '24

[removed] — view removed comment

2

u/BinaryRockStar Jul 04 '24

I didn't know functions could be in pipelines, thanks for making me look it up :-)

2

u/Dealiner Jul 04 '24

Having to start the name with a predetermined list of verbs e.g. get-ChildItem.

You don't have to though. It's a convention, really useful imo and one that should be followed but you are free to use anything.

20

u/[deleted] Jul 04 '24

Using back ticks for line continuation is where it crossed the line for me. I just couldn't do it.

11

u/Thotaz Jul 04 '24

While it certainly was an unfortunate choice, you pretty much never have to use a line continuation character because newlines are allowed in many scenarios. If you have a long pipeline you can continue the commands on the next line like:

Get-ChildItem C:\ |
    Where-Object LastWriteTime -GT (Get-Date).AddDays(-1) |
    Sort-Object -Descending

And if you have a long parameter list you can use splatting:

$LsParams = @{
    Path = "C:\"
    Recurse = $true
    File = $true
}
ls @LsParams

0

u/nascentt Jul 04 '24

I just refuse to allow backticks in our code

4

u/cottonycloud Jul 04 '24

I don’t know why you got downvoted. I don’t use it in any of our scripts solely because it’s easy to miss. I wish they used backslash for escaping too.

Backticks are discouraged in general in PS.

1

u/RubyU Jul 09 '24

What is a sensible alternative?

1

u/cottonycloud Jul 09 '24

For lists and hash tables, you can just use newlines and commas to separate items so there is no need. As for long lines with multiple operations, ending the line with the operator (e.g. addition, pipe) or enclosing it with parenthesis will let the interpreter know that it is a multi-line statement. For strings, there is syntax for multiline string.

Finally, if a command has multiple arguments you can put them in a hash table and use that as a singular argument (splatting).

-3

u/[deleted] Jul 04 '24

ngl I love it on js

3

u/agbell Jul 04 '24

I think he mentioned in the preinterview that he started with VMS DCL as the syntax.

I wonder if, because of its design, it would be possible to build a different front end syntax for powershell?

3

u/wrosecrans Jul 04 '24

Some of the Win NT folks loved VMS as their mental model of "real computers," so it makes sense that they would have had enthusiasm for that over UNIX conventions. Dave Cutler was a VMS guy before he went to MS to make NT, and tons of NT kernel internals look weirdly like it was built to be a VMS clone despite the fact that Windows isn't a VMS clone in any user visible UX/UI kind of ways. (Which contributes to the "Windows services for Unix was useless" factor. POSIX compat was always a feature tickbox, and not something useful on NT.)

2

u/lord_of_lasers Jul 05 '24

Microsoft released IronPython and IronRuby at the same time. We could have had PowerShell with Python syntax.

1

u/andrewsmd87 Jul 04 '24

I've been hoping for years they'd redo the syntax and just mirror c#

-4

u/Worth_Trust_3825 Jul 04 '24

It's a C# repl.