Title: Do not require { ... } around variable names for null-conditional member access · Issue #11379 · PowerShell/PowerShell · GitHub
Open Graph Title: Do not require { ... } around variable names for null-conditional member access · Issue #11379 · PowerShell/PowerShell
X Title: Do not require { ... } around variable names for null-conditional member access · Issue #11379 · PowerShell/PowerShell
Description: Follow-up from #3240. Null-conditional member access (?.) was implemented and will be available as an experimental feature in 7.0 However, in the interest of backward compatibility the implementation currently requires that the variable ...
Open Graph Description: Follow-up from #3240. Null-conditional member access (?.) was implemented and will be available as an experimental feature in 7.0 However, in the interest of backward compatibility the implementati...
X Description: Follow-up from #3240. Null-conditional member access (?.) was implemented and will be available as an experimental feature in 7.0 However, in the interest of backward compatibility the implementati...
Opengraph URL: https://github.com/PowerShell/PowerShell/issues/11379
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"Do not require { ... } around variable names for null-conditional member access","articleBody":"Follow-up from #3240.\r\n\r\nNull-conditional member access (`?.`) was implemented and will be available as an _experimental_ feature in 7.0\r\n\r\nHowever, in the interest of backward compatibility **the implementation currently requires that the variable name be enclosed in `{...}`**, because `?` is technically a legal character in a variable name whose use surprisingly _doesn't_ require `{...}`.\r\n\r\nThat is, if you want to ignore an attempt to call`$obj.Method()` if `$obj` is `$null` (or undefined), you would expect the following, analogous to C#:\r\n\r\n```powershell\r\n# Does NOT work as intended.\r\n# 'obj?' as a whole is interpreted as the variable name.\r\n$obj?.Method()\r\n```\r\n\r\nInstead, you must currently use:\r\n\r\n```powershell\r\n# !! Must enclose 'obj' in {...} to signal that '?' is a syntactic element as part of '?.'\r\n${obj}?.Method()\r\n```\r\n\r\n_Update_: Null-coalescing - `$var??='default` and `$a??$b` - and the ternary operator - `$var?1:0` - are similarly affected (though there the use of whitespace before the `?` resolves the issue).\r\n\r\nThis requirement is (a) unexpected and (b) cumbersome:\r\n\r\n* New users will not expect the need for `{...}` and won't necessarily know that _it_ is what is required when the following fails (possibly _undetected_, unless `Set-StrictMode -Version 2` or higher is in effect): `$o = [pscustomobject] @{ one = 1 }; $o?.one`\r\n\r\n* Even once users _do_ know about the need for `{...}`:\r\n * They will forget to use it on occasion, because of the counter-intuitive need for it.\r\n * When they do remember, this seemingly artificial requirement will be an ongoing source of frustration, especially since `{...}` is hard to type.\r\n\r\n**Use of `{...}` shouldn't be necessary, and while not requiring it amounts to a _breaking_ change, it arguably falls into [bucket 3: Unlikely Grey Area](https://github.com/PowerShell/PowerShell/blob/master/docs/dev-process/breaking-change-contract.md#bucket-3-unlikely-grey-area).**\r\n\r\n---\r\n\r\n### Why this change should be considered acceptable:\r\n\r\nNote: @rjmholt discusses why changing PowerShell's syntax is highly problematic _in general_ in [this comment](https://github.com/PowerShell/PowerShell/issues/3240#issuecomment-565745004), but for the reasons presented below I think it is worth making an exception here.\r\n\r\n`?.` is a _new_ syntactic feature; by definition scripts that use it _cannot_ (meaningfully) run on older versions - unless you specifically add conditionals that provide legacy-version-compatible code paths, but that seems hardly worth it - you would then just stick with the legacy features.\r\n\r\nYes, the interpretation of `$var?.foo` in old scripts that used `$var?` as a variable name would break, but:\r\n\r\n* `?` should never have been allowed as part of an identifier _without enclosing it in `{...}`_.\r\n\r\n* Since being able to do so is unexpected and probably even _unknown_ to many, such variable names are exceedingly rare in the wild, speaking from personal experience, but [@mburszley's analysis provides more tangible evidence](https://github.com/PowerShell/PowerShell/issues/3240#issuecomment-526179551).\r\n\r\n * Even Ruby only allows `?` (and `!`) at the _end_ of identifiers, and there only of _method_ identifiers, and I suspect that most Ruby users are aware that they should _not_ assume that other languages support the same thing.\r\n\r\nSo, pragmatically speaking:\r\n\r\n* The vast majority of existing code will not be affected - a token such as `$var?.foo` will simply not be encountered.\r\n\r\n* If you write `$var?.foo` with the new semantics, then yes, running that on older versions could result in different behavior (rather than breaking in an obvious manner), depending on what strict mode is in effect - but _you should always enforce the minimum version required to run your code as intended anyway_ (`#requires -Version`, module-manifest keys).\r\n\r\nAll in all, to me this a clear case of a bucket 3 change: a technically breaking change that breaks very little existing code while offering real benefits (or, conversely, avoiding perennial headaches due to unexpected behavior).\r\n\r\n\r\n\r\n\r\n\r\n","author":{"url":"https://github.com/mklement0","@type":"Person","name":"mklement0"},"datePublished":"2019-12-17T16:25:21.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":53},"url":"https://github.com/11379/PowerShell/issues/11379"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:75bc28fd-0a14-cd9b-21f9-e603cbd6f8fc |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | C386:22943D:F71EA:15B208:6A5A40A7 |
| html-safe-nonce | 2d968e82dbddaa2689f6d1ddd48eeada8e9729cd2acc1a9d3ebd92c1e7a10344 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJDMzg2OjIyOTQzRDpGNzFFQToxNUIyMDg6NkE1QTQwQTciLCJ2aXNpdG9yX2lkIjoiMjQzMjMwMTkwMjA1MjYwNjExOSIsInJlZ2lvbl9lZGdlIjoiaWFkIiwicmVnaW9uX3JlbmRlciI6ImlhZCJ9 |
| visitor-hmac | 820771ddd5e5dd41152dbc1e65b346b911d815c96e66b3f43d9731b3f4d8ffc8 |
| hovercard-subject-tag | issue:539174894 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/PowerShell/PowerShell/11379/issue_layout |
| twitter:image | https://opengraph.githubassets.com/a927a238c0586fdc58d8c3500b97c3dcdd06ae13b80af53fa95a2ee6cbd3c3fe/PowerShell/PowerShell/issues/11379 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/a927a238c0586fdc58d8c3500b97c3dcdd06ae13b80af53fa95a2ee6cbd3c3fe/PowerShell/PowerShell/issues/11379 |
| og:image:alt | Follow-up from #3240. Null-conditional member access (?.) was implemented and will be available as an experimental feature in 7.0 However, in the interest of backward compatibility the implementati... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | mklement0 |
| hostname | github.com |
| expected-hostname | github.com |
| None | 19c67ad7579d2401ff06e88a32ef45460fbb40fab3191c7f7582d5e166f326fc |
| turbo-cache-control | no-preview |
| go-import | github.com/PowerShell/PowerShell git https://github.com/PowerShell/PowerShell.git |
| octolytics-dimension-user_id | 11524380 |
| octolytics-dimension-user_login | PowerShell |
| octolytics-dimension-repository_id | 49609581 |
| octolytics-dimension-repository_nwo | PowerShell/PowerShell |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 49609581 |
| octolytics-dimension-repository_network_root_nwo | PowerShell/PowerShell |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | e618485bff22dab2ef1ffb4e34e4e6626688df69 |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width