#Powershell Nihilism as Software Discipline
409 messages · Page 1 of 1 (latest)
I disagree with "idiomatic powershell" definition in context of the article. Additionally, it seems like OP should just write C#
Thanks! Not sure if I'm advertising... funny outlook... I'm just a guy who thinks better when I write out a whole problem; and have found that some folks appreciate hard rules that keep them safe. Especially in unsafe languages that are required use in most environments. Just try'na contribute man.
I did look for a spot to drop community contributions or whatever 💁♂️
Don't write powershell that looks like powershell so you can look like you know powershell. Serve yourself and your organization better.
Its a problem of underdog elitism those of us have in this ecosystem; try'na break free and get down to the meat.
Stop and think; Powershell is 'elite tier' sysadmin stuff. The powershell layer of junk makes it so my kid who's public school taught them all they need to know about making high-performant powershell code.... but when my kid goes to read powershell code... they feel stupid.
There's no reason for all of it; and it's elitist gatekeeping.
I can't say I agree with a few of these points. At some point if you hate things like the pipeline then maybe pwsh isn't the language for you. The typing stuff seems weird, I have no idea (or have encountered heard) any difference between [int] vs [System.Int32]. Speed things are also a moot point in most scripts, if you are nigling over ForEach-Object vs foreach statement then maybe a faster language is better for you.
Appreciate the share but I just can't agree with it 🙂
Powershell is my favorite language brother.
The big boys gotchu thinking I'm somehow some low-level developer.
No. They built a sticky ecosystem; made you feel stupid until you earned it; and now it's hard to realize and admit all the fluff actually keeps children back from joining us.
Just posting a link feels like advertising. If you wanted some dialog, you would say "hey I wrote this. what do you think?"
that's on you brother. I'm not responsible for your distrust in humaity.
Distrust? No. It is about clarity. I did end up reading it and assuming that you wanted some dialog about it.
This forum is about help more than less too.
No; there's nothing really to talk about. Try running a weekend project without breaking the rules.
So again; it sounds like you just want to advertise your opinion...
*I looked around for a spot; the other powershell discord has a spot
It is more or less cool. I'm just trying to get your perspective. I can certainly appreciate having strong opinions about powershell and pwsh.
Well; thanks for part of this; I have to go update the header; because this drew out the motive behind the motive I was talking with my wife about before getting going
But yeah I see now you are clarified more here. Your initial comment about a "funny outlook" threw me off and I didn't read as diligently as I should have.
But yeah this discord doesn't really have "contributions" and maybe it should...
This whole us vs them is hard to tease apart too
like; where's the channel for people to post their projects or what their working to encourage one-another?
It didn't jump out at me?
yeah that is fair. i agree with a place for that.
This is as good as any especially if you want some more focused dialog about the piece.
I wasn't sure if you wrote it to begin with either.
gotcha gotcha
For the sysadmin ,which is the target market for PowerShell in general, I would say your points make it harder for those folks. I can get down with several of points in the context of a more robust module. I guess your target audience is more devs or folks with mid-level experience with PowerShell.
I'm a sysadmin.
The whole death of powershell seems just like a ramp to c#
nope.
I see. Well you've got more experience than your typical click-ops windows sysadmin.
barely graduated high school. I'm a big dummy. Notice the concepts to achieve the goal are simplified. Not overly complex.
This is a dummy's exploration through a needlessly complex system.
It's because I can't keep my mind around the complex
I think you take for granted your knowledge. Many sysadmins wouldn't know about [int] or [System.Int32] for instance.
Breaking down the whole language primitives deal isn't dummy level either.
this is all past sysadmin into dev
public school; took a highschool class and skipped out and smoked weed most of the time.
I'm tell'in ya man. The pedagogy is all wrong; and it's making people give up on powershell.
My shop is full of Ex-powershell attemtptors because if it. Don't be siloed
Now my perspection could be colored because I haven't been exposed to a greater swath of sysadmins too.
And this article would only help a dev. I don't see it helping a noobie sysadmin.
with words like pedagogy you are obviously well-read at least. 🙂
Yeah; helps the people who'd read it because they'd teach it to the new guys instead of wasting time explaining all of the other junk
the "junk" you discuss is what helps the noobies though.
at least it is designed to help them.
PowerShell has its fair share of https://github.com/nightroman/PowerShellTraps
Give it some thought. I didn't just arrive here; I've been a koolaid drininking one-liner too-clever for my own good pwsh wraggler all the same. It wasn't worth it.
With the goal of getting more sysadmins using pwsh?
I'm in a similar boat. I embraced aliases to get people to use it. 😉
I figured sysadmins coming from cmd.exe would appreciate shorter commands.
That mabye microsoft was trying to create a ubiquitous platform and vendor lock the minds of anyone who might like this stuff...
well yeah i've read the monad manifesto and don jones' shell of an idea
*and it worked.
i'm not sure where you are going with the vendor lock piece. pwsh is open source.
so teasing out the goal.
- get more new users to powershell
- get them using faster and better practices?
Get-Process myprocess | Stop-Process
is easier than a variable declaration and foreach
at the shell.
well your foreach methods and such is more challenging when you are at the terminal prompt.
gotta bounce for a meeting
alright. later on.
@raven apex I'm gonna be completely honest, It was a really funny article. While not everything is accurate, I assume that was meant to be written like that, I did get quite a few giggles out of it.
I would love to see you contribute more, even if its more on the fringe side of things You might learn a lot more internals to things. Who knows I bet you can help a whole lot more people in #powershell-help, than this article will reach in the right stages of their learning of the language.
wait... what's not accurate?
i defy you sir! 😉
yes; i do play around a bit with words; perhaps I can clarify for you. A lot of folks in the powershell community.... believe one thing.... and that thing is wrong.
I dont want to lean towards that direction in this conversation, I would love to see you participate more in the PowerShell-Help community as well as Fringe channels more often. Its where the behind the scenes things happen .
sorry... We miscommunicated there... I replied 'at the shell' to something.... It might have been a run-on thought, that I've now lost.
Anyhow the goal is help folks stay safe and spend time learning the right stuff; not double learning; (especially non-transferable skills), not spending half a career holding back because "this stuff is for devs". The stuff point-and-click admins do every day to hold all the constructs they hold in their heads... they are the ones underestimated.
A million architectures and ideas from 'the best and brightest' all playing together, with only a shadow of the detail... The cognitive overload when context switching isn't just for 10x devs; so much so that we need to give them uniquely the right to unearth the arcane and gain systems level thinking. Binary is the first mathematics any of us ever learn man. Yes. No. It's not that hard. Some folks just get told their special for understanding it more than others; it creates a gap; a well researched gap in early childhood development onwards....
I started off as a networking guy; because the wires are wires and the lights blink, and no matter the box, i could hit a letter, then tab until the cows came home until I figured it out.
First solo powershell2.0 project was a 9000 member org migration from exchange 2007 to google apps. ...It was a trial by fire thing; I don't really remember doing much before that....
luck as it goes for the choices I made as a kid;
but yeah cabling jockeys can understand types. I can build you an ethernet frame by hand now if I really wanted to... And all of us pit monkeys are like that, Or we'd be doing different jobs. And if tooling would stop pretending we're dumb.
Yeah I think we do have a lot of common ground. I also think the GUI hides the system from the admin. Using powershell and the like lets you peel the curtain which is important for debugging.
Yeah; sorry that was the miscommunication there: I was juggling real work with this. pwsh on the terminal.... sorry the article only enters the frame once you open a file to create something permanent.
Yeah no problem. I did that too a bit while reading your article and your comments and such. It caused me to misinterpret things.
I also love powershell too. 😃
So I have a passion for helping folks to learn it and use it. I try my best at my current employer to help folks see the power of the shell.
I'm sitting here in a small shop with just a few guys... other than one 'kid' they've all been doing this for a lifetime.... all of them open up cmd , including our degreed folks.... I talk about powershell, throw it out to the kid; even the kid says its too much; and he's a papered Cyber-security guy.... pwsh is overwhelming for them; too much.
I feel you. I feel that pain.
I stay up too late, always have. that's all I've got beyond them 💁♂️
I did get one guy to cross over which felt great. He still has some to learn and he needs the basics but at least he sees the light.
Yeah I like to work. I like technology and learning things so I’m up late too and off hours working. It is the main way to learn something fast.
I try to suggest to the other sysadmins to start small and try to solve a problem with powershell when they have time. I do end up having to do the research many times and show the commands.
I may just need to work with a bigger shop is where I am at to keep the powershell going.
But I guess that's the point of the article; all of them are highly technical folks; and most have had a class or two at the post-secondary level on first-principles; So, this is my approach. Use what they know; don't ask them to learn new things; and in so doing, let them write better code in their first six months than most of us ever have.
I see now. Yeah I did take that approach too. Meet them where they are.
🤣 I guess I could make the case I was clocking hours in strategic planning
One of the issues with this approach is that the article is full of rules and just extra things people have to learn how does that help the "its too much" as now they need to avoid cmdlets, learn how to invoke .NET method, understand loops, use weird casting rules, etc. I can understand that this dynamic nature of PowerShell and shell oriented language features might make scripts a bit less strict but if you are going to jettisen all of that then you are just better off going to C# and gaining all the benefits it brings alongside the static typing/compile checks you get there
I have to agree with this sentiment. If I wasnt already deep into powershell and just starting, I can see how easily it would be to read this article and be put off by the "Quirkiness" of PowerShell.
For me however my belly jiggled.
*unlearn
just to clarify. Unlearn.
I've been over in the Pode discord for only a bit... but that's where all this started
Powershell is doing that already... all by itself.
I'm six months back into full time in a Microsoft Only shop; with our youngest of four finally off to the races. so yeah.... I'm surprised that in the microcosm of powershell didn't keep the same rate of change as the rest of the landscape; which is where I thought my 'rust' was going to show.... turns out a lot that was promised to be fixed a decade ago has turned from bug to feature.
Yeah.... so a six month long manic episode. (copy pasted from Pode DC). But I think that about concludes the background.
I do feel like a dad who asked their kid to clean their room; only to walk back in the door to find they've been playing games for hours.
Someone sent me the article which I read earlier. My comments to them were:
- Not sure how he can say "Underneath its simplicity is a pile of over-engineered abstractions trying really hard to look simple.", then go on to say "I want classes, type annotations, sealed behavior, and zero magic.". Classes are very much an abstraction layer, and while they're often right, they're often out of reach of the average joe.
- Not sure what his beef is with
$MyInvocation, there's significant value in reflecting on the given invocation and its something we do throughout the module. - Completely disagree with "Use
-not, not!. Save!for languages that care about you. at least enough to make it a first-class citizen.", as you might imagine 🤣 (I use a bang all the time) - The statement "Never use the pipeline unless you're at the terminal. Ever." is silly as pipelining is one of PowerShell's most powerful features and has significant benefits for filtration and other uses. That's like having car and saying "never use the brakes because they only slow you down"...
- Disagree with "Always prefer
-InputObjector passing explicitly via variables.", most-InputObjectparameters only accept a single object, not an array. Its there purely for binding via the pipeline - I was unaware of "PowerShell accepts fake enum values. Don’t trust the binding — enforce it yourself.", I've never seen that happen. Maybe it only happens outside or strict mode?
- "There is no faster or safer way to iterate: use foreach. Stop Trying. ...in both(!!!) versions of Powershell". The
foreach () {}loop is king, but$data | & { process { ... } }is marginally faster. - "$ErrorActionPreference = 'Stop' should be the first line in every script you write. Not negotiable.". Best thing old mate's written so far.
- "Enums and classes — there isn't time in the world. If you want them to be more than Snover’s shower-thought, write them somewhere else.". Agreed, we tried real hard with PowerShell classes, almost right up until we shipped v4
- "Dot-sourcing is an act of war — either against PowerShell’s module system, or against yourself. Choose wisely.". 2nd-best thing he's written so far.
All in all, most things are on point
-
classes a logical abstraction; but they are compiled; and therefore for the runtime; less abstract. More concrete. They also remove all the need for return flow control handling and clean up your debug process
-
If you're using $myInvocation to do contextual dispatch, I'm all for it; but if you're using it to see if you can build a better for-loop using powershell runtime features like .getsteppedpipeline... no
-
Pipeline filtering is slow and adds a bunch of nuance based on what cmdlet you might be throwing at it that you have to understand before you can use it.
ifsand well-named compound boolean filters. It's not a race-car; it's a fishing net. For small collections; do whatever you want. -
Yeah... well that's a logical fallacy. it is not
purely there for bindingit's there to recieve any input at all. It is the primary and only ingress to the body logic. Use it; don't use the|as an intermediary -
yes.
foreach...($i in $items)is marginally slower than$data | & { process { ... } }, but($i in Get-Data)is the best of both.... (not($i in (Get-Data))though obviously. -
Classes are the only thing close to predictable return flow you can get; if your a
print/write-hostdebugger and found yourself commenting and uncommenting your debug statements a thousand times.... it's faster to restart your terminal to refresh the class than it is to do the previous.... Plus... compiled.... concrete for the runtime.
Thanks for the read man!
I've never created a steppable pipeline as I've never had a need. I'm sure it has benefits, but I'm sure most people attempting to have just read an article and thought "that looks cool". When piping into anonymous scriptblocks and using the call operator, I've never needed to reach for more perf from the engine that a steppable pipeline may provide.
My only other comment on everything you've said above is that pipelining itself isn't slow, it's that ForEach-Object is, and most people blame pipelining when what they're piping into is the offender. You yourself have admitted piping into an anonymous scriptblock is performant. My main problem with pipelining is that you have no control on a per-item basis when piping into a cmdlet, so the entire thing has to work, and that piping into a scriptblock or even ForEach-Object makes for a crap stacktrace. I like using foreach () as its all on the stack of the calling function.
I should give credit where it's due also, one of the best things you've mentioned is that you can collect off statements, such as $output = foreach ($item in $items) {...}, $var = if ($otherVar = 1) { $yetAnotherVar }, etc. Most people don't realise this, but its one of PowerShell's most powerful features. Obvious props for mentions about avoiding global scope, etc as well
The only other thing I'd have thrown in there is some talk around strict mode as set with Set-StrictMode. It can help take a lot of the looseness out of PowerShell and ensure it stops on a dime. I don't like silent nulls for OOB access on arrays, etc. This causes stuff like that to throw a terminating error
I didn't include a bunch of alternatives because they can't be universally applied from 5<->7...
but; the logic comes from the addition of the .ForEach and .Where methods now available on collections in 7..... what do you notice? no |
It may because I'm used to Linux Pipelining... having become more familiar with that sooner; but on the left is a single process that gets disposed |--text is passed via stdOut--| the right is a new process
Whereas in powershell; there's a single-process and the GC has to spin up to manage the objects as they pass through the pipeline.
I just go 'Why?"
The .Where() and .ForEach() methods have been available since PowerShell 4, and .Where() is particularly useful as it has extra args you can give it to get the first x number of matches, etc. An example of this would be (1, 1, 1, 1, 1).Where({$_.Equals(1)}, 'First', 2), which is akin to 1, 1, 1, 1, 1 | Where-Object {$_.Equals(1)} | Select-Object -First 2. There's also some potential benefit/disbenefit to the .Where()/.ForEach() operators as they always return a collection, even an empty one. This means a potentially dangerous null in a strict mode environment is avoided, however maybe the true null is desirable. This also means that usage of them within a function where the output of the .ForEach() method isn't captured, it can return a loose empty collection into your output, potentially breaking things. For this reason, any usage of them must be nulled out, either by assiging to $null or casting to [void].
The idea I believe with PowerShell is so that data can be processed via the pipeline while it's still being streamed out of the source cmdlet. In your example above, if you were to put brackets around the object before the first pipe, it'd probably emulate that to some degree.
It's probably also just worth saying that PowerShell's meant to be a fun language to get things done quickly from an admin's perspective. Yeah there's dumb stuff you can do like +=ing arrays that is a first rate perf killer (recently addressed in PowerShell 7.5, I believe) that can be addressed with minor know-how, but all in all, I find it the most fun language I work with (PowerShell, C++, C#) and its easier to get into it over something like vbscript/batch is, so all in all despite its flaws, it's still a win in terms of Windows administration
what's dumb is that I didn't know there was a strict mode for functions/cmdlets and haven't tried it on a class
SINCE POWERSHELL 4 YOU SAY!?!?!?
see, yeah I was thinking about | pipelines in powershell 4....
I don't know how long Set-StrictMode has been there for. I want to say PoweShell 3, but don't hold me to it. There's three versions you can set as well. I personally use -Version 3 in my module code, however its often too hard on users. Most find -Version 1 on code someone else has to use/modify to be the sweet spot. Those .Where/ForEach methods are definitely PowerShell 4 additions though, I know that much for certain
Wherever you call Set-StrictMode, it's set for the SessionState you've called it from. If it's in a module, it's module-wide. If it's in a function, its just that function and any child funcs called within that SessionState, such as your module, etc
Well; I hit my writing goal for the week. But Imma definitely circle back around and add an update next week after playing around with strict mode levels.... can't thank you enough!
I Love PS with all my heart; and being able to sit on a 2008 box and just rock out a quick audit with the same code/commands I learned when Vista was angering the world cannot be overstated. Its amazing. (we just unearthed one on monday at a new-client onboard)
And powershell vs python... in this space.... powershell is my wife; python is my mistress.
*that didn't come out right! They are fun languages; and you're so on point with that
I don't know whether to ❤️ or 🤣 on the last message haha. No problems at all though my man, its been nice to get acquainted and I'm keen to see what your thoughts on strict mode at across all the levels! 🤘
to me, this is a case-in-point: https://discord.com/channels/535372312049090560/1354830047634264185
This person did their best to do it the "Powershell Way" (TM) , like the rest of us have.
#535372312049090566 message
started here again; to me... poignant.
That link doesn’t work. At least on ios mobile.
For someone who loves powershell, you got an interesting take.
Let me try another way to talk about it. What language features do you love? Is it the quick instantiation of dotnet objects? If no pipeline, what else do you love?
Or maybe it is the setting the output of a foreach() directly for a $var?
That server hasn't had much activity today; so its in #chat
I love that its everywhere; I love that its everywhere; I love that its everywhere; I loved it more when I thought I was a wizard for understanding it.
Maybe it is the context of usage on the language features that adds nuance.
powershell discord? I don’t see a chat channel.
🤔 ubiquity!
it's another server and we don't have access to it
Says unknown and I don’t have access to it.
not sure if Discord allows cross server links or that server doesn't allow access without an invitation
that's here
cuss
the link is for another server
yeah; a server where newbs maybe feel safe
That is certainly an interesting reason. So you could very well say the same about python or bash if your life went differently. 😉
I don't think our bot allows cross server links or at least links that have not been explicitly allowed
too much porn spam with Discord links
Yeah looks like OP is timed out.
if you reaally want to share it base64 encode the string or put it in a pastebin
eX5HrfZQ
Ha! Encoding your message!
is the discord dot gg path
gg/eX5HrfZQ
lol
I mean; I've got sooome python chops (in self-denegrating, unassured tone):
Multi-threaded/Multi-Process Downloader for Currency Exchange Rates from Histdata.com - dmidlo/histdata.com-tools
*pre-AI
I guess that's probably the idea of a silo
Gotta be honest boys.... I'm tired of fighting fires.... I wanna help the firefighters now.
https://powershell.one/tricks/performance/pipeline
This was the article that kicked off the article.... I had to circle back around today and apologize and backfill how it went down. I explained my heart there well enough in the comments.
The PowerShell Pipeline is robust but tends to be slow. With a couple of tricks you can speed it up tremendously and make it as fast as classic foreach loops.
I do wish he named that article "Speeding up ForEach-Object" instead. Yes foreach statements are faster as it's a pure language element, but the pipeline itself is fine in all but the most outrageous scales. ForEach-Object (and Where-Object) are slow for reasons unrelated to the pipeline
That entire pipeline article is pretty much why I just do & { process { ... } } or filter Out-Somthing { ... } setups everywhere now. Having everything processed in a child scope has benefits also
ForEach-Object has a niche benefit though of being able to invoke a scriptblock in its bound SessionState though. For instance, I might have a module function with a FilterScript argument. Invoking that scriptblock alone doesn't work as expected, however if I run it via ForEach-Object, it'll invoke properly and works as one would expect, with access to variables within its scope, etc
. $sb should work mostly the same
I really never noticed it being all that slow. Just read through the GitHub issue. Looks like sadly nothing became of it.
It hasn't from my experience, however I would have to test that again before I hand-on-heart say it doesn't work right
aside from $_, if that's what you're referring to then 👍
Well there's $_, but also variables defined in the caller's scope where they're defining the scriptblock delegate. You might have
$validVals = 'Val1', 'Val2', 'Val3'
Invoke-SomeModuleFunction -Filter { $validVals -contains $_ }
those will work fine yeah, unless you recreate the scriptblock
scriptblocks are bound to the session state they are created in
I'll have a play with that now to make sure I'm not speaking out of school here
& $sb will also work, though writing to a variable (unless scope is specified) won't be visible after execution (due to the new scope)
I misspoke earlier. Yes you can call it with the dot-source or call operator, but as you clarified very early on, $_ is not accessible. If the function accepting the filterscript is in the same SessionState, either operator works from my experience, but when the function is moved into a module, then it does not. I've got around this by doing ForEach-Object -InputObject $_ -Process $Filter, etc
yep! that's correct, session states are sort of like a stack of scopes. When looking for a variable it'll crawl the stack, and if it's not found it'll look in global. But only the top most scope in global (e.g. $global:x), no child scopes
ScriptBlock.InvokeWithContext is also an option, though you do not have the ability to dot source
🤦♂️ You guys.... 🤣 🤗 .... stop writing powershell in powershell. Use your training.
sorry you'll have to be more specific
You can’t make the stack smaller by more calls.
Every time you reach for powerShell, when you’re inside of powershell instead of going lower all you’re doing is tossing bits around
sorry metaphor is not really helping, if you'd like to have a technical discussion I'm happy to elaborate on anything
huh? | | | | | | | | | | | | <--- you want the call stack
|||| <--- to be small.
call stack alone isn't particularly important. At very large scales the extra command processor startup/teardown will be measurable but not by much
fine.
When folks start nesting PowerShell calls—say by passing ScriptBlocks, calling Invoke-Command, or using ForEach-Object -Process, especially with implicit closure dependencies like $_ or module-scoped variables—they're layering logical scope and execution context, not just the call stack in the CLR sense.
Each invocation like that spins up:
A new execution scope
Sometimes a new SessionState if invoked in a different module boundary or pipeline
An additional command processor context, which comes with its own set of overheads: parameter binding, variable isolation, scriptblock serialization behavior, etc.
So yes, the call stack might stay lean in the CLR, but PowerShell’s runtime environment balloons with transient scope complexity and context juggling, and that’s where the problem lives.
Stop nesting logic deeper inside the shell's own machinery if you can express it cleaner and flatter.
systems-level cleanliness.
When folks start nesting PowerShell calls—say by passing ScriptBlocks, calling Invoke-Command, or using ForEach-Object -Process, especially with implicit closure dependencies like $_ or module-scoped variables—they're layering logical scope and execution context, not just the call stack in the CLR sense.
yep! but generally speaking most variables in the nested invocation will be considered optimized locals by the compiler. Not when dot sourcing (and ForEach-Object does indeed dot source) but $_ specifically (and a few others) are special. They are often optimized even when locals optimization is disabled. This is due to SessionStateScope containing a series of MutableTuple's for dotted scopes.
But yeah, definitely agree that ForEach-Object is slower. That doesn't mean it isn't useful though. There's nuance in everything!
& $sb and the like are fine though, especially via steppable pipeline since then only a single command processor (and associated objects) are created for that entire pipeline. And it can be optimized!
Sometimes a new SessionState if invoked in a different module boundary or pipeline
Only new if a module is being imported. It can be a differentSessionStatefrom your current one, but it's reused.
So yes, the call stack might stay lean in the CLR, but PowerShell’s runtime environment balloons with transient scope complexity and context juggling, and that’s where the problem lives.
there may be times where it's needed to stick toforeachstatements, but generally it's inconsequential. Only very large scopes will the difference betweenforeachand& { process { $_ } }matter all that much
Stop nesting logic deeper inside the shell's own machinery if you can express it cleaner and flatter.
if that's your preference then you do you! Not objective truth though
Okay; so... I'm just say'in first.... most of my powershell code looks just like the next guy's. and you're 100% correct.... none of this really matters until you're in large collections. .... but.....
again yup. most variables get optimized as locals—but if we're relying on compiler-level tuple packing to justify nested invocation chains, we’re already way past what most maintainers can follow (Way outa my league on this one... but hey, it seems that's exactly where we are) . Performance isn't the only axis.
Just because the compiler makes it work fast doesn’t mean humans can read or reason about it cleanly.
ForEach-Object 'dot sources' sure—but only kinda. It gives you $_, but not in the sense that it inherits your lexical scope like a function would. It’s still its own pipeline segment with edge-case behaviors. Sounds like more 'PowerShell trivia night' than robust coding.
I tired of writing code that only works if someone memorized scope trivia from Stack Overflow.
If the code only starts behaving after you’ve read a detailed thread on how SessionState chains and MutableTuples interact… maybe that’s a smell?
If a technique needs three experts to explain why it's safe, it’s not safe by default.
I used to debate about the best build for a deck of magic cards too
again yup. most variables get optimized as locals—but if we're relying on compiler-level tuple packing to justify nested invocation chains, we’re already way past what most maintainers can follow (Way outa my league on this one... but hey, it seems that's exactly where we are) . Performance isn't the only axis.
totally, the end user doesn't need to worry about all that, it's implementation detail.
Just because the compiler makes it work fast doesn’t mean humans can read or reason about it cleanly.
ah so again we're into subjective territory. Totally fine if you findforeachmore readable, but a lot of folks find the opposite to be true. I'm good with either for most cases, though I too tend to preferforeach
ForEach-Object 'dot sources' sure—but only kinda. It gives you $_, but not in the sense that it inherits your lexical scope like a function would. It’s still its own pipeline segment with edge-case behaviors. Sounds like more 'PowerShell trivia night' than robust coding.
it's literally the sameSessionStateScopeobject. The part that makes it slow is the startup/teardown and unoptimized locals
If the code only starts behaving after you’ve read a detailed thread on how SessionState chains and MutableTuples interact… maybe that’s a smell?
nope not needed! This is just one of my areas of expertise, so I happen to be able to explain it here
it's literally the same SessionStateScope object. The part that makes it slow is the startup/teardown and unoptimized locals
and note, steppable pipeline doesn't have those issues at all
No.... yes. this is subjective.... but it's just wrong to do that to people. If we just take a moment to teach them a foreach... it becomes readable
AND transferable knowledge
AND explicit
AND safer
AND faster
sorry, something being your preference doesn't mean it's everyone's
🤦♂️
but hey we'll just agree to disagree and I'll step out of the thread. Feel free to ping if you have any questions though, always happy to explain internals
I don't think you explained much.
I used to keep a blog..... and that's a generous statement at that
sorry was that to me?
not sure I understand the relevance but anyway have a good night! Offer still stands either way
sorry for accidently closing the post for a sec hope that didn't mess anything up
gonna click the right button this time, 👋
just the lamest... "deference to preference" instead of hearing the pain from the community that wanted to but couldn't.... the [void] that wasn't.
I think maybe you should also take a step back and see how this can come across as arrogant and off putting. Understand that everyone has their own viewpoints and understandings and we can’t always agree. But instantly dismissing people’s viewpoints without any constructive response is not a great way to have a good dialogue amongst a community of people.
I’m sure you aren’t being, or meaning to be, arrogant and you surely know your stuff but a lot of your responses here have been dismissive or personal vibes dismissing other people’s viewpoints
nah; first impressions are everything.... I opened with a zinger.... grew up in a cold field and finished high-school late. I care about a category of people.
first thing that happened here was to be told to shuffle off.
I knew what I was in for.
If that’s how you feel then I’ll just leave you to it
Yeah I didn't realize you wrote the piece. So just a link posted threw me off.
please read that link. It would mean a great deal to me
some of your metaphors and less direct technical language can be harder to follow. it is like I'm reading a puzzle or a poem. 😉
I realized tonight that you weren't wrong
It is cool, friend. You don't need to give me a life story. I'll take a look at it though.
sorry... I'm slow...
hell of a ride. glad you made it out. reads like if Charles Bukowski was into tech. 🙂 I'll let him know.
I'm not out yet. But thanks it means the most.
Cheers! 🙂
Reflections
Whether I will it or not—I hold myself to my own standards, inescapably so. And my heart remains heavy for how all that turned out.
I’ve figured out why. I was bringing some job stress into the conversation that I didn’t realize I was carrying. That’s on me. Some of the intensity I brought was from asking PowerShell to solve a completely different kind of systems problem—one it simply cannot solve.
I do feel like I was gaslit. Or maybe it’s just that “this ain’t the crowd.” Am I the know-it-all? Or did I walk into a room of know-it-alls and foolishly say apple-cart-upsetting things? I’m still not sure how to feel about all of it.
I’m sure y’all get plenty of peacocks around here—but that’s not me. If you knew me, if you understood my approach to life and the things that actually motivate me, you’d see that money, notoriety, or status simply don’t register. In fact, I actively eschew these things. I believe they pollute clarity of thought. I was raised to see the world through a humble lens—and I think the things that trip people up the most are often the very things I try to steer clear of.
Isn’t the phrase “implementation detail” subjective anyway? I don’t know. That’s not even a helpful way to process.
I guess what’s bothering me most is that I feel yucky about not being able to clearly express that this wasn’t just a preference I was trying to communicate. I tried—but clearly didn’t do it right from the start.
It’s not just a preference.
Sure, it’s colloquial. Sure, it’s anecdotal.
It’s also an audit of the voices from the trenches—folks who can, but can’t.
And it’s why I keep hearing from people that the language is difficult.
As for metaphor: everyone I try to teach tech or programming concepts to tells me they appreciate metaphor. I’ll have to hold onto that. I don’t want to become the kind of person who’s out of touch with folks who actually struggle. I think that’ll be difficult, though—because all this material has always been hard for me.
Maybe it's been easy? ...I can only speak to the sensation. It's always felt hard. Like I have to 'will' my brain into acceptance...
Yesterday, I helped someone who was struggling in the ‘other’ PowerShell Discord. I hope it helped—even if just in giving them the courage to keep going. That’s a win, I think.
I never in a million years thought I’d accidentally go toe-to-toe with someone who—by all appearances—is working deeply on the internals of PowerShell. And yet… I still feel confident enough to maintain my stance: that some of this is verifiably a disservice, with no loss to rectify, no matter the “expert correction.”
^ …or at least for an organization that has the resources and will such as this; it could be verifiable.
I guess that’s a win too. Though it remains, it sure doesn’t feel like one.
First tech job as a career-changer was with Geek Squad and Best Buy; They had this email signature ritual of picking a few words to punctuate correspondence with 'type hints' toward the personality of the interlocutor. I chose carefully then, and you ever get an email from me they remain there today.
Best Regards,
David Midlo
Discovery | Integrity | Will | Organic | Stewardship
I’ve figured out why. I was bringing some job stress into the conversation that I didn’t realize I was carrying. That’s on me. Some of the intensity I brought was from asking PowerShell to solve a completely different kind of systems problem—one it simply cannot solve.
No worries! It happens to us all.
I do feel like I was gaslit. Or maybe it’s just that “this ain’t the crowd.” Am I the know-it-all? Or did I walk into a room of know-it-alls and foolishly say apple-cart-upsetting things? I’m still not sure how to feel about all of it.
You walked into a room full of passionate folks who spend their free time answering PowerShell questions and generally discussing PowerShell. A few of us have our 10k hours not just in using PowerShell but also talking to a lot of different folks from different backgrounds and skill sets specifically about PowerShell.
Not that this should necessarily change your view on my opinions, but I myself am a developer on the PowerShell team. The areas we're discussing are the areas I'm most involved in (before that I was a sysadmin for a long time fyi, dev is recent for me).
Isn’t the phrase “implementation detail” subjective anyway? I don’t know. That’s not even a helpful way to process.
It can be generally, but the area I was referring to is definitely considered implementation detail. It's not documented, not part of the change contract. That doesn't really matter though, I was explaining why your rule about nested calls doesn't really apply in the majority of real world scenarios. You don't need to know the implementation detail to know "actually nesting calls are fine", but it does need to be explained if someone is insistent that they aren't.
It’s not just a preference.
Sure, it’s colloquial. Sure, it’s anecdotal.
It’s also an audit of the voices from the trenches—folks who can, but can’t.
I dunno what to tell ya man, readability is very subjective. Plenty of folks find foreach to be less readable. Most aren't particularly worried about it one way or another, it's just not that big of a deal.
And it’s why I keep hearing from people that the language is difficult.
As for metaphor: everyone I try to teach tech or programming concepts to tells me they appreciate metaphor.
Metaphor is a great tool in a lot of scenarios. Technical debate (for lack of a better word) is where it's weakest. If I'm trying to correct misinformation, I need to get at the specifics if that makes sense.
I don’t want to become the kind of person who’s out of touch with folks who actually struggle.
Maybe I'm off base here and I apologize if I'm reading too much into this, but I'm getting the impression you think we don't often talk to inexperienced folks? They are by far the bulk of the people we interact with here. And generally speaking, the bulk of who we've interacted with throughout our careers
Maybe it's been easy? ...I can only speak to the sensation. It's always felt hard. Like I have to 'will' my brain into acceptance...
(...)
I never in a million years thought I’d accidentally go toe-to-toe with someone who—by all appearances—is working deeply on the internals of PowerShell. And yet… I still feel confident enough to maintain my stance:
Truth can only be found through repeated examination and re-evaluation of our beliefs. Distilling exactly why a belief exists and interrogating if it truly has value - or if our reasons are simply the ones our brains came up with as justification - is a very useful skill.
that some of this is verifiably a disservice, with no loss to rectify, no matter the “expert correction.”
To be clear there are definitely plenty of things I'd recommend against in PowerShell. It's got a lot of weird flaws for sure. Nested calls and the pipeline are generally fine though.
*definitly a personal reflection; don't read into it. I was worried you might.
*I've gotta close out discord for a for some days; I'm stuck on a that other problem... and it's destroying my health 😮💨. I'll be back. Thanks for some clarity.
no worries man, gotta take care of yourself! Wish ya well
Something about a long drive works pretty good for me. Before I go heads down on some things and don't get to revisit this while it's fresh in everyone's mind.
humor me for a second. Let's just say we do take that as a static; That folks have different styles... and that a guy like me might feel like he could help broaden the ecosystem with an alternative style...
Either from new-comers who only have first principles, so that we can say:
- "You'll learn some more sophisticated tricks as you go along, but this bespoke tool you built while you were learning will be there with you for the rest of your career (or at least until the next paradigm shift).
or:
- For those coming from other languages that have more explicit behaviors
- or for those who want P vs NP to be the problem instead of the platform
- those who want to write code once and know that it will scale without a major refactor. (same as above... but human element of refactoring involved)
- etc, you get the idea....
How would you continue my codification of this? <--- we got lost in the weeds; technical deep-dives are fun.... but let's just, for the sake of argument that is, assume 100% correctness from my assertions for the sake of seeking guidance here.
Not that it is likely these ideas would expand beyond 'fringe', I know I wouldn't have come here had these answers been offered in parallel as I was coming up; this is a thing I care about, so I might as well try to hone it into something that doesn't completely break the minds of incoming engineers of my work; or again, in the unlikely event that I'm on to something bigger; that I don't accidentally end up fracturing the ecosystem in even the smallest way; I think the platform itself protects against this in many ways... but I digress.
*ancillary but perhaps supporting question:
let's say; Implementation detail aside, I wrap the generator expression variant of a foreach in a cmdlet so it was more idiomatic; what do I lose? <-- As a mental excercise, I'm not running to psgallery to make another new foreach package or anything like that 🤣 .
I'm bouncing off and focus-timing discord for the next week after this.... just wanted to throw this out there.
humor me for a second. Let's just say we do take that as a static; That folks have different styles... and that a guy like me might feel like he could help broaden the ecosystem with an alternative style...
(...)
How would you continue my codification of this? <--- we got lost in the weeds; technical deep-dives are fun.... but let's just, for the sake of argument that is, assume 100% correctness from my assertions for the sake of seeking guidance here.
honestly I'm having a real hard time parsing what you're asking me there. The rest of this response will be assuming we're still talking about the whole pipeline/nested calls thing.
so some background you might be missing is that your suggestion isn't new. The myth that the pipeline is slow and that you should never use it is very old and long debunked, that's why I expressed my frustration with the title of the blog you were responding to. Even if you yourself did not hear this from someone else, it's one of a new that get parroted a lot because someone prominent said it without actually understanding what they were seeing a long time ago
as for what you should do if you have a style suggestion for folks, well you'd be fighting an up hill battle for sure - most people aren't particularly interested in changing their preferred style. You definitely wouldn't want to phrase it as objective truth because that will without a doubt trigger defensive responses. You'd want to back it up with concrete reasons if you wanted a fair shot at convincing anyone
let's say; Implementation detail aside, I wrap the generator expression variant of a foreach in a cmdlet so it was more idiomatic; what do I lose?
so I was unsure what you were referring to here so I went through the blog post to see if you mentioned it. I assume you're talking about this line?
foreach ($file in Get-ChildItem -Recurse) {}is the correct form. This is a lazy-loaded generator expression.
to be clear this isn't lazily loaded. The command will be invoked, it's output gathered into a single array, and then it will iterate that array after the command completes. It's just a normal foreach statement
on second thought I'm guessing that's not what you're referring to since it wouldn't do anything to wrap that in command. So I'd need to see more of what you're talkin' about to comment.
The way command output works though is blocking concurrency, when an object is written to the pipeline (which always exists, even if there is no visible downstream command) it immediately calls the code for the downstream command's process block and does not return until it's finished. So basically, the way it works it you can't have a generic way to call any command and lazily pull it's output (aside from as a downstream command)
I found it.
I thought it was in here
It’s not
Here; chapter 4
I couldn’t remember
I tore apart my entire library to find it.
And you’re mistaken, about my opinion about the pipeline
The pipeline is like cigarettes for teenagers; I was looking for one simple rule, and I know that I came up with too many.
It’s a gateway drug.
I love powershell in the same way that I like python.
They’re both expressive multi paradigm languages that make it easy to onboard new people; and more importantly to reason about your own code later when you’re feeling like a dummy, trying to read your own work.
It is incredibly and deceptively simple sometimes; it’s amazing.
So my question to you to clarify is if you were to develop your own pipeline-free style what would be your axioms that you think would arise in due course of consideration?
to be quite frank if I were to throw away large portions of the language I'd use a different one. Afraid we're not likely to agree on much there
Yes, but what about a pragmatic world where Microsoft is the dominant player in commerce? Where such things are unavoidable.
Saying change language languages from powershell is like saying humanity has a future of a happy and fulfilled existence on Mars.
Ain’t gonna happen.
Flowershell is the air we breathe and it’s not going away.
👋🏼 flowershell was on accident 🤣
It's more saying if you are changing PowerShell to be not like PowerShell then what's the point of using it in the first place. Using another language like C#/Python/whatever that suits your style is a better choice
I love powershell; please put that idea out of your mind that I don’t.
I'm not saying you don't but I don't understand the benefit of throwing away half the language features
at that point it's not PowerShell anymore
just humor me and say that’s acceptable. It’s a lateral thinking exercise.
I am humoring you 🙂 If you remove pipelining and casting behaviour of pwsh then it's not a language I think I would enjoy or recommend. At that point I get really nothing over something like C# but now the negatives of a non-compiled language
Again, assuming there are no other languages that have ever been invented.
when I'm using a different language I use the standard conventions of the language, even if I don't particularly like them.
you're welcome to use whatever style preference you want, I don't know what you want me to say there. What would I do if I wanted to do things my own way regardless of convention? I'd do things my own way regardless of convention I guess
I mean, that’s the fact, so let’s accept that as excluded from the exercise. Following convention for human readability is an assumed. But it’s not part of what I’m asking.
Constraint breeds invention, and innovation
I guess I don't see the point, what's the end goal you have in mind here. Improvements to the language, stylistic guidelines, something new entirely?
There are a few already out there and as you've encountered they can be very personal preference
Suppose I’m in introducing a new style guide with my article
Can you help me make it better?
We sort off are, maybe not directly but you've seen how some of the suggestions from the original post somewhat contradict our preferences and recommendations. It's not saying you are wrong but it's also saying you aren't right
And there are certainly things I prefer that seeminglyscience probably doesn't and vice versa. Just as there are things you think are good ($ErrorActionPreference = 'Stop') but others I cannot agree with (avoiding the pipeline, explicit .NET casting, etc). We are neither right or wrong and we can advocate our own personal preferences but we can't force others to use our styles if they don't agree with it
I’m obviously representative of some spectrum of powershell user who avoids powershell when they can; there’s a lot of really talented folks out there who could maybe find a little slice where they spend more time in powershell.
Obviously, the Internet complains about every language since time in memorial. I came here with that as an assumed.
But that’s how languages get better.
Sure, just as there are multiple other types of users who use PowerShell. We all have our own perspectives which have been formed from our own use cases and way of working. Same as in Python there are so many different crowds of users who use it which both drive the language and ecosystem going forward. You'll probably see a data scientist use it in a different way from a sysadmin. Same as in pwsh, someone coming from C/C++/C# would write in a different style from a general sysadmin who is more used to scripting than a compiled language
Also just to reiterate, you've done nothing wrong by posting that blog post or linking it here. Just be aware that not everyone will agree with what you say and to not take it personally
Obviously, I could just do all of my work with Python and APIs, these days. But I’m here talking to you guys about my favorite language.
I’m looking at the python ecosystem, I’m looking at the JavaScript ecosystem, and they all actively teach embracing different styles as you develop.
It’s hard for me to believe that you haven’t noticed that about powershell…. I say so gently.
Not looking for agreement, gentlemen.
I’m looking for you to understand my goal.
I think I can understand your goal, I just can't agree with your recommendations
Based on style, if so, I think we can agree that’s an acceptable division.
at this point, I guess I am looking for a little bit more than that on the technical side of things.
Which is why I proposed the exploratory question of what would happen if you were to wrap the generator expression form of a foreach loop in cmdlet.
Is it truly functionally identical? Or have I missed something in my research?
can you elaborate on what you mean there?
I guess you don’t have to consider a wrap….
But conceptually what I’m saying is all the guts of foreach-object; take it out and put the generator expression in.
Have I broken functionality?
I’m on mobile…. I’d have to pull up the source.
I think it’s less what does that term mean technically but what do you see that being in powershell
any details could help really
Things like handy scriptblock processing go away, right? That kind of stuff?
are you asking what happens if in a script you replace something that was using ForEach-Object with a foreach statement?
No, not quite; I’ll have to go back to the source and get back to you get my thoughts together more on it.
*side note.
Oh, I missed that. ‘Generator Expression’. Pythonic term. Keyword is the same though
yield.
foreach ($i in get-item)
If you use it in a pipeline then it is essentially a generator
yeah ^ the pipeline is basically PowerShell's equivalent. It can't really be made to work like that when used in foreach if that's what you're asking
You could probably hack it in with some shim that results in an IEnumerable but it can’t be done natively. This is why the pipeline is so crucial to pwsh if you want to stream things outside of .NET calls
even then you'd need to run it in a different thread since it doesn't have a way to exit the method
So yeah, not super familiar with the architecture; would I be wasting my time if I tried to start working on something like that for a pull request?
it would require every command to use yield return basically, and a lot of architecture changes
basically no I don't think it's feasible
With full acceptance of that. I’m disappointed. Consider that on my wish list.
I do wish that was part of the initial design for sure - but atm even if it were feasible it would be a tough sell. The pipeline already provides that functionality, so impact wouldn't be that high
That; ($I in (Get-Item)) would resolve, but absent that it would yield.
yeah I get ya. Like how Get-Process | % Name works vs (Get-Process) | % Name
right
Do you have link to the source where this is at?
- rather... the snippets that flashed through your mind that made you say "basically no"?
it's sort of all across the code base, but I suppose the most relevant line in a round about way is this one https://github.com/PowerShell/PowerShell/blob/f44c11c7bbf9269c7f6d110ba498d228bfe56bd0/src/System.Management.Automation/engine/Pipe.cs#L463
many many others would need to change though
basically every command ever would need to be rewritten to use yield return instead of WriteObject. The pipeline processor would need to change a lot. The PowerShell compiler as well
Yeah; I saw what you were saying immediately.... I just want to read it. thanks!
that's where I was
private StatementAst UsingStatementRule(Token usingToken) <-- there... *furiously swapping spaces on Mac
&
private ParamBlockAst ParamBlockRule()
my entry point anyway.
It'd be gross to just parse it and drop it into the pipe as an aliasisy-kinda-thing
parser can't help ya there. It'll still be a command invocation, which will still call the PSCmdlet.* methods, which will have the same problem of not returning until completed
...mmmhmm... sure... understood. ....lol... maybe...
um... If I've presently found myself here at these:
https://github.com/PowerShell/PowerShell/blob/master/src/System.Management.Automation/engine/CommandProcessorBase.cs
https://github.com/PowerShell/PowerShell/blob/master/src/System.Management.Automation/engine/CommandProcessor.cs
https://github.com/PowerShell/PowerShell/blob/f44c11c7bbf9269c7f6d110ba498d228bfe56bd0/src/System.Management.Automation/engine/cmdlet.cs < protected virtual void ProcessRecord()
Am I closer to wrapping my head around this?
ProcessRecord is the binary command version of a process block. It's definitely related
Thanks
my mind is melting... um.. I'm trying to reason about how it's emitting objects.... I can't put a finger on it yet... but... its that that idea?
it gets added to a Pipe which then either passes it to a downstream command or if it's List<object> backed then added to a list to be unwrapped after it's completed
No, the shim... um... like ProcessRecord ...and all the other cmdlets would have to be refactored to yield an IEnumerable; is that your two brains and explanations put together?
they'd need to be refactored to use yield return https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/statements/yield
(and ofc all of the architecture around it would need to accomidate that change)
Pipe... downstream... would need... to change...
thousands of cmdlets
.....
yeah.... sure... I get that.... the WriteObject piece... um...
I meant like this public override IEnumerable<object> ProcessRecord()
yield return foo
yep that's right, theoretically anyway
but... wait
linq
that'd be fun.
say all this was in-place already....
Get-HeavyData |
Where-Object { $_.IsValid } |
Select-Object Id, Value |
Export-Csv -Path data.csv
Would.... no... um... what would this do?
🤷♂️ that is undetermined
*i'm on the lazy-load....
I'm really only describing the high level issues that prevent it from being easily added into the current architecture. Actually designing how it all fits together after changing that is an entirely seperate project
.... I have a hunch it would.... maybe not do anything until it hit Export-Csv
like linq
um...
var results = bars
.Where(x => x.prop)
.Select(x => x.prop2)
.OrderBy(x => x);
I'm sure this goes without saying but just in case it needs to be said, due to the amount of breaking changes and size - this isn't something PowerShell could actually consider even in a PR
so how it works in this fork is w/e you want really
lol... not sure where you're at; but I'm CST and roll'in up on 2am. I'm just daydreaming
I saw your point when you said it.
HUGE; Powershell10 huge
EST 😛
yeah I figured, I've just figured that before and then had to turn away wild PRs months later so better safe than sorry
Noooo... 🤣 🤙
est..... 🔥
well my style guide is f*'d
part of it.
I completely see that; Can't thank you enough.... jerk. 😉
whole foreach topic was predicated on ($i in Get-Item) being this.
think I've put off sleep long enouhg, have a good night!
you too, sleep well 🛌
Thanks for having patience with me ALL!
starting to make my rounds on making sure I correct any misunderstandings I've put out there in the wild already.... but I wanted to take some time to encode what it was that brought me here. I went with JS to abstract it from powershell technicalities and for the use of ===.
here's my style-guide so far:
const SLA = 99.999;
const techSacrifices = {
familyTime: true,
health: true,
personalLife: true
};
const performanceMetrics = {
speed: 100,
efficiency: 100,
maintainability: 100
};
const lowPerformingCode = (metrics, sla = SLA) => {
const speedCheck = metrics.speed < sla;
const efficiencyCheck = metrics.efficiency < sla;
const maintainabilityCheck = metrics.maintainability < sla;
return (speedCheck === true) || (efficiencyCheck === true) || (maintainabilityCheck === true);
};
const isImmoral = (code, sla = SLA) => {
return lowPerformingCode(code, sla) === true;
};
const checkCodeMorality = (codeMetrics, sacrifices, sla = SLA) => {
const immoral = isImmoral(codeMetrics, sla) === true;
return {
isImmoral: immoral === true,
message: immoral === true
? "This code is immoral! 😈\n" +
"It disrespects the sacrifices of everyone in tech—engineers, line technicians, and all others—who give up family time, health, and personal life.\n" +
"We owe them better. We owe them performant, maintainable systems.\n" +
"It is inheritantly immoral, even when written by moral agents."
: "This code is virtuous! 😇\n" +
"It honors the dedication and sacrifices made by everyone in tech.\n" +
"Fast, efficient, and maintainable—just as they deserve."
};
};
// Example usage
const result1 = checkCodeMorality(performanceMetrics, techSacrifices);
console.log(result1.message);
“I must study politics and war that my sons may have liberty to study mathematics and philosophy.
My sons ought to study mathematics and philosophy, geography, natural history, naval architecture, navigation, commerce and agriculture
in order to give their children a right to study painting, poetry, music, architecture, statuary, tapestry, and porcelain.”~ * Excerpt from a letter written by a forlorn John Adams to his wife a world away; Abigail Adams. May 1780*
https://founders.archives.gov/documents/Adams/04-03-02-0258
Here i thought this would be better in fringe
The Steppable Pipeline Article, Three discord servers, Bluesky, and LinkedIn Powershell PowerUsers.... ouch that hurt.
https://dev.to/dmidlo/powershell-nihilism-as-software-discipline-3e6p
On a brighter note, I recovered a cherished possession, and hit my writing goal for the week #shoplocal:
Thanks again all!
My revised philosophy with foreach now clearly not being a drop-in replacement for the the yielding-style pipeline behavior would be this; it's well-known progenitor and inspiration:
- Prefer going vertical with your code instead of horizontal.
I think, and you all likewise must, that this has played itself out. Thanks again; I'll pop in again sometime... probably much in the same way. Sorry in advance 😉
To quote Anthony Kiedis: More I See, Less I Know
One of my LinkedIn connects posted this today..... I was like; yup.
I feel compelled to comment on this one since it's near the top and I'd read it several times ```ps
enum State { Start; Stop }
function Run { param([State]$Mode) $Mode }
Run 'Destroy'
It doesn't do what you say at all ("PowerShell accepts fake enum values. "). It rejects the argument.
```ps
PS> function Run { param([State]$Mode) $Mode }
PS> Run Destroy
Run : Cannot process argument transformation on parameter 'Mode'. Cannot convert value "Destroy" to type "State".
Error: "Unable to match the identifier name Destroy to a valid enumerator name. Specify one of the following
enumerator names and try again:
Start, Stop, Restart"
There are potential problems with use of enums for parameter bindings, but this is not it.
This one is a problem, it'll take the truthy value. Since Start is 0 it gets discarded. The composite argument used below is still acceptable as a single coerced string value:
enum State { Start; Stop }
function Run { param([State]$Mode) $Mode }
Run 'Start, Stop'
It'll also accept truncated string values (where there's a unique match), for better or worse. So this is acceptable: ```ps
Run 'Sta'
So you still have an argument for "Use ValidateSet". It's just you have the wrong assertion to back it up.
https://github.com/dmidlo/Get-DataHash/blob/main/private/types/DataHash.psm1
um... I was working on this when this tripped me up when I was refactoring..... I'll have to remember the specific circumstances. I was writing heart-on-sleeve raw at the time under sleep exhaustion 🤣 .
I'm glad for it; because I wouldn't have taken the time to get better dx by implementing the algorithmhelper class.... um I wonder if it made it into a commit
I'd argue one of the best defences against that problem is to MD5 = 1, which will autonumber from there, and just avoid falsey values in the enum.
I don't think it made it in; I can't find anything that's jogging my memory now 😢
lol; it wouldn't have made it in...
😬 .... what do you think of the code?
its a gen1 algo.... I have most of the details of gen2 worked out.... there's flaws and features missing from this that I need for what I'm trying to build.... but part of that is going to be a LiteDB provider; so I'm just working on the logic 'on paper' to get rid of the some of the flaws, increase deterministic guarantees when mixed collections get larger, and an XPath style exclusion to get a little bit more specific targeting for ephemeral fields. Provider means I wait until a C# refactor.
https://github.com/dmidlo/SOGHS/blob/main/CRUX-IDX.md
*kinda alot more... but... those are the primary concerns.
AlgorithmHelper arguably unnecessarily introduces case-sensitivity into the enum values.
You should probably hidden the other private properties.
The first DataHash constructor unnecessarily summarizes and hides the exception behind a string message.
$InputObject is (to me) a bit of an odd name for a constructor argument. But it's just a variable name so that's entirely personal preference.
You could avoid duplication in the ctor if you were to add a method to deal with it's body.
You've a few places where you copy a hash set. You could have just return [HashSet[string]]::new($this._ignoreFields).
Since you always initialize ignore fields, you may as well just move that back to being a default value for the property.
This assertion doesn't do what you think (implied by the code) it does (line 177 and at least one other point) ```ps
$InputObject -is [PSCustomObject]
It's testing to see if the value is a PSObject because that's contextually a type accelerator (and PSObject can box anything). It's only what it says it is when it's a parser instruction. If you *really* wanted to check for a custom object you'd have to use the full type name.
`_isScaler` suggests it's checking for something that isn't a collection, but it would return `false` for anything other than a primitive or string.
When you implement equatable or comparable, you will find that you need to explicitly declare `IEquatable` and `IComparable` in your class definition (for some consumers, like `Sort-Object`). This will affect the signatures you can use because classes in PS have... issues.
This statement on 195 will always emit true (rhs is always true).
```ps
if ($InputObject -is [string] -or [System.Collections.Generic.IEnumerable[string]]) {
and then I run out of chars I can type :-p
Blocking to a specific depth would be important as well. I am betting that the circular logic check is ignored in certain situations.
but I don't know anything about development. 🚒🔥
I needed to write some 'chaos' style tests to get into some of these spaces.... These logical errors a a bit embarrassing though! 😅
🤷♂️ those happen to everyone. It's why we test.
Pester testing 🤷♀️ and code reviews?
I can't tell you how many times i've found a typo in my code review comments. and had to argue stylization for choosing one cmd over another..
I have to remind my co workers some times that hand waving a pr is dangerous
yeah there's always style stuff 😄 Use of .ForEach everywhere would get a comment from me too.
I had to go into detail a few weeks ago about how Assembly.LoadFrom fixes a dependency issue against conflicting binaries
I'm doing my best right now; slappin crap together to do right by some folks
oh sure, and all comments above should be dismissed or acted upon as you see fit.
If I had to formally approve your code and you worked with me, it would take rather longer. But I don't, and you don't have to care about any opinions I may hold on it because they may be contextually irrelevant.
I think you need to find a bigger pond to swim in.
No man, no need to back off from that. Can't tell you how amazing it is having any feedback at all. *sorry I had walk in a circle for a sec
Some of it is quite interesting, that PSCustomObject thing for example... I see that one at work a bit too often (where we have a large number of average to proficient PS code writers, and a smaller number of advanced to expert).
I probably need to add it to our own enormous conventions doc.
It's a nasty gotcha I mostly see in that proficient to expert gap.
This describes the extent of the problem:
[PSObject]$a = 1
$a -is [int]
$a -is [PSCustomObject]
$a -is [System.Management.Automation.PSCustomObject]
$b = [PSCustomObject]@{ a = 1 }
$b -is [PSCustomObject]
$b -is [System.Management.Automation.PSCustomObject]
Where the PSObject wrapper can be added to any type, and PS will silently, and contextually, strip it away.
In this case of course I've forced the issue by explicitly adding the PSObject wrapper around my int. But it can exist anywhere and if you don't absolutely control input...
I would actually check if its just PSObject in $object.Psobject.PSTypeInfo
you can prevent false positives
I'm sorry boys; my brain completely shut down with a big mix of feels ending in gratitude; um I'm humbled... uhh anything else I should be looking at to improve the shape of it? or comments on maybe what I'm looking at the bottom of this for Gen2 ?:
https://dev.to/dmidlo/the-problem-powershells-hashing-illusion-74p
It's shut down.... but I'm going to be digging through these notes after a full rest ❤️
my design is more fleshed out and a couple things have changed, but I have it hidden behind a .gitignore in the SOGHS project until have some better prototyping done
Honestly I find the tone of the article leads me to want to object to it 😄
Instead of stating your problem (I want to hash objects), and explaining how you tackle that, you're immediately into saying "this is PowerShells fault".
But the root cause of that problem is ordering (or lack of) in things implementing IDictionary or ISet (although not exclusively those). You would have had the same problems if you were trying to do this in C# or any other .NET language.
I gotta figure tone thing out
More neutral language really. I didn't find an existing way to address my problem in PS, so here's how I tackled it.
Then you have an interesting article where you can discuss the approach you've taken, the problems you ran into and solved, etc, etc.
https://github.com/dmidlo/ps-migration/tree/main/private/db
this is the context; slap-together; unfinished.... but as I worked on it; I also began to see how I might accomplish a walk on live graphs....
It's a poor-man's powershell object drift/version control system based on litedb
I guess you could go straight to types... this arch is completely toasted now though
it was never going to live in poweshell forever
that'd be the provider i mentioned
this was the original hasher before the refactor, for example
python too
iirc
yeah, I would expect this problem to apply to a lokt of languages
this is where alllllll the heavy lifting is done.
I don't use the built-in DbRef system of LiteDb; Ref would be a misnomer there. It's abstracted up just one layer of identity from lite's objectId so data can be migrated consistently from one instance (well, file) to another when needed.
Bundle is an Application Object (hopefully any object powershell can deal with) ... git tree equivalent.
to use 'poor-man's' again; There's some merkle aggregation going on to create the layers of identity needed to do indexing based on ps object derived identity.
might be hard to visualize.... um....
maybe just paste it into ai and ask it to tell you about it....
anyway; that's the context of trying to get a consistent object hasher; Obviously in order to provide any guarantees to myself around it.
*this db layer was going to be published on psgallery as 'ReLiteDB'..... It's just a subsystem for trying to solve a different problem.
lol you are not making me jealous that's for sure
Like I said; Big mix of feels, ending in gratitude. Thanks for looking at my code and giving some tips! I'm going to dig into them in the moring.... but... i gotta get up with the kids in a bit. Nice meeting you!
and you
This is an issue that was closed 2017.
I don't understand why you want to reopen it. by parsing words here.
I don't think it's the appropriate place to be airing so much as well.
@raven apex We need to practice better discipline when commenting on github issues.
- github is for fixing code and discord only on the initial issue. Otherwise it can cause confusion as to the direction needed to be taken.
- Discord is for commentary, discussion around an issue and airing your life story.
- Everybody in the github issue thread as well as others receives email updates by default of your comment. 👀
something about wits and ends.
Thanks again is all.
I'm going to grab some of the info you guys laid out and move on with life; this thread will self-destruct in a couple hours.
*I fell alseep otherwise I would have responed sooner
There are things; .... you know... I told my son:
"Learn from other peoples mistakes so you can make new and beautiful ones of your own"
I'll never in my life regret transparency; and anyone who stumbled in can only benefit it ways beyond the stack.
I didn't intend for email dispatch, or reopening an issue.... that... was an oversight.
Apparently some things are not up to me on discord. I'd like to request moderator review for the deletion of this thread. I can only close it.
"Learn from other peoples mistakes so you can make new and beautiful ones of your own"
^ weighing this; .... what fades fades, what remains remains.