Reserving keywords

Reserving keywords

  • Comments 35

A couple months ago we asked our MVPs how they felt about reserving keywords in V2.  We received some excellent but mixed feedback, so we’d like to open the discussion up a bit wider.

There are keywords we hope to use in a future version of PowerShell, but won’t be implemented in V2.  “class”, “using”, and “new” are excellent candidates for additions to PowerShell, but we haven’t decided on the exact list yet.

Because V1 did not reserve these keywords, reserving them now would be a breaking change.  For example, some people like to add an alias like:

New-Alias -Name new -Value New-Object

If we reserved “new”, scripts using this alias would be broken.  Similarly, in Bruce Payette’s book “Windows PowerShell In Action”, he describes a way to implement a keyword like “class”, though he uses “CustomClass” instead of “class”

The biggest benefit of reserving in V2 is that we’ll break fewer scripts.

The cons to reserving in V2 include:

  • Breaking scripts needlessly.  We’ve tried to make V2 as backwards compatible as possible.  The breaking changes that we do have implement real functionality (for example, try/catch are new keywords, breaking scripts that used try or catch as a function.)
  • Some keywords can be implemented in script, at least well enough to look like a real keyword.

Here’s an example of how you might implement the C# using statement in a V2 PowerShell script:

function using             
{             
    param($obj, [scriptblock]$sb)             
            
    try {             
        & $sb             
    } finally {             
        if ($obj -is [IDisposable]) {             
            $obj.Dispose()             
        }             
    }             
}            

And here is how you can use that function – it looks very similar to how a using keyword might look:

using ($stream = new-object System.IO.StreamReader $PSHOME\types.ps1xml) {             
    foreach ($_ in 1..5) { $stream.ReadLine() }             
}

Feel free to give us your feedback in the comments – are you using any common language keywords as a function name in your scripts?  If you do, how bothersome would it be if you had to change your scripts?

- Jason Shirk [MSFT]

