Note: In addition to the immediate bug, the current behavior of selecting the explicitly defined parameter set with its mandatory parameter in parameter-less invocations is questionable as a whole - see the proposal below.
function foo {
[CmdletBinding()] # No default parameter set.
param(
# Only one explicitly defined parameter set, comprising
# one mandatory and one optional parameter.
[Parameter(ParameterSetName='bar', Mandatory)]
$MandatoryInItsSetButOptionalOverall,
[Parameter(ParameterSetName='bar')]
$MustBeCombinedWithMandatory,
# An untagged (all-parameter-sets) parameter.
$UnrelatedAndOptional
)
# Echo the effective parameter set.
$PSCmdlet.ParameterSetName
}
# Note: This will (questionably) prompt for a -MandatoryInItsSetButOptionalOverall value.
# Submit any value or just press Enter.
foo | Should -Be 'bar'
The test should succeed.
The test fails:
Expected strings to be the same, but they were different.
Expected length: 3 Actual length: 18 Strings differ at index 0.
Expected: 'bar' But was: '__AllParameterSets'
That is, even though set bar was clearly selected - otherwise there would have been no prompt - __AllParameterSets was then reported as the effective parameter set.
As an aside regarding the fundamental behavior:
As the naming of the parameters suggests, bar _shouldn't_ have become the effective parameter set by default.
While that can be worked around by naming an (otherwise unused) different _default_ parameter set in the [CmdletBinding()] attribute, doing so shouldn't be necessary - see the initial post of #11143 for an example, and the proposal below for a potential resolution.
PowerShell Core 7.0.0-preview.6
This time (!) I think you are right and PowerShell is wrong. (Although "It's a corner case" and "Don't write like that" also apply to some extent)
param(
# Only one explicitly defined parameter set, comprising
# one mandatory and one optional parameter.
[Parameter(ParameterSetName='bar', Mandatory)]
$MandatoryInItsSetButOptionalOverall,
[Parameter(ParameterSetName='bar')]
$MustBeCombinedWithMandatory,
# An untagged (all-parameter-sets) parameter.
$UnrelatedAndOptional
)
Says "I am naming one parameter set". With one set we expect PowerShell to create a second parameter set so you can have "Not the 'bar' set" and it names this '__AllParameterSets'
Here's the table of what it should do
$MandInSet $MustbeComined $unrelated Result
- - - Not Set "bar"
- - X "
- X - Set bar, prompt for mand
- X X "
X - - Set bar OK as is
X - X "
X X - "
X X X "
And it seems to use this logic to report the parameter set name, but it uses different logic to decide what to prompt for - there it says "There is only one set and that has a mandatory parameter".
If you declared two sets explicitly i.e
[Parameter(ParameterSetName='bar')]
[Parameter(ParameterSetName='Fud')]
$UnrelatedAndOptional
The problem goes away. But PowerShell should either say "Error: you have defined only one parameter set" or, if allows one set it should use the same logic for prompting and set name.
To avoid breaking existing scripts it can't throw an error, and can't stop prompting, so, as you say, the "wrong" part is the set name.
Good analysis.
As for "it's a corner case": only in the sense that it may not be _common_, but it is a legitimate scenario.
As for "Don't write like that": You _should_ be able to write like that, because all the information is there to infer the intended behavior; it is just a variant of the more general problem described in #11143: The need to _work around_ the questionable behavior by artificially introducing another parameter set designated as the default [CmdletBinding(DefaultParameterSetName='Fud')]; or, even more cumbersomely, using the workaround you suggest
([Parameter(ParameterSetName='bar')] [Parameter(ParameterSetName='Fud')] $UnrelatedAndOptional)).
We can discuss can vs should vs must :-)
But people _should not_ write functions / cmdlets which define a single parameter set, but it is _allowed_. Legitimacy is a matter of opinion ... and inferring intent which isn't written is potentially dangerous.
Dividing things into one set doesn't make any sense, so PS has to either make a second set or throw an error if someone does that. But when the only declared set has a mandatory parameter it goes the "safe" way . So this won't run without a name or ID
Function BadOne {
param (
[Parameter(ParameterSetName="ByID", Mandatory=$true)]$ID,
[Parameter(ParameterSetName="ByName",Mandatory=$true)]$Name,
$waitForServer
)
if ($ID) {runsql "Delete from Foo where ID = $ID"}
else {runsql "Delete from foo where name like '$name*'"}
if ($waitForServer) {Start-Sleep $waitForServer}
}
If I'm lazy and don't write the mandatory, it still doesn't run with out a name or ID , PowerShell protects me from my own bad (but perfectly legal) code. You and I have done that one to death :-)
But if I take out the ID parameter, PowerShell will decide I can't get into the function without the name parameter. It's handling code I really should not write (but am allowed to write) in the safe way. It's not clear without naming a second set that I want things to proceed so PS so it requires me to be explicit (which good, usually) but that is also cumbersome (bad, usually). I'm fine with that side.
But if someone depends on the parameter set name (as they might if this is something from which a parameter has been removed) things will break; it needs a single named parameter set, WITH a mandatory parameter AND relying on ParameterSetName to get the bug to occur, but it is a bug all the same.
and inferring intent which isn't written is potentially dangerous.
Do you consider writing 'foo' -replace 'o' instead of 'foo' -replace 'o', '' dangerous, because it doesn't explicitly specify a replacement operand?
Having _useful, well-documented_ default behavior is a great blessing, in any language, because it reduces noise.
But people should not write functions / cmdlets which define a single parameter set, but it is allowed.
All we know is that the current behavior is _inconsistent_, and there's no official documentation as to how it _should_ work.
_Logically_ there is no reason for your "should" and, more importantly, _not_ enforcing it avoids unnecessary code (having to come up with a name for a parameter set that is logically _implied_ and for which a default name exists).
Omitting a Mandatory property has nothing to do with laziness - it has _different semantics_ that are already meaningfully supported: a group of related parameters belonging to the same parameter set may all be non-mandatory by themselves, yet I may want to know - by querying $PSCmdlet.ParametersetName - if _at least one_ of them was specified. Tagging any of them as Mandatory would _break_ that behavior.
But if I take out the ID parameter, PowerShell will decide I can't get into the function without the name parameter.
What you consider a protection, I consider a bug and a nuisance. The inference that -Name is then mandatory _overall_ and that it should become the _default_ parameter set is logically ill-founded.
It's not clear without naming a second set that I want things to proceed
If you go by the simple rules proposed in #11143, it _is_ clear: Since no default parameter set is designated, argument-less invocation is allowed (as is invocation with only all-parameter-sets arguments) and makes __AllParameterSets the effective parameter set.
While that may not make much sense with _only_ a single, mandatory parameter ($Name) in the then only explicit set (ByName), the example in the initial post shows a meaningful example with _multiple_ parameters.
Of course, if you have just _one_ explicit parameter set whose parameter you want to be mandatory _unconditionally_, there is no good reason to use an explicit parameter set at all: simply replace [Parameter(ParameterSetName="ByName",Mandatory=$true)]$Name with [Parameter(Mandatory=$true)]$Name
and inferring intent which isn't written is potentially dangerous.
Do you consider writing
'foo' -replace 'o'instead of'foo' -replace 'o', ''dangerous, because it doesn't explicitly specify a replacement operand?
Would it delete information from my production database ?
foo -replace doesn't parse (but I would have required replace to have the replacement string; however it is what it is now, and changing at this point would create more of a problem)
You can't run copy -destination \stuff it requires a path. That's inconvenient, it could assume current directory (as it does for destination when path is specified). But since the same thing prevents del [enter] deleting all my files, I'm happy for copy to be consistent and not run without a path.
But people should not write functions / cmdlets which define a single parameter set,
_Logically_ there is no reason for your "should" and, more importantly, _not_ enforcing it avoids unnecessary code (having to come up with a name for a parameter set that is logically _implied_ and for which a default name exists).
The logic is that parametersets divide the the parameters into groups. Dividing into one group makes no sense. It lets people cut a corner, and sometimes that's OK.. But when a parameter in the sole group is mandatory, you can't _not_ select the the group.
Omitting a
Mandatoryproperty has nothing to do with laziness
It may or may not be. In that example the sets have only one member so they are de-facto mandatory, I want them to be mandatory but I don't need to write it (which is something you were asking to be changed in the other issue), not writing mandatory is cutting a corner in _that_ case, but there are other cases...
it has _different semantics_ that are already meaningfully supported: a group of related parameters belonging to the same parameter set may all be non-mandatory by themselves, yet I may want to know - by querying$PSCmdlet.ParametersetName- if _at least one_ of them was specified. Tagging any of them asMandatorywould _break_ that behavior.
If the set can exist without a parameter then that parameter is non-mandatory, I used export-Excel as an example, you can create a table by giving a TableName or TableSyle. That's a set with two optional members.
You've given a clever use of a single set; though rather than writing[Parameter(parameterSetName="a")]for each parameter and referring using if ($pscmdlet.parametersetname -eq a) {...}
it's shorter to use
`$PSBoundParameters.Keys -match "^(Pone|Ptwo)$"
But if I take out the ID parameter, PowerShell will decide I can't get into the function without the name parameter.
What you consider a protection, I consider a bug and a nuisance. The inference that
-Nameis then mandatory _overall_ and that it should become the _default_ parameter set is logically ill-founded.
The behaviour is protective, it's just a question of whether one values the protection. If there bug is allowing a single parameter set which forces PowerShell to make one of two inferences.
It's not clear without naming a second set that I want things to proceed
If you go by the simple rules proposed in #11143, it _is_ clear: Since no default parameter set is designated, argument-less invocation is allowed (as is invocation with only all-parameter-sets arguments) and makes
__AllParameterSetsthe effective parameter set.
You're asking for Del [enter] to delete all files.
Of course, if you have just _one_ explicit parameter set whose parameter you want to be mandatory _unconditionally_, there is no good reason to use an explicit parameter set at all: simply replace
[Parameter(ParameterSetName="ByName",Mandatory=$true)]$Namewith[Parameter(Mandatory=$true)]$Name
You're completely correct, that code should never get written. But in a world where people add bits and remove bits if "orphaned" bits like that do occur. If PowerShell is presented with it, is it certain that I have not ended up with one parameter set by deleting other things and so the parameter needs to be mandatory. If I wanted it _not_ to be mandatory I could remove "mandatory" if I wanted it to be unconditionally mandatory I could remove the set When there is ambiguity it doesn't run the code. And
Would it delete information from my production database ?
It just might, depending on context.
The point is: There is no substitute for (a) understanding the language features you're working with and (b) testing thoroughly before performing potentially destructive actions.
foo -replacedoesn't parse (but I would have required replace to have the replacement string;
I, for one, greatly appreciate the convenience of _not_ having to specify the replacement string, because defaulting to '' is a _sensible, time-saving, concision-promoting default_.
In other words: You can shoot yourself in the foot with _any_ language feature, but that shouldn't get in the way of implementing sensible default behavior.
Dividing into one group makes no sense.
It makes sense if there's an _implied_ other group, which there is is - sometimes: let's make it consistent. If you're not aware of this implied other group, you wouldn't have a reason to create the explicit group to begin with.
If the set can exist without a parameter
it's shorter to use `$PSBoundParameters.Keys -match "^(Pone|Ptwo)$"
That alternative is both obscure and fragile.
Either the author wants the only set they have declared to be default set
Then they shouldn't have declared a n explicit set to begin with.
But in a world where people add bits and remove bits if "orphaned" bits like that do occur.
Again: you need to understand the feature you're working with, and you must test your use of them.
Any feature allows you to use it in ways that don't make sense, and it's infeasible to guard against all possible unintended uses.
Another approach to resolving the current inconsistencies and obscure failures, namely one that favors the explicit expression of intent you prefer, would be the following:
Note: This is a more fundamentally breaking than the proposal in #11143, but perhaps with opt-in features being considered to avoid breaking changes, this is an option:
Enforce the following _at parse time_ to signal that there's a fundamental problem with the function that needs resolving, as opposed to the current _situational_ failures that depend on the specifics of a given invocation. This also has the advantage of being able to provide a specific error messages with clear resolution directions.
If an explicit parameter set is associated with at least one parameter, enforce designating the default parameter set in [CmdletBinding()] to avoid ambiguity and signal explicit intent.
References to otherwise undefined parameter sets in [CmdletBinding()] won't be permitted.
[CmdletBinding(DefaultParameterSetName='')] will signal the explicit intent to allow invocations without parameters altogether, as well as invocations comprising all-parameter-sets parameters only.
$PSCmdlet.DefaultParameterSetName will then reflect '' (the empty string).While we're at: Let's drop the unnecessary Name suffix from the DefaultParameterSetName and ParameterSetName properties.
The point is: There is no substitute for (a) understanding the language features you're working with and (b) testing thoroughly before performing potentially destructive actions.
I don't think anyone would disagree with that point. But if one tests a script to ensure that today it can't run without parameters, and then someone changes the language so that it will run and do damaging things with no parameters, it puts the onus on the script author to go back and re-test every script for every release of the language. They won't do that, and then the people who made the change are blamed for the result.
I wrote "a", "b", "d". "e", "f" | delete-something earlier in the year. and that . after d functions as an operator even with a space after it. So my line read, "a," "b", the 'e' property of the string "d" , "f" and the script (not mine) deleted a, b, * and f* . I can bluster all I want that . should never be "member" if followed by white space but there may be people whose code depends on being able to just that. One can't break their scripts to wrap people who make an error like that one in cotton wool.
foo -replacedoesn't parse (but I would have required replace to have the replacement string;I, for one, greatly appreciate the convenience of _not_ having to specify the replacement string, because defaulting to
''is a _sensible, time-saving, concision-promoting default_.
Its an allowed shortcut it might make it harder for someone who doesn't know that behaviour to read a script (because it is an undocumented feature)
One could make a case that -join or -split without parameter should join assume '' but that means the operator is sometimes unary and sometimes binary which makes it hard to implement.
IF things had be designed to require 2 values (my way and the way the [Regex] object works), there is a sound case to say "allow the shortcut", because no-one would have code out there which worked in a particular way with a single value.
However now that things don't happen that way if I convinced people that it the second operand must error if it has 1 or 3 values that would break existing scripts. Worse, your scripts which relied on that behaviour to remove something would (1) give a non-terminating error, (2) not remove something and (3) blunder on to use the wrong string with who-knows-what consequences. Sometimes the status-quo might not be "best" way but a change causes adverse consequences which outweigh the improvement.. Arguing for a sub-optimum status-quo isn't something many people like doing. But sometimes that's what you have to do to avoid doing harm.
In other words: You can shoot yourself in the foot
Did you know "Shooting oneself in the foot" isn't about poor skills with a gun. Soldiers in WWI used did it to get out of fighting. Depending on who you say "He shot himself in the foot" to, they may think you're describing took one negative to because the feared something else.
Dividing into one group makes no sense.
It makes sense if there's an _implied_ other group, which there is is - sometimes: let's make it consistent. If you're not aware of this implied other group, you wouldn't have a reason to create the explicit group to begin with.
PowerShell creates the extra group instead of throwing an error - and doing so helps test code before it is complete. Expanding the scope of it would change the behaviour of scripts which run on PowerShell up to V6, in a way which is dangerous.
If the set can exist without a parameter
it's shorter to use `$PSBoundParameters.Keys -match "^(Pone|Ptwo)$"That alternative is both obscure and fragile.
Not at all . And I, for one, greatly appreciate the convenience of being able to use a simple regex rather than attach parameter attributes, and be able to see that condition applies to Parameter_one and _two at the point the conditional code executes and not scroll up to look at the attributes.
Either the author wants the only set they have declared to be default set
Then they shouldn't have declared a n explicit set to begin with.
You're right. But after a painful series of edits by authors who didn't talk to each other the script ended up like that. Should a future version of PowerShell work like all past versions. Or should it assume the author wrote this script with this version of PowerShell in mind ? It's a choice between making you declare a second parameter set and trashing other people's systems.
But in a world where people add bits and remove bits if "orphaned" bits like that do occur.
Again: you need to understand the feature you're working with, and you must test your use of them.
When a script was written by someone who understood how things worked at the time lives in production for years, and is supported by people with less knowledge, that because a laudable but unacheivable goal.
Any feature allows you to use it in ways that don't make sense, and it's infeasible to guard against all possible unintended uses.
All possible ? Probably. Del doesn't delete all your files if you run it with no parameters. Why not ? We run del . more than any other version of the command it would be a huge time saver.
Most commands which need an input won't run without the input. You're arguing that scripts and functions which don't run without input today, should start running without input in the future. It's the equivalent of saying next years version of a dangerous piece of machinery should have the safety guards removed, and if people who relied on them lose arms, they should have understood the machine wasn't the same as ones they used before.
You're arguing that scripts and functions which don't run without input today, should start running without input in the future.
No. As stated in my proposal in #11143 and the alternative above, they are _breaking changes_, although in different ways: #11143 would make things more permissive, the alternative would make things stricter.
I can see the appeal of the stricter approach, but in either case the breaking nature must be managed.
Note that from your perspective the status quo has _insufficient_ safeguards, and fixing that would mean that existing scripts could break.
You're arguing that scripts and functions which don't run without input today, should start running without input in the future.
No. As stated in my proposal in #11143
That says
If an advanced function or script doesn't explicitly declare a default parameter set via its [CmdletBinding()] attribute:
- Always allow invocations without arguments
Today with no input this doesn't run. It has no cmdletbinding attribute and the * line says it would always be allowed to run without arguments, deleting all data.
Function BadOne {
param (
[Parameter(ParameterSetName="ByID")]$ID,
[Parameter(ParameterSetName="ByName")]$Name,
$waitForServer
)
if ($ID) {runsql "Delete from Foo where ID = $ID"}
else {runsql "Delete from foo where name like '$name*'"}
if ($waitForServer) {Start-Sleep $waitForServer}
}
Your second bullet point it that says:
Which breaks this script.
Function OKOne {
param (
[Parameter(ParameterSetName="X",Mandatory=$True)]$East,
[Parameter(ParameterSetName="Y")]$North,
$waitForServer
)
if ($PSCmdlet.ParameterSetName -eq "Y") {
"Process North South"
}
}
Both types of script are common enough that I've encountered multiple clients with scripts which fit one or both patterns.
Note that from your perspective the status quo has _insufficient_ safeguards, and fixing that would mean that existing scripts could break.
Well yes, I tried to make the point that it is not about strictness or laxness - as I said, if existing things were made more to my taste (stricter languages - that's how I was taught, I'm stuck with that bias) it could be every bit as bad as making them more to your taste. In my view, very little is broken as things stand: current safeguards are adequate without being excessive; things tend to fail safely, and where shortcuts are denied the extra work is tolerable.
I had an idea. If there were something named differently, let's call it a "LooseSet" , it could do
anything you wanted and not break existing scripts.
Param (
[parameter(looseSet=A,Mandatory)]$x
[parameter(looseSet=A)]$y
$z
)
Would not allow X without Y, but would allow just Z or nothing at all
Param (
[parameter(looseSet=one,)]$a
[parameter(looseSet=one)]$b
[parameter(looseSet=Two,)]$c
[parameter(looseSet=Two)]$d
)
Would allow no parameters and support a check something to see if you had been passed a or b, or passed c or d without demanding one has a mandatory parameter, or [cmdletbinding] adds a set.
This could sit in parallel with what exists, breaks nothing, and any explanation would say why they were different from parameter sets and what steps need to be taken to ensure the body isn't dangerous.
What would break is already spelled out in #11143. I understand that you think that is dangerous.
Reflecting on that is what made me propose the alternative, which I am now leaning toward.
It would give you the strictness you desire while eliminating inconsistencies and providing clear failure cases with specific error messages.
But, of course, it is a breaking change that script authors would have to _opt into_ or - God forbid / allow - the right approach for a future PowerShell version not saddled with technical debt.
Personally, I'm not interested in fixing the current behavior _in a backward-compatible fashion_ (except for the obvious bug that prompted this issue), introducing a new property increases complexity and doesn't eliminate the existing inconsistencies and obscure failures.
That's a misuse of "Technical debt". Things which are imperfect are not automatically technical debt; things which have escalating cost (like interest), can't be avoided forever (like repayment) but are ducked to meet a deadline generally are.
Personally, I'm not interested in fixing the current behavior _in a backward-compatible fashion_
Well that's the end of that discussion then. Re-read of what Bruce said on that other thread. He's smarter than both of us put together. And I'll leave this here. Have a good life.
https://github.com/PowerShell/PowerShell/issues/6745#issuecomment-483926648
That's a misuse of "Technical debt"
Good point, thank you for the correction. I've always used _technical debt_ loosely (but incorrectly) to mean "accumulated broken behavior that can't be fixed without breaking backward-compatibility", but I do hope it's clear from the _content_ of #6745 that the latter is what I actually _meant_.
Well that's the end of that discussion then
It's the end of my personal involvement in the specific debate of how to improve parameter-set handling _without breaking backward compatibility_, because:
(a) you can _work around_ the existing limitations by simply designating a made-up parameter set in the [CmdletBinding()] attribute - no need for introducing additional properties such as looseSet
(b) the _fundamental problems_ with the current behavior _cannot be fixed_ if maintaining backward compatibility is the premise.
Therefore, my personal interest is limited to _exploring how to solve the problem fundamentally_, with two possible outcomes:
Ideally, a fundamental solution can be implemented and users can at least _opt in_ or, perhaps, some day, there will be a "vNext" in which a fundamental solution can be the _default_.
At the very least, it's important to have clarity on how things _should_ work, which helps guide future design decisions.
Re-read of what Bruce said on that other thread.
You're linking to a comment by @JayKul, which refers to a (perceived) _fiat_ decision by the powers that be. Contrast this with this statement, for instance.
He's smarter than both of us put together.
The merit of someone's argument is unrelated to your perception of their level of intelligence.
Have a good life.
Please refrain from making such comments. They add nothing to the discussion and serve only to antagonize.
@iSazonov, can you please label this issue as a bug?
The surrounding discussion aside, the original problem described in the initial post is a clearly an easily verifiable bug in the context of the current behavior.
If you want a simpler repro:
# Just press Enter when prompted; passing a -Foo argument makes the problem go away.
& { [CmdletBinding()] param([Parameter(Mandatory, ParameterSetName='ByFoo')] $Foo) $PSCmdlet.ParameterSetName } | Should -Be ByFoo
Have a good life.
Please remain from making such comments. They add nothing to the discussion and serve only to antagonize.
You are too willing to be be antagonized without realizing that you antogoize others. For clarity, that was intended to mean "I will discuss maters with with you no further; but I bear you no ill will" . Since it is obvious that you're not especially concerned if a change renders the new product unadoptable, don't accept that (e.g) Bruce Payette is more likely to know what's good and bad than you or I, and seem to want to argue every point and the language used, you appear to want to test the second half, but the first half stands. I should, perhaps have known better than to expect you to take a wish of a good future in the spirit it was meant. I won't reply further.
@jhoneill I wonder why you throw an exception on good discussion? :-) Please be patient and follow CoC. @mklement0 too - please ignore personal comments - it is moderator's headache :-)
@jhoneill As for your concern. Sometimes we change the mind to the opposite, even in global things. For example, for PowerShell 6 a main rule was "To have only ported cmdlets", all window-only cmdlets was removed (with one exception), But for PowerShell 7 the rule was changed to "To have easy adoption for Windows users". As result some Windows-only cmdlet was added back. This happened because Windows users do not want to use limited PowerShell version and stay on Windows PowerShell. We get this understanding only after collect statistics for 2 years.
For the discussion we want to collect all points, concerns and ideas so that get more full understanding the problem. Perhaps we reject this today but can accept 2-3 years later. Or forget at all :-) Be patient please.
@iSazonov My patience is finite, so is my time, and engaging with MK has proved to be excessively demanding of both.
PowerShell 6 has not displaced Windows PowerShell because too many things do not work. That's being addressed in 7: if people are persuaded that what they have worked for 10+ years moves to 7 safely and reliably we get progress; otherwise I'll be working on 5.1 until I retire. I'll point you at Bruce's comment
even relatively small changes on a core path can seriously hinder adoption. Look at Python 3. It took 10 years to really catch on.
If someone wants to say they know better than Bruce, and proclaim
I'm not interested in fixing the current behavior in a backward-compatible fashion
then it's better for me, and for the general tone if I leave them to it.
@jhoneill:
engaging with MK has proved to be excessively demanding of both.
Please refrain from making such comments. They add nothing to the discussion and serve only to antagonize.
If someone wants to say they know better than Bruce
Deferring to whom you perceive to be an authority is your personal choice, but doing so has no place in a rational debate.
@iSazonov:
please ignore personal comments - it is moderator's headache :-)
I understand, and I will keep that in mind - I wasn't even aware that moderation of such matters was being performed. (Does what is described here happen routinely?)
On what - I promise - is a one-time explanation:
While _ignoring_ personal comments is certainly an option, my personal preference is to:
(a) hold people accountable for their actions,
_and_ (b) seek to instill an understanding as to _why_ ad hominem comments are uncalled for.
I agree that, in the face of the apparent futility of (b) here, I should have stopped much earlier (though, except for the original plea, all comments regarding the unwarranted personal dimension were addressed in the context of comments primarily focused on discussing the issue at hand).
engaging with MK has proved to be excessively demanding of both.
Please refrain from making such comments. They add nothing to the discussion and serve only to antagonize.
It is interesting that you have used _It adds/they add nothing to the discussion and serve only to antagonize._ three times as if it is a common response: the bullet points sound like someone who has a prepared strategy when they choose to be antagonized. Others might wonder _why_ they attract that kind of comment.
How I see the the consumption of my time, and how I feel the strain on my patience is as a valid a thing for me to express as any thought of yours. To categorize that view as an ad hominem attack suggests you might be well advised to avoid Latin tags - I had to study Latin so even its correct use doesn't impress me; when people use it for "he said something I don't like" ... describing the effect would, to coin a phrase, serve only to antagonize.
My view is that I have wasted too much time responding to postings which only the work of Dunning & Kruger can explain. Having recognized that, I won't you goad me into wasting any more.
Most helpful comment
@jhoneill I wonder why you throw an exception on good discussion? :-) Please be patient and follow CoC. @mklement0 too - please ignore personal comments - it is moderator's headache :-)
@jhoneill As for your concern. Sometimes we change the mind to the opposite, even in global things. For example, for PowerShell 6 a main rule was "To have only ported cmdlets", all window-only cmdlets was removed (with one exception), But for PowerShell 7 the rule was changed to "To have easy adoption for Windows users". As result some Windows-only cmdlet was added back. This happened because Windows users do not want to use limited PowerShell version and stay on Windows PowerShell. We get this understanding only after collect statistics for 2 years.
For the discussion we want to collect all points, concerns and ideas so that get more full understanding the problem. Perhaps we reject this today but can accept 2-3 years later. Or forget at all :-) Be patient please.