[Nix-dev] Using string as path to eg. builtins.readFile

Bas van Dijk v.dijk.bas at gmail.com
Tue Jun 21 09:44:01 CEST 2016


Hi Erik,

Do note that I went through the same trouble as you figuring out how
to apply builtins.readFile to a dynamically constructed path. Maybe we
can document this "trick" in the documentation of builtins.readFile so
other people don't have to go through the same trouble.

To understand these things I would recommend using nix-repl:

  $ nix-repl
  Welcome to Nix version 1.11.2. Type :? for help.

  nix-repl> name = "bar"

  nix-repl> ./foo + "${name}"
  /home/bas.van.dijk/foobar

Note that the previous is equivalent to the simpler:

  nix-repl> ./foo + name
  /home/bas.van.dijk/foobar

The reason that you get "foobar" is that we didn't include a "/". So
lets try to do that:

  nix-repl> ./foo/ + name
  error: syntax error, unexpected '+', at (string):1:8

Apparently the Nix path parser doesn't like a slash at the end of a
path literal. So lets try adding the slash dynamically:

  nix-repl> ./foo + "/" + name
  /home/bas.van.dijk/foobar

What happened here? Well, + is left associative so it is interpreted as:

  (./foo + "/") + name

Lets try evaluating that left expression alone:

  nix-repl> ./foo + "/"
  /home/bas.van.dijk/foo

Apparently Nix performs normalization on paths since the final slash
is not included. So lets put the parenthesis differently:

  nix-repl> ./foo + ("/" + name)
  /home/bas.van.dijk/foo/bar

That's better! Now we can shorten this using some antiquotation:

  nix-repl> ./foo + "/${name}"
  /home/bas.van.dijk/foo/bar

I hope this helped.

Cheers,

Bas

On 21 June 2016 at 09:19, 4levels <4levels at gmail.com> wrote:
> Hi Bas,
>
> Out of curiosity I've been experimenting with different approaches but only
> yours works and I have no clue why..  Is there anything I can learn / read /
> study to understand why?  Without having to study C++ (or python for that
> matter as I can't even tell them apart ;-)
> Is this basic lambda programming or very specific to Nix?
>
> Works
> builtins.readFile (./keys + "/${name}")
>
> Doesn't work
> builtins.readFile (./keys/ + "${name}") - unexpected +
> builtins.readFile (./keys/ + name) - unexpected +
> builtins.readFile (./keys + "/" + name") - no build errors, but doesn't
> parse the / in the middle -> ./keysmancloud.amazon.iam.key_id -> not found
>
> Kind regards and thanks again, my key deployment sections have become very
> compact and maintainable now..
>
> Erik
>
> On Tue, Jun 21, 2016 at 1:56 AM 4levels <4levels at gmail.com> wrote:
>>
>> Hi Bas,
>>
>> Thank you so much! Exactly what I was looking for.
>> It's these basic things that I keep not getting my head around.. You have
>> no idea how many fruitless Google and GitHub searches I tried on this one
>> ;-)
>>
>> Finally resolved and another lesson learned, amazing!
>>
>> Kind regards,
>>
>> Erik
>>
>>
>> On Tue, Jun 21, 2016, 01:39 Bas van Dijk <v.dijk.bas at gmail.com> wrote:
>>>
>>> On 19 June 2016 at 15:58, 4levels <4levels at gmail.com> wrote:
>>> > builtins.readFile "./keys/${name}"
>>>
>>> Hi Erik, try this:
>>>
>>>   builtins.readFile (./keys + "/${name}")


More information about the nix-dev mailing list