Leave a Comment
  • Please add 6 and 3 and type the answer here:
  • Post
  • Don't reserve a keyword if you think you <b>might</b> need it; do reserve a keyword if you know will <b>will</b> need it.

    I'd probably draw the line at about an 80% confidence level.

  • I am in favor of Reserving Keywords in V2.  It appeals to me as the "correct" solution to the problem. To not do so is to design more risk permutations/complexities into future product decisions.

  • If you do not use “class”, “using”, and “new” and etc. as keywords in V2, then simply do not reserve them. Do not break existing code (not mine though). Why? Do not waste time and do not make simple difficult (and new bugs). Better make yet another 1 thing 1% better.

    You think it is possible that some words potentially can be keywords in the coming future. I do not see any problem, sorry. Tell about this in documentation. Use large bold font and exclamations signs, if you like. From now on it is me who is responsible for consequences of using these words, not you. It is me who should read the manual and make right decisions.

  • In designing C#, we've found the use of "conditional keywords" -- keywords that are only reserved in certain contexts -- to be extremely useful.  If this approach can be sued for PowerShell then it would eliminate (or at least reduce) the need to reserve keywords for future versions.

    Here's what the C# spec says about them:

    <spec>

    In some places in the grammar, specific identifiers have special meaning, but are not keywords. For example, within a property declaration, the “get” and “set” identifiers have special meaning (§10.7.2). An identifier other than get or set is never permitted in these locations, so this use does not conflict with a use of these words as identifiers.

    </spec>

    This approach has enabled us to add new features to the language while preserving backward compatibility.

    This approach might also work for PowerShell.  The C# designers would be happy to chat with you about the approach and its potential suitability for PowerShell.

    --Scott

  • If the decision is one of "when" and not "if" then I would say do this sooner since the impact could only get worse with time.

    At the same time you should consider a way to allow users to escape these keywords in their existing scripts so that refactoring is as simple as is possible.  As an example, T-SQL lets you use keywords as long as you enclose them within square brackets.

  • Jason, you need a long-term reserved-keyword story. Here is what SQL Server does, maybe you can get some inspiration from that. When version N is shipped, it has an "N-1 compatibility" setting. In your case it might be a command-line flag or an environment variable setting. In that mode, new keywords for release N are not recognized. So, if you want your legacy scripts to work, you set this. When you are developing new scripts, you don't. There are wrinkles in this scheme, but for most users it works well. If you have a story like that, pre-reserving keywords in advance is not needed.

  • Just reserve it now and get it over with.  Of course thats easy for me to say, I don't think any of my scripts are using those keywords

  • You're going about this all wrong.  You need just one keyword: PWVersion

    This looks like the SQL concept described above.

    You need to versionize the product so the sript inputs are recognized as the level of powershell features upon which it was built for.

    You should see already that you will always have this problem in more ways than just key words.

    The basic design goes like this:

    Non-versioned scripts are interpreted as v1

    Everything else needs the PWVersion keyword at the top.

    From there it is no longer your job to tell the world how much money they pour into maintaining their legacy solutions. If the old scripts work fine in v1, they do nothing. If v2 has features they must have, they can migrate away from the incompatible keywords to conform to the new.

    Not only does this solve the keywork question, but now the incompatible work-arounds that people write before you provide the solutions in vNext won't be broken either.  PowerShell can pass the legacy logic in one's script to the legacy interpretation while giving everyone else the new interpretation.

    Heck, if you really want to impress the customer, let them context-switch in midstream.  They can wrap a complicated legacy solution that uses some custom tool (and hence too expensive to replace) in a push/pop syntax like this:

    PWVersion=2

    <newest coolest logic>

    PWVersion=1

    <legacy stuff using custom tool>

    PWVersion=2

    <back to newest logic>

  • Holy crap that's a lot of comments for this blog... Anyhow here's a radical idea.

    How about you use the major 2.0 release as an opportunity to get away from all the "seemed like a good idea at the time" things of v1.

    For example, continue to support the .ps1, .psm1, etc extensions but discourage their use and instead push for .ps and .psm with #requires directives. That way, if you encounter a .ps1 file, treat those keywords the way you did in v1. If you encounter a .ps file or if it's entered interactively, treat it as a reserved keyword.

  • As a developer who worked since his Tandy TRS 80 (Basic Level I - 4K) days with reserved keywords, I wouldn't mind bcause I really never "try to override" these keywords!

    But I understand that it is really tempting to use "new" eg. as an alias :-)

    Anyway: You should reserve keywords (even those, expected for future use)!

    Introducing a compatibilty mode "Set-CompatibilityMode = V[1..42]:-) might be a solution but you will suffer from that ... even in V42 :-)

    I like Josh's idea that breaks with the "*.ps1" Scripts and allows for the all new "*.ps" extension to be associated with Powershell V2 ( and above ) versions that do reserve keywords!

    good luck for taking the "MakeEverybodyHappyDecision" *sss*

    kind regards, Klaus

  • There have been few comments about how SQL Server handles future deprecated features/keywords, so I won't describe my observations on SQL Server deprecated features in detail. We talking about a very specific deprecation need, reserving a keyword which will not be implemented in V2.If a language feature will be deprecated in a future release but it is not implemented, the SQL Server docs simply state this in their release notes and documentation. They do not warn, prevent, or requiring escaping for future keywords. I'm fine with the SQL Server approach. The other thing SQL does is provide an upgrade advisor utility to scan your SQL code and report code which should be changed. A full blown utility like what SQL Server provides with GUI and XML export capabilities may be overkill, but a nice script to identify potential changes which need to be made to our V1 and V2 code would be handy.

  • My vote:

    1. reserve them now if you are 80% sure they will be implented in V3

    2. If #1 is not acceptable, wait to reserver it when the functionality is there and have

    #requires -version 1 or -version 2 remove the reserved keyword and the related function.

  • I'm against reserving at least some of the keywords.  There are several good examples of creating a using command, for example, that can be done in PowerShell v1.  If you're reserving keywords in PowerShell v2 then you're breaking the ability to get the syntax/experience that users can get today in v1, and when is v3 coming out?  Let the community provide creative solutions that extend PowerShell with keyword-esque functionality when you guys are out of time to do so.

  • "Breaking changes" now with V2 is saying to your very best customers: "Whatever you do today, we might break tomorrow." Breaking changes are what prevents people from upgrading. If you can't design enhancements that don't break existing deployments, you should probably just retire and let younger people take over. Breaking changes are what prevented VISTA from being successful. I suggest you avoid that path.

  • Why not having separate compatibility checker as part of Application Compatibility Toolkit?

    Consider scenario:

    - we are releasing new PoshV2 with new cmdlets

    - Give users ACT PS. This will be installed on machine(s) with Posh V1

    - whenever cmdlet\function that has same name as defined in ACT PS, it will either break (interactive), display warning or write event log entry

    Simple and fits into MS strategy.

Page 2 of 3 (35 items) 123