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

Make string interpolation and builtins.toString behave the same #7327

Closed
fricklerhandwerk opened this issue Nov 21, 2022 · 3 comments
Closed
Labels
feature Feature request or proposal language The Nix expression language; parser, interpreter, primops, evaluation, etc

Comments

@fricklerhandwerk
Copy link
Contributor

fricklerhandwerk commented Nov 21, 2022

Is your feature request related to a problem? Please describe.

toString exp and "${exp}" behave differently.

toString e

Convert the expression e to a string. e can be:

  • A string (in which case the string is returned unmodified).
  • A path (e.g., toString /foo/bar yields "/foo/bar".
  • A set containing { __toString = self: ...; } or { outPath = ...; }.
  • An integer.
  • A list, in which case the string representations of its elements
    are joined with spaces.
  • A Boolean (false yields "", true yields "1").
  • null, which yields the empty string.

Only the first three work with string interpolation, but not e.g. "${1}" or "${true}".

Describe the solution you'd like

The following should work:

"${1}"
"1"
"${[ 1 /foo/bar true ]}"
"1 /nix/store/<hash>-bar true"
"${true}"
"true"
"${false}"
""
"${null}"
""

Describe alternatives you've considered
Make toString work on fewer things, to make the features converge consistency, but that would break existing code or require a deprecation strategy.

Additional context
It's not clear why these differences even exist, except that string interpolation on paths serves a different purpose than for the other data types.

@fricklerhandwerk fricklerhandwerk added feature Feature request or proposal language The Nix expression language; parser, interpreter, primops, evaluation, etc labels Nov 21, 2022
@tejing1
Copy link

tejing1 commented Jan 23, 2023

At least make integers work... the rest are of more debatable value, but integers working in antiquotes is just basic functionality in any decent language at this point.

@sternenseemann
Copy link
Member

sternenseemann commented Jul 8, 2023

Only the first three work with string interpolation, but not e.g. "${1}" or "${true}".

String interpolation has different behavior from toString when it comes to paths. Making both more similar will only increase the confusion around it.

Additionally, implicit type conversions are usually a source of pitfalls, so it is actually good that string interpolation is limited to the absolute essentials (i.e. Nix would be painful to use if paths and derivations needed explicit conversion).

Problem is probably solved by giving a canonical name to the types of coercion or conversion (the C++ Nix code calls both coercion, in the case of toString the function is called with the coerceMore flag (and a different store behavior flag), Tvix distinguishes weak and strong coercion for now) and documenting them.

@tejing1
Copy link

tejing1 commented Jul 8, 2023

I would argue that the current behavior of toString on paths is broken design in the first place. It should be difficult, perhaps even impossible, for nix code to extract eval-time file paths as data.

Path types vs. strings encode a fundamental difference in how the information is being treated (eval time vs run time, essentially), and having basic language constructs completely obliterate that difference just confuses the issue for newcomers, inviting them to make an entire class of mistakes, and annoys the experienced.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature Feature request or proposal language The Nix expression language; parser, interpreter, primops, evaluation, etc
Projects
None yet
Development

No branches or pull requests

3 participants