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

nix eval doesn't understand expressions that don't begin with a paren #3032

Closed
lilyball opened this issue Aug 7, 2019 · 7 comments
Closed

Comments

@lilyball
Copy link
Member

lilyball commented Aug 7, 2019

Describe the bug
The nix eval command is documented as evaluating a Nix expression, but its actual handling of the argument is rather confusing. As near as I can tell, unless the argument begins with an open paren, it's assumed to be a path identifying an attribute in NIX_PATH. Passing anything else just emits a confusing error message saying it doesn't know what to do with the expression.

To Reproduce
Steps to reproduce the behavior:

  1. nix eval nixpkgs.hello.name
  2. nix eval '(nixpkgs.hello.name)'
  3. nix eval '1 + 2'
  4. nix eval '(1 + 2)'
  5. nix eval -f '<nixpkgs>' hello.name
  6. nix eval -f '<nixpkgs>' '(hello.name)'

Expected behavior

  1. The name of nixpkgs.hello, which for me is "hello-2.10"
  2. Preferably the same thing, though arguably the current behavior of saying undefined variable 'nixpkgs' is acceptable.
  3. 3
  4. 3
  5. The name of nixpkgs.hello again
  6. The same thing.

Actual behavior

  1. As expected.
  2. The undefined variable warning.
  3. error: don't know what to do with argument '1 + 2'
  4. As expected.
  5. As expected.
  6. error: undefined variable 'hello' at (string):1:2. This one actually mystifies me; does nix eval just discard the -f argument entirely if the expression begins with a paren? I would have expected it to import the attributes like it does without parens, or like nix repl does with :l.

Additional details
In general, nix eval should just treat all arguments as expressions and evaluate them. The only problem with this very general approach is either nix eval nixpkgs.hello.name would stop working because the channels wouldn't be available as top-level attributes, or alternatively nix eval 'some-arbitrary-expression' would be evaluated with all the channels already imported, which is probably surprising (in addition to the performance implications of always loading all entries of the path).

Given that, I think reasonable behavior is

  1. If the expression consists entirely of an attribute path, look it up using NIX_PATH and return the results. This matches the behavior today.
  2. Otherwise, if it parses as anything other than just an attribute path, treat it as an expression. If an -f flag was passed, load the file into the environment first, otherwise leave the environment empty.

This means that nix eval '1 + 2' would behave just as nix eval '(1 + 2)' does today, and it also means that nix eval -f '<nixpkgs>' '(hello.name)' would behave the same as nix eval -f '<nixpkgs>' hello.name.

Metadata

  • system: "x86_64-darwin"
  • host os: Darwin 18.7.0, macOS 10.14.6
  • multi-user?: no
  • sandbox: no
  • version: nix-env (Nix) 2.2.2
  • channels(lily): "nixpkgs-19.09pre186574.88d9f776091"
  • nixpkgs: /Users/lily/.nix-defexpr/channels/nixpkgs
@worldofpeace
Copy link
Contributor

This is a nix ui issue so it should be in the nix repo. I'll see if someone can transfer it for you.

@grahamc grahamc transferred this issue from NixOS/nixpkgs Aug 7, 2019
@lilyball
Copy link
Member Author

lilyball commented Aug 7, 2019

Oops, thanks. I think Safari auto-completed the repo URL for me and I didn't notice.

@lilyball
Copy link
Member Author

lilyball commented Aug 7, 2019

Also see #2078

@edolstra
Copy link
Member

edolstra commented Aug 7, 2019

This is intended behaviour. Expressions have to enclosed in parentheses, to disambiguate them from other kinds of installables (like store paths or flake references).

@lilyball
Copy link
Member Author

lilyball commented Aug 7, 2019

The documentation for nix eval does not mention the ability to pass a Nix store path as an argument, and it's unclear to me what that does. That said, we could add a rule that says "if the argument can be parsed as a path, treat it as a nix store path and do whatever it is we do with that today".

Similarly, if we can parse the argument as a flake reference, we can then treat it that way. I'm assuming a flake reference is a thing that looks like nixpkgs:hello, right? It should be easy enough to define handling for that.

Basically what I'm getting at is nix eval should never say error: don't know what to do with argument '1 + 2'. If it doesn't know how to interpret the argument, it should just fall back to evaluating it as a Nix expression, just as it does if the argument starts with a paren.

@tobiasBora
Copy link

I agree that this is confusing. I understand that disambiguate is important, but then the error message should be more explicit, and say something like "If you wanted to input a nix expression, please add parens.". The fallback is also a nice idea.

@edolstra
Copy link
Member

edolstra commented Jun 8, 2020

Will close this issue since on the flakes branch (which should be merged into master soon), parentheses are no longer supported to indicate an expression. You have to use nix eval --expr "...".

@edolstra edolstra closed this as completed Jun 8, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants