Skip to content

Make get hole errors and cell path hole errors identical (improvement on #7002)#7647

Merged
rgwood merged 5 commits intonushell:mainfrom
webbedspace:hole-error
Jan 2, 2023
Merged

Make get hole errors and cell path hole errors identical (improvement on #7002)#7647
rgwood merged 5 commits intonushell:mainfrom
webbedspace:hole-error

Conversation

@webbedspace
Copy link
Copy Markdown
Contributor

@webbedspace webbedspace commented Jan 1, 2023

Description

This closes #7498, as well as fixes an issue reported in #7002 (comment)

BEFORE:

〉[{foo: 'bar'} {}] | get foo
Error: nu::shell::column_not_found (link)

  × Cannot find column
   ╭─[entry #5:1:1]
 1 │ [{foo: 'bar'} {}] | get foo
   · ────────┬────────   ─┬─
   ·         │            ╰── value originates here
   ·         ╰── cannot find column 'Empty cell'
   ╰────

〉[{foo: 'bar'} {}].foo
╭───┬─────╮
│ 0 │ bar │
│ 1 │     │
╰───┴─────╯

AFTER:

〉[{foo: 'bar'} {}] | get foo
Error: nu::shell::column_not_found (link)

  × Cannot find column
   ╭─[entry #1:1:1]
 1 │ [{foo: 'bar'} {}] | get foo
   ·               ─┬        ─┬─
   ·                │         ╰── cannot find column 'foo'
   ·                ╰── value originates here
   ╰────

〉[{foo: 'bar'} {}].foo
Error: nu::shell::column_not_found (link)

  × Cannot find column
   ╭─[entry #3:1:1]
 1 │ [{foo: 'bar'} {}].foo
   ·               ─┬  ─┬─
   ·                │   ╰── cannot find column 'foo'
   ·                ╰── value originates here       
   ╰────

EDIT: This also changes the semantics of get/select -i somewhat. I've decided to leave it like this because it works more intuitively with default and compact.
BEFORE:

〉[{a:1} {b:2} {a:3}] | select -i foo | to nuon
null

AFTER:

〉[{a:1} {b:2} {a:3}] | select -i foo | to nuon
[[foo]; [null], [null], [null]]

User-Facing Changes

See above. EDIT: the issue with holes in cases like [{foo: 'bar'} {}].foo.0 versus [{foo: 'bar'} {}].0.foo has been resolved.

Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

  • cargo fmt --all -- --check to check standard code formatting (cargo fmt --all applies these changes)
  • cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect to check that you're using the standard code style
  • cargo test --workspace to check that all tests pass

After Submitting

If your PR had any user-facing changes, update the documentation after the PR is merged, if necessary. This will help us keep the docs up to date.

@rgwood
Copy link
Copy Markdown
Contributor

rgwood commented Jan 1, 2023

Nice!

I think this is a step in the right direction. We may also need to adjust the behaviour of get -i (not saying it has to happen in this PR):

〉[{ foo: "bar"} {}] | get -i foo
〉[{ foo: "bar"} {}] | get -i foo | to nuon
null
〉[{ foo: "bar"} {}] | select -i foo
╭───┬─────╮
│ # │ foo │
├───┼─────┤
│ 0 │ bar │
│ 1 │     │
╰───┴─────╯

IMO the behaviour of get -i where it returns a single null value is not very useful; it should behave like select and replace missing values with nulls. That's how I envision cell paths working when users opt into lenient error checking (with -i or some future ? syntax); curious whether other people agree.

@webbedspace
Copy link
Copy Markdown
Contributor Author

webbedspace commented Jan 1, 2023

I came up with an ingenious way of making [{foo: 'bar'} {}].foo.0 still work, even though the .foo access should produce an error at that point in cell path evaluation. See here for details. This method has the side-effect that stuff like [{foo: 'bar'} {}].foo | reject 1 also works without erroring.

@rgwood
Copy link
Copy Markdown
Contributor

rgwood commented Jan 1, 2023

Hmm, I think that change is generally a good idea but get -i seems more broken now:

〉[{ foo: "bar"} {}] | get -i foo
Error: nu::shell::column_not_found (link)

  × Cannot find column
   ╭─[entry #7:1:1]
 1 │ [{ foo: "bar"} {}] | get -i foo
   ·                ─┬           ─┬─
   ·                 │            ╰── cannot find column 'foo'
   ·                 ╰── value originates here
   ╰────

@webbedspace
Copy link
Copy Markdown
Contributor Author

OK, I fixed it. However, I just noticed I've inadvertently changed the semantics of -i somewhat.

BEFORE:

〉[{a:1} {b:2} {a:3}] | select -i a | to nuon
[[a]; [1], [null], [3]]
〉[{a:1} {b:2} {a:3}] | select -i foo | to nuon
null

AFTER:

〉[{a:1} {b:2} {a:3}] | select -i a | to nuon
[[a]; [1], [null], [3]]
〉[{a:1} {b:2} {a:3}] | select -i foo | to nuon
[[foo]; [null], [null], [null]]

I've decided that the latter way is better because it can interact with default more intuitively:

〉[{a:1} {b:2} {a:3}] | select -i a | default 0 a
[[a]; [1], [0], [3]]
〉[{a:1} {b:2} {a:3}] | select -i foo | default 0 foo
[[foo]; [0], [0], [0]]

open los_tres_amigos.json
| get amigos
| default rusty_luck 1
| default 1 rusty_luck
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By the way… am I losing my mind, or was this test always wrong until now? default rusty_luck 1 is not the correct order of default arguments, and never was, right?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suspect the test was always wrong.

FWIW I also assumed that the order was default <column name> <default value> instead of when I first encountered default, I find the current order somewhat unintuitive.

let working_set = StateWorkingSet::new(engine_state);

// Value::Errors must always go to stderr, not stdout.
is_err = true;
Copy link
Copy Markdown
Contributor Author

@webbedspace webbedspace Jan 2, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does anyone have an opinion about these lines? I don't know why Value::Errors seemingly were allowed to go to stdout, but that seemed wrong to me (and I needed to make this change to make a test pass, due to the aforementioned business about creating but not returning Value::Errors in follow_cell_path_helper().)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it makes sense to force errors to stderr.

@rgwood
Copy link
Copy Markdown
Contributor

rgwood commented Jan 2, 2023

OK, I fixed it. However, I just noticed I've inadvertently changed the semantics of -i somewhat.

Sounds good to me - the "-i sometimes collapses everything into a single null" behaviour was bad IMO.

@rgwood rgwood added the notes:breaking-changes This PR implies a change affecting users and has to be noted in the release notes label Jan 2, 2023
_ => Ok(Value::int(input.into_iter().count() as i64, call.head).into_pipeline_data()),
_ => {
let mut count: i64 = 0;
// Check for and propagate errors
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a little concerned by this approach of checking for errors in downstream commands.I worry that there will be a long tail of commands where we forget to do it, leading to inconsistency. It also takes us further away from an "errors are just data" approach (which we admittedly do not adhere to very well today).

That said, users who do something like $foo | get bar | length will expect it to fail on an unsuccessful bar access... so maybe this is an OK approach for now.

In the future it would be nice if this sort of check was handled at a higher level (not sure exactly where).

Copy link
Copy Markdown
Contributor

@rgwood rgwood left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR!

I think this is a good incremental improvement to cell paths. I really like that behaviour is more consistent across get and select now, and that -i no longer collapses multiple errors to a single null value.

This one will probably break a handful of scripts, and it will need an explanation in the 0.74 blog post (0.74 is being released on Jan 10): nushell/nushell.github.io#715

I'm happy to merge this, just want to get another opinion first.

@fdncred
Copy link
Copy Markdown
Contributor

fdncred commented Jan 2, 2023

+1 for more consistent and expected behavior

@rgwood rgwood merged commit 65d0b5b into nushell:main Jan 2, 2023
@webbedspace webbedspace deleted the hole-error branch January 4, 2023 08:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

notes:breaking-changes 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.

Cell paths: foo.1 is not always equal to 1.foo

3 participants