Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optional members in cell paths: Attempt 2 #8379

Merged
merged 15 commits into from
Mar 16, 2023

Conversation

rgwood
Copy link
Contributor

@rgwood rgwood commented Mar 10, 2023

This is a follow up from #7540. Please provide feedback if you have the time!

Summary

This PR lets you use ? to indicate that a member in a cell path is optional and Nushell should return null if that member cannot be accessed.

Unlike the previous PR, ? is now a postfix modifier for cell path members. A cell path of .foo?.bar means that foo is optional and bar is not.

? does not suppress all errors; it is intended to help in situations where data has "holes", i.e. the data types are correct but something is missing. Type mismatches (like trying to do a string path access on a date) will still fail.

Record Examples

{ foo: 123 }.foo # returns 123

{ foo: 123 }.bar # errors
{ foo: 123 }.bar? # returns null

{ foo: 123 } | get bar # errors
{ foo: 123 } | get bar? # returns null

{ foo: 123 }.bar.baz # errors
{ foo: 123 }.bar?.baz # errors because `baz` is not present on the result from `bar?`
{ foo: 123 }.bar.baz? # errors
{ foo: 123 }.bar?.baz? # returns null

List Examples

〉[{foo: 1} {foo: 2} {}].foo
Error: nu::shell::column_not_found

  × Cannot find column
   ╭─[entry #30:1:1]
 1 │ [{foo: 1} {foo: 2} {}].foo
   ·                    ─┬  ─┬─
   ·                     │   ╰── cannot find column 'foo'
   ·                     ╰── value originates here
   ╰────
〉[{foo: 1} {foo: 2} {}].foo?
╭───┬───╮
│ 0 │ 1 │
│ 1 │ 2 │
│ 2 │   │
╰───┴───╯
〉[{foo: 1} {foo: 2} {}].foo?.2 | describe
nothing

〉[a b c].4? | describe
nothing

〉[{foo: 1} {foo: 2} {}] | where foo? == 1
╭───┬─────╮
│ # │ foo │
├───┼─────┤
│ 0 │   1 │
╰───┴─────╯

Breaking changes

  1. Column names with ? in them now need to be quoted.
  2. The -i/--ignore-errors flag has been removed from get and select
    1. After this PR, most get error handling can be done with ? and/or try/catch.
  3. Cell path accesses like this no longer work without a ?:
〉[{a:1 b:2} {a:3}].b.0
2

We had some clever code that was able to recognize that since we only want row 0, it's OK if other rows are missing column b. I removed that because it's tricky to maintain, and now that query needs to be written like:

〉[{a:1 b:2} {a:3}].b?.0
2

I think the regression is acceptable for now. I plan to do more work in the future to enable streaming of cell path accesses, and when that happens I'll be able to make .b.0 work again.

@rgwood rgwood marked this pull request as draft March 10, 2023 02:15
@codecov
Copy link

codecov bot commented Mar 10, 2023

Codecov Report

Merging #8379 (8c7f501) into main (aa876ce) will decrease coverage by 0.03%.
The diff coverage is 69.91%.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #8379      +/-   ##
==========================================
- Coverage   68.06%   68.04%   -0.03%     
==========================================
  Files         621      621              
  Lines       99885    99943      +58     
==========================================
+ Hits        67988    68002      +14     
- Misses      31897    31941      +44     
Impacted Files Coverage Δ
crates/nu-command/src/debug/inspect_table.rs 0.00% <0.00%> (ø)
crates/nu-explore/src/nu_common/table.rs 0.00% <0.00%> (ø)
crates/nu-explore/src/nu_common/value.rs 0.00% <0.00%> (ø)
crates/nu-parser/src/parse_keywords.rs 68.51% <0.00%> (-0.05%) ⬇️
crates/nu-command/src/filters/drop/column.rs 80.00% <33.33%> (+2.15%) ⬆️
crates/nu-protocol/src/ast/cell_path.rs 53.19% <35.71%> (-23.00%) ⬇️
crates/nu-protocol/src/value/from_value.rs 34.97% <50.00%> (+0.07%) ⬆️
crates/nu-protocol/src/value/mod.rs 56.29% <59.64%> (-0.28%) ⬇️
crates/nu-cli/src/repl.rs 24.35% <88.57%> (ø)
crates/nu-parser/src/parser.rs 83.26% <91.52%> (+0.05%) ⬆️
... and 15 more

... and 1 file with indirect coverage changes

@fdncred
Copy link
Collaborator

fdncred commented Mar 10, 2023

Just to be clear, the reason you're suggesting we remove --ignore-errors/-i is because:

These produce identical results

{ foo: 123 } | get bar?
{ foo: 123 } | get -i bar

and these produce identical results

[{a:1 b:2} {a:3}] | select b?
[{a:1 b:2} {a:3}] | select -i b

If that is correct, then I'd propose dropping the -i in this PR, and maybe have a deprecate message on -i?

@rgwood
Copy link
Contributor Author

rgwood commented Mar 10, 2023

Right, ? can replace -i in most situations. For others, try/catch can be used. I’ll remove -i

@rgwood
Copy link
Contributor Author

rgwood commented Mar 10, 2023

On second thought... removing -i is going to be hard, it's used in default_env.nu 😞

let home = ($env | get -i (if $nu.os-info.name == "windows" { "USERPROFILE" } else { "HOME" }) | into string)

Removing the flag will break people's env.nu. Maybe we should leave it around for now.

@rgwood
Copy link
Contributor Author

rgwood commented Mar 10, 2023

Oh! I just noticed that the get -i was added to default_env.nu after the 0.76 release: #8173

If I remove it before the 0.77 release, that will make future deprecation of -i much easier. Will do that in another PR.

sholderbach pushed a commit that referenced this pull request Mar 10, 2023
This is a follow-up from #8173,
which was merged shortly after the 0.76 release. That PR changed
`default_env.nu` so that the user's home folder is displayed as `~` in
the left prompt. It did so using `get -i`.

This PR just rewrites the Nu code from
#8173 to use `try`/`catch`
instead of `-i`, which will make it easier to remove the `-i` flags from
`get` and `select` eventually (see
#8379).

I would like to merge this before the 0.77 release, so we don't end up
with lots of `env.nu` files using `get -i` out in the wild.
@rgwood
Copy link
Contributor Author

rgwood commented Mar 10, 2023

I've removed the -i flag from get and select. Hopefully that won't make too many people angry.

@webbedspace
Copy link
Contributor

Thanks for revisiting this feature!

@rgwood rgwood marked this pull request as ready for review March 14, 2023 16:39
@rgwood
Copy link
Contributor Author

rgwood commented Mar 16, 2023

I asked in Discord and several people voted to merge this. Let's give it a try!

@rgwood rgwood merged commit 21b84a6 into nushell:main Mar 16, 2023
@rgwood rgwood added the pr:breaking-change This PR implies a change affecting users and has to be noted in the release notes label Mar 16, 2023
rgwood added a commit that referenced this pull request Mar 16, 2023
#8379 removed the `-i` flag from
`get` and `select` because the new `?` functionality covers most of the
same use cases. However, #8480
made me realize that `-i` is still useful when dealing with cell paths
in variables.

This PR re-adds the `-i` flag to `get` and `select`. It works by just
marking every member in the cell path as optional, which will behave
_slightly_ differently than `-i` used to (previously it would suppress
any errors, even type errors) but IMO that's OK.
sophiajt pushed a commit that referenced this pull request Mar 22, 2023
This is a follow-up to #8379 and
#8502.

This PR makes it so that the new `?` syntax for marking a path member as
optional short-circuits, as voted on in the
[8502](#8502) poll.
Previously, `{ foo: 123 }.bar?.baz` would raise an error:

```
> { foo: 123 }.bar?.baz
  × Data cannot be accessed with a cell path
   ╭─[entry #15:1:1]
 1 │ { foo: 123 }.bar?.baz
   ·                   ─┬─
   ·                    ╰── nothing doesn't support cell paths
   ╰────
   ```

Here's what was happening:

1. The `bar?` path member access returns `nothing` because there is no field named `bar` on the record
2. The `baz` path member access fails when trying to access a `baz` field on that `nothing` value

After this change, `{ foo: 123 }.bar?.baz` returns `nothing`; the failed `bar?` access immediately returns `nothing` and the `baz` access never runs.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pr:breaking-change This PR implies a change affecting users and has to be noted in the release notes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants