mirror of
https://github.com/NixOS/nix-pills
synced 2024-11-13 23:27:11 +00:00
Merge pull request #30 from michaelpj/imp/pills-2
Pills 2-4: edit for style and clarity
This commit is contained in:
commit
c5abff6df4
3 changed files with 308 additions and 301 deletions
|
@ -18,11 +18,9 @@
|
|||
</para>
|
||||
|
||||
<para>
|
||||
<link
|
||||
xlink:href="https://nixos.org/nix/manual/#chap-installation">Nix
|
||||
installation</link> is as easy as installing any other package.
|
||||
It will not revolutionize our system, it will stay in its own
|
||||
place out of our way.
|
||||
<link xlink:href="https://nixos.org/nix/manual/#chap-installation">Installing
|
||||
Nix</link> is as easy as installing any other package.
|
||||
It will not drastically change our system, it will stay out of our way.
|
||||
</para>
|
||||
|
||||
<section>
|
||||
|
@ -37,114 +35,114 @@
|
|||
</para>
|
||||
|
||||
<para>
|
||||
My pills are not a simple tutorial, there's are several articles
|
||||
out there to learn the basics of nix and unix. We'll instead
|
||||
walk through the nix system to understand the fundamentals.
|
||||
These articles are not a tutorial on <emphasis>using</emphasis> Nix.
|
||||
Instead, we're going to walk through the Nix system to understand the fundamentals.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
First thing to note: those stuff in nix store refer to software
|
||||
in nix store itself. It doesn't use libc from our system or
|
||||
whatelse. It's a self-contained nix bootstrap.
|
||||
The first thing to note: derivations in the Nix store refer to other
|
||||
derivations which are themselves in the Nix store. They don't use <literal>libc</literal>
|
||||
from our system or anywhere else. It's a self-contained store of all the software we need to bootstrap up
|
||||
to any particular package.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Quick note: in a multi-user installation, such as the one used in NixOS,
|
||||
<note><para>
|
||||
In a multi-user installation, such as the one used in NixOS,
|
||||
the store is owned by root and multiple users can install and build
|
||||
software through a nix daemon. You can read more about multi-user
|
||||
software through a Nix daemon. You can read more about multi-user
|
||||
installations here: <link
|
||||
xlink:href="https://nixos.org/nix/manual/#ssec-multi-user">https://nixos.org/nix/manual/#ssec-multi-user</link>.
|
||||
</para>
|
||||
</para></note>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>So small nix store</title>
|
||||
<title>The beginnings of the Nix store</title>
|
||||
|
||||
<para>
|
||||
Start inspecting the output of the install command:
|
||||
Start looking at the output of the install command:
|
||||
</para>
|
||||
|
||||
<screen>copying Nix to /nix/store..........................</screen>
|
||||
|
||||
<para>
|
||||
Effectively, that's right the <literal>/nix/store</literal> we
|
||||
were talking in the first pill. The contents is the strictly
|
||||
That's the <filename>/nix/store</filename> we
|
||||
were talking in the first article. We're copying in the
|
||||
necessary software to bootstrap a Nix system. You can see bash,
|
||||
core utils, the toolchain, perl libraries, sqlite and nix itself
|
||||
coreutils, the C compiler toolchain, perl libraries, sqlite and Nix itself
|
||||
with its own tools and libnix.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
You surely noticed that in <literal>/nix/store</literal> not
|
||||
only directories are allowed, but also files, always in the form
|
||||
You may have noticed that <filename>/nix/store</filename> can contain
|
||||
not only directories, but also files, still always in the form
|
||||
<replaceable>hash-name</replaceable>.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>The holy database</title>
|
||||
<title>The Nix database</title>
|
||||
|
||||
<para>
|
||||
Right after copying the store, the installation process
|
||||
initializes the database with the current information:
|
||||
initializes a database:
|
||||
</para>
|
||||
|
||||
<screen>initialising Nix database...</screen>
|
||||
|
||||
<para>
|
||||
Oh Nix also has a database. It's under
|
||||
<literal>/nix/var/nix/db</literal>. It is an sqlite database
|
||||
Yes, Nix also has a database. It's stored under
|
||||
<filename>/nix/var/nix/db</filename>. It is a sqlite database
|
||||
that keeps track of the dependencies between derivations.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The schema is very simple: there's a table of valid paths,
|
||||
mapping from auto increment integer to store path.
|
||||
mapping from an auto increment integer to a store path.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Then there's a dependency relation from one path to other paths.
|
||||
Then there's a dependency relation from path to paths upon which they depend.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
You may inspect it by installing sqlite
|
||||
(<command>nix-env -iA sqlite -f '<nixpkgs>'</command>) then running
|
||||
<command>sqlite3 /nix/var/nix/db/db.sqlite</command>
|
||||
You can inspect the database by installing sqlite
|
||||
(<command>nix-env -iA sqlite -f '<nixpkgs>'</command>) and then running
|
||||
<command>sqlite3 /nix/var/nix/db/db.sqlite</command>.
|
||||
</para>
|
||||
|
||||
<note><para>If this is the first time you're using Nix after the
|
||||
initial installation, remember you must close and open your
|
||||
terminals first.</para></note>
|
||||
terminals first, so that your shell environment will be updated.</para></note>
|
||||
|
||||
<para>
|
||||
<emphasis>Important rule:</emphasis> never change
|
||||
<literal>/nix/store</literal> manually because that wouldn't be
|
||||
in sync with the sqlite db, unless you know what you are doing.
|
||||
</para>
|
||||
<important><para>
|
||||
Never change <filename>/nix/store</filename> manually. If you do, then it will
|
||||
no longer be in sync with the sqlite db, unless you <emphasis>really</emphasis>
|
||||
know what you are doing.
|
||||
</para></important>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>The first profile</title>
|
||||
|
||||
<para>
|
||||
Then we discover the <link
|
||||
xlink:href="https://nixos.org/nix/manual/#sec-profiles">profile</link>
|
||||
concept during the installation:
|
||||
Next in the installation, we encounter the concept of the <link
|
||||
xlink:href="https://nixos.org/nix/manual/#sec-profiles">profile</link>:
|
||||
</para>
|
||||
|
||||
<xi:include href="./02/user-environment.xml" parse="xml" />
|
||||
|
||||
<para>
|
||||
A profile in nix is a general and very convenient concept for
|
||||
realizing rollbacks. Profiles are used to compose more
|
||||
components that are spread among multiple paths, under a new
|
||||
unified path. Not only, profiles are made up of multiple
|
||||
generations: they are versioned. Whenever you change a profile,
|
||||
A profile in Nix is a general and convenient concept for
|
||||
realizing rollbacks. Profiles are used to compose
|
||||
components that are spread among multiple paths under a new
|
||||
unified path. Not only that, but profiles are made up of multiple
|
||||
"generations": they are versioned. Whenever you change a profile,
|
||||
a new generation is created.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Generations thus can be switched and rollback-ed atomatically.
|
||||
Generations can be switched and rolled back atomically, which makes
|
||||
them convenient for managing changes to your system.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
|
@ -153,45 +151,46 @@
|
|||
|
||||
<xi:include href="./02/profile.xml" parse="xml" />
|
||||
<para>
|
||||
That <package>nix-1.7</package> derivation in the nix store is
|
||||
nix itself, with binaries and libraries. The installation
|
||||
basically reproduced the hierarchy of the
|
||||
<package>nix-1.7</package> derivation in the profile by means of
|
||||
That <package>nix-1.7</package> derivation in the Nix store is
|
||||
Nix itself, with binaries and libraries. The process of "installing"
|
||||
the derivation in the profile basically reproduces the hierarchy of the
|
||||
<package>nix-1.7</package> store derivation in the profile by means of
|
||||
symbolic links.
|
||||
</para>
|
||||
<para>
|
||||
The contents of this profile are special, because only one
|
||||
program has been installed in our profile, therefore e.g. the
|
||||
bin directory fully points to the only program being installed.
|
||||
<filename>bin</filename> directory points to the only program
|
||||
which has been installed (Nix itself).
|
||||
</para>
|
||||
<para>
|
||||
But that's only the contents of the latest generation of our
|
||||
profile. In fact, <literal>~/.nix-profile</literal> itself is a
|
||||
profile. In fact, <filename>~/.nix-profile</filename> itself is a
|
||||
symbolic link to
|
||||
<literal>/nix/var/nix/profiles/default</literal>.
|
||||
<filename>/nix/var/nix/profiles/default</filename>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
In turn, that's a symlink to <literal>default-1-link</literal>
|
||||
in the same directory. Yes, that means it's the generation #1 of
|
||||
In turn, that's a symlink to <filename>default-1-link</filename>
|
||||
in the same directory. Yes, that means it's the first generation of
|
||||
the <literal>default</literal> profile.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Finally that's a symlink to the nix store "user-environment"
|
||||
derivation that you saw printed during the installation process.
|
||||
Finally, <filename>default-1-link</filename> is a symlink to the nix
|
||||
store "user-environment" derivation that you saw printed during the installation process.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The <filename>manifest.nix</filename> will be meat for the next pill.
|
||||
We'll talk about <filename>manifest.nix</filename> more in the next article.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Meet nixpkgs expressions</title>
|
||||
<title>Nixpkgs expressions</title>
|
||||
|
||||
<para>
|
||||
More wild output from the installer:
|
||||
More output from the installer:
|
||||
</para>
|
||||
|
||||
<screen><xi:include href="./02/nixpkgs-expressions.txt"
|
||||
|
@ -203,7 +202,7 @@
|
|||
expressions</link> are used to describe packages and how to
|
||||
build them. <link
|
||||
xlink:href="https://nixos.org/nixpkgs/">Nixpkgs</link> is the
|
||||
repository containing all these expressions: <link
|
||||
repository containing all of the expressions: <link
|
||||
xlink:href="https://github.com/NixOS/nixpkgs">https://github.com/NixOS/nixpkgs</link>.
|
||||
</para>
|
||||
|
||||
|
@ -213,35 +212,35 @@
|
|||
</para>
|
||||
|
||||
<para>
|
||||
The second profile we meet is the channels profile.
|
||||
The second profile we discover is the channels profile.
|
||||
<filename>~/.nix-defexpr/channels</filename> points to
|
||||
<filename>/nix/var/nix/profiles/per-user/nix/channels</filename>
|
||||
which points to <literal>channels-1-link</literal> which points
|
||||
to a nix store directory containing the downloaded nix
|
||||
to a Nix store directory containing the downloaded Nix
|
||||
expressions.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Channels are a set of packages and expressions available for
|
||||
download. Similar to debian stable and unstable, there's a
|
||||
download. Similar to Debian stable and unstable, there's a
|
||||
stable and unstable channel. In this installation, we're
|
||||
tracking nixpkgs unstable.
|
||||
tracking <literal>nixpkgs-unstable</literal>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Don't bother yet with nix expressions.
|
||||
Don't worry about Nix expressions yet, we'll get to them later.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Finally, for your own convenience, it modified
|
||||
<filename>~/.profile</filename> to automatically enter the nix
|
||||
Finally, for your convenience, the installer modified
|
||||
<filename>~/.profile</filename> to automatically enter the Nix
|
||||
environment. What
|
||||
<filename>~/.nix-profile/etc/profile.d/nix.sh</filename> really
|
||||
does is simply adding <filename>~/.nix-profile/bin</filename> to
|
||||
does is simply to add <filename>~/.nix-profile/bin</filename> to
|
||||
<varname>PATH</varname> and
|
||||
<filename>~/.nix-defexpr/channels/nixpkgs</filename> to
|
||||
<varname>NIX_PATH</varname>. We'll discuss about
|
||||
<varname>NIX_PATH</varname> in another pill.
|
||||
<varname>NIX_PATH</varname>. We'll discuss
|
||||
<varname>NIX_PATH</varname> later.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
|
@ -254,15 +253,15 @@
|
|||
<title>FAQ: Can I change /nix to something else?</title>
|
||||
|
||||
<para>
|
||||
You can, but there's a strong reason to keep using
|
||||
<literal>/nix</literal> instead of a different directory. All
|
||||
the derivations depend on other derivations by absolute path. I
|
||||
remind you in pill 1 that bash pointed to a
|
||||
<package>glibc</package> under <filename>/nix/store</filename>.
|
||||
You can, but there's a good reason to keep using
|
||||
<filename>/nix</filename> instead of a different directory. All
|
||||
the derivations depend on other derivations by using absolute paths. We
|
||||
saw in the first article that bash referenced a
|
||||
<package>glibc</package> under a specific absolute path in <filename>/nix/store</filename>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
You can see now by yourself, don't worry if you see multiple
|
||||
You can see for yourself, don't worry if you see multiple
|
||||
bash derivations:
|
||||
</para>
|
||||
|
||||
|
@ -275,43 +274,48 @@
|
|||
from debian mirrors) otherwise:
|
||||
|
||||
<itemizedlist>
|
||||
<listitem><para><package>glibc</package> would be installed under <filename>/foo/store</filename></para></listitem>
|
||||
<listitem><para>thus bash needs to point to <package>glibc</package> under <filename>/foo/store</filename></para></listitem>
|
||||
<listitem><para>the binary cache won't help, and we'd have to recompile all the stuff by ourselves</para></listitem>
|
||||
<listitem><para>
|
||||
<package>glibc</package> would be installed under <filename>/foo/store</filename>
|
||||
</para></listitem>
|
||||
<listitem><para>
|
||||
Thus bash would need to point to <package>glibc</package> under <filename>/foo/store</filename>,
|
||||
instead of under <filename>/nix/store</filename>
|
||||
</para></listitem>
|
||||
<listitem><para>
|
||||
So the binary cache can't help, because we need a <emphasis>different</emphasis> bash,
|
||||
and so we'd have to recompile everything ourselves.
|
||||
</para></listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
After all <filename>/nix</filename> is a cool place.
|
||||
After all <filename>/nix</filename> is a sensible place for the store.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Conclusion</title>
|
||||
<para>
|
||||
We've installed nix on our system, fully isolated and owned by
|
||||
the <literal>nix</literal> user as we're still diffident with
|
||||
We've installed Nix on our system, fully isolated and owned by
|
||||
the <literal>nix</literal> user as we're still coming to terms with
|
||||
this new system.
|
||||
</para>
|
||||
<para>
|
||||
We learned some new concepts like profiles and channels. In
|
||||
particular, with profiles we're able to manage multiple
|
||||
generations of a composition of packages, while with channels
|
||||
we're able to download binaries from nixos.org.
|
||||
we're able to download binaries from <literal>nixos.org</literal>.
|
||||
</para>
|
||||
<para>
|
||||
The installation put everything under <filename>/nix</filename>,
|
||||
and some symlinks in the nix user home. That's because every
|
||||
and some symlinks in the Nix user home. That's because every
|
||||
user is able to install and use software in her own environment.
|
||||
</para>
|
||||
<para>
|
||||
I hope I left nothing uncovered in a way that you think there's
|
||||
some kind of magic behind. It's all about putting components in
|
||||
the store and symlinking these components together.
|
||||
</para>
|
||||
<para>
|
||||
Also I hope the commands in this pill were consistent with your
|
||||
fresh nix installation.
|
||||
I hope I left nothing uncovered so that you think there's
|
||||
some kind of magic going on behind the scenes. It's all
|
||||
about putting components in the store and symlinking
|
||||
these components together.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
|
@ -319,7 +323,7 @@
|
|||
<title>Next pill...</title>
|
||||
|
||||
<para>
|
||||
...we will enter the nix environment and learn how to interact
|
||||
...we will enter the Nix environment and learn how to interact
|
||||
with the store.
|
||||
</para>
|
||||
</section>
|
||||
|
|
|
@ -4,22 +4,22 @@
|
|||
version="5.0"
|
||||
xml:id="enter-environment">
|
||||
|
||||
<title>Enter Environment</title>
|
||||
<title>Enter the Environment</title>
|
||||
|
||||
<para>
|
||||
Welcome to the third Nix pill. In the previous <link
|
||||
linkend="install-on-your-running-system">second pill</link> we have
|
||||
Welcome to the third Nix pill. In the <link
|
||||
linkend="install-on-your-running-system">second pill</link> we
|
||||
installed Nix on our running system. Now we can finally play with it a
|
||||
little, things also apply to NixOS users.
|
||||
little, these things also apply to NixOS users.
|
||||
</para>
|
||||
|
||||
<section>
|
||||
<title>Enter the environment</title>
|
||||
|
||||
<para>
|
||||
In the previous pill we created a nix user, so let's start by switching
|
||||
user with <literal>su - nix</literal>. If your
|
||||
<literal>~/.profile</literal> got evaluated, then your should now be able
|
||||
In the previous article we created a Nix user, so let's start by switching
|
||||
to it with <command>su - nix</command>. If your
|
||||
<filename>~/.profile</filename> got evaluated, then your should now be able
|
||||
to run commands like <literal>nix-env</literal> and
|
||||
<literal>nix-store</literal>.
|
||||
</para>
|
||||
|
@ -31,8 +31,8 @@
|
|||
<screen><xi:include href="./03/source-nix.txt" parse="text" /></screen>
|
||||
|
||||
<para>
|
||||
I remind you, <literal>~/.nix-profile/etc</literal> points to the nix-1.7
|
||||
derivation. At this point, we are in our nix user profile.
|
||||
To remind you, <literal>~/.nix-profile/etc</literal> points to the <literal>nix-1.7</literal>
|
||||
derivation. At this point, we are in our Nix user profile.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
|
@ -40,8 +40,8 @@
|
|||
<title>Install something</title>
|
||||
|
||||
<para>
|
||||
Finally something practical! Installation in the nix environment is an
|
||||
interesting process. Let's install nix-repl, a simple command line tool
|
||||
Finally something practical! Installation into the Nix environment is an
|
||||
interesting process. Let's install <literal>nix-repl</literal>, a simple command line tool
|
||||
for playing with the Nix language. Yes, Nix is a <link xlink:href="http://nixos.org/nix/manual/#idm47361539226272">
|
||||
pure, lazy, functional language</link>, not only a set of tools to
|
||||
manage derivations.
|
||||
|
@ -54,19 +54,18 @@
|
|||
<screen><xi:include href="./03/install-repl.txt" parse="text" /></screen>
|
||||
|
||||
<para>
|
||||
Now you can run nix-repl. Things to notice:
|
||||
Now you can run <literal>nix-repl</literal>. Things to notice:
|
||||
</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
We did install software as user, only for the nix user.
|
||||
We installed software as a user, and only for the Nix user.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
It created a new user environment. That's a new generation of our
|
||||
nix user profile.
|
||||
Nix user profile.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
|
@ -78,31 +77,31 @@
|
|||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
We installed nix-repl by derivation name minus the version. I repeat:
|
||||
we did specify the <emphasis role="bold">derivation name</emphasis>
|
||||
(minus the version) to install.
|
||||
We installed <literal>nix-repl</literal> by derivation name minus the version. I repeat:
|
||||
we specified the <emphasis role="bold">derivation name</emphasis>
|
||||
(minus the version) to install it.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>
|
||||
We can list generations without walking through the /nix hierarchy:
|
||||
We can list generations without walking through the <filename>/nix</filename> hierarchy:
|
||||
</para>
|
||||
|
||||
<screen><xi:include href="./03/list-generations.txt" parse="text" /></screen>
|
||||
|
||||
<para>
|
||||
List installed derivations:
|
||||
Listing installed derivations:
|
||||
</para>
|
||||
|
||||
<screen><xi:include href="./03/list-installed-derivations.txt" parse="text" /></screen>
|
||||
|
||||
<para>
|
||||
So, where did nix-repl really get installed?
|
||||
So, where did <literal>nix-repl</literal> really get installed?
|
||||
<literal>which nix-repl</literal> is
|
||||
<literal>~/.nix-profile/bin/nix-repl</literal> which points to the store.
|
||||
We can also list the derivation paths with nix-env -q --out-path. So
|
||||
that's how those derivation paths are called: the
|
||||
We can also list the derivation paths with <command>nix-env -q --out-path</command>. So
|
||||
that's what those derivation paths are called: the
|
||||
<emphasis role="bold">output</emphasis> of a build.
|
||||
</para>
|
||||
</section>
|
||||
|
@ -111,10 +110,11 @@
|
|||
<title>Path merging</title>
|
||||
|
||||
<para>
|
||||
At this point you sure have the necessity to run "man". Even if you
|
||||
already have man system-wide outside of the nix environment, you can
|
||||
install and use it within nix with <literal>nix-env -i man</literal>. As
|
||||
usual, a new generation will be created, and ~/.nix-profile will point to
|
||||
At this point you probably want to run <literal>man</literal> to get some documentation.
|
||||
Even if you
|
||||
already have man system-wide outside of the Nix environment, you can
|
||||
install and use it within Nix with <command>nix-env -i man</command>. As
|
||||
usual, a new generation will be created, and <filename>~/.nix-profile</filename> will point to
|
||||
it.
|
||||
</para>
|
||||
|
||||
|
@ -127,26 +127,26 @@
|
|||
<screen><xi:include href="./03/ls-nix-profile.txt" parse="text" /></screen>
|
||||
|
||||
<para>
|
||||
Now that's interesting. When only nix-1.7 was installed, bin/ was a
|
||||
symlink to nix-1.7. Now that we've actually installed some things
|
||||
(man, nix-repl), it's a real directory, not a symlink.
|
||||
Now that's interesting. When only <literal>nix-1.7</literal> was installed, <filename>bin</filename> was a
|
||||
symlink to <literal>nix-1.7</literal>. Now that we've actually installed some things
|
||||
(<literal>man</literal>, <literal>nix-repl</literal>), it's a real directory, not a symlink.
|
||||
</para>
|
||||
|
||||
<screen><xi:include href="./03/ls-profile-bin.txt" parse="text" /></screen>
|
||||
|
||||
<para>
|
||||
All clear. nix-env merged the paths from the installed derivations.
|
||||
<literal>which man</literal> points to the nix profile, rather than the
|
||||
system man, because <literal>~/.nix-profile/bin</literal> is at the head
|
||||
of <literal>$PATH</literal>.
|
||||
Okay, that's clearer now. <literal>nix-env</literal> merged the paths from the installed derivations.
|
||||
<command>which man</command> points to the Nix profile, rather than the
|
||||
system <literal>man</literal>, because <filename>~/.nix-profile/bin</filename> is at the head
|
||||
of <varname>$PATH</varname>.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Rollback / switch generation</title>
|
||||
<title>Rolling back and switching generation</title>
|
||||
|
||||
<para>
|
||||
The last command installed "man". We should be at generation #3, unless
|
||||
The last command installed <literal>man</literal>. We should be at generation 3, unless
|
||||
you changed something in the middle. Let's say we want to rollback to the
|
||||
old generation:
|
||||
</para>
|
||||
|
@ -154,21 +154,20 @@
|
|||
<screen><xi:include href="./03/rollback.txt" parse="text" /></screen>
|
||||
|
||||
<para>
|
||||
Now <literal>nix-env -q</literal> does not list "man" anymore.
|
||||
<literal>ls -l `which man`</literal> should now be your system installed
|
||||
one.
|
||||
Now <command>nix-env -q</command> does not list <literal>man</literal> anymore.
|
||||
<command>ls -l `which man`</command> should now be your system copy.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Enough with the joke, let's go back to the last generation:
|
||||
Enough with the rollback, let's go back to the most recent generation:
|
||||
</para>
|
||||
|
||||
<screen><xi:include href="./03/generation-3.txt" parse="text" /></screen>
|
||||
|
||||
<para>
|
||||
I invite you to read the manpage of nix-env. nix-env requires an operation
|
||||
to perform, then there are common options for all operations, and there
|
||||
are options specific to an operation.
|
||||
I invite you to read the manpage of <literal>nix-env</literal>. <literal>nix-env</literal> requires an operation
|
||||
to perform, then there are common options for all operations, as well as
|
||||
options specific to each operation.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
|
@ -189,43 +188,44 @@
|
|||
|
||||
<para>
|
||||
To query and manipulate the store, there's the
|
||||
<literal>nix-store</literal> command. We can do neat things, but we'll
|
||||
<literal>nix-store</literal> command. We can do some interesting things, but we'll
|
||||
only see some queries for now.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Show direct runtime dependencies of nix-repl:
|
||||
To show the direct runtime dependencies of <literal>nix-repl</literal>:
|
||||
</para>
|
||||
|
||||
<screen><xi:include href="./03/references.txt" parse="text" /></screen>
|
||||
|
||||
<para>
|
||||
The argument to nix-store can be anything as long as it points to the
|
||||
nix store. It will follow symlinks.
|
||||
The argument to <literal>nix-store</literal> can be anything as long as it points to the
|
||||
Nix store. It will follow symlinks.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
It may not make sense for you right now, but let's print reverse
|
||||
dependencies of nix-repl:
|
||||
It may not make sense to you right now, but let's print reverse
|
||||
dependencies of <literal>nix-repl</literal>:
|
||||
</para>
|
||||
|
||||
<screen><xi:include href="./03/referrers.txt" parse="text" /></screen>
|
||||
|
||||
<para>
|
||||
Did you expect it? Our environments depend upon nix-repl. Yes, the
|
||||
environments are in the store, and since there are symlinks to nix-repl,
|
||||
therefore the environment depends upon nix-repl
|
||||
Was it what you expected? It turns out that our environments depend upon <literal>nix-repl</literal>.
|
||||
Yes, that means that the environments are in the store, and since they contain symlinks to <literal>nix-repl</literal>,
|
||||
therefore the environment depends upon <literal>nix-repl</literal>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
It lists two environments, generation 2 and generation 3.
|
||||
Two environments were listed, generation 2 and generation 3, since these are the ones that had
|
||||
<literal>nix-repl</literal> installed in them.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The manifest.nix file contains metadata about the environment, such as
|
||||
which derivations are installed. So that nix-env can list them, upgrade
|
||||
or remove them. Guess what, the current manifest.nix can be found in
|
||||
<literal>~/.nix-profile/manifest.nix</literal>.
|
||||
The <filename>manifest.nix</filename> file contains metadata about the environment, such as
|
||||
which derivations are installed. So that <literal>nix-env</literal> can list, upgrade
|
||||
or remove them. And yet again, the current <filename>manifest.nix</filename> can be found at
|
||||
<filename>~/.nix-profile/manifest.nix</filename>.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
|
@ -233,16 +233,16 @@
|
|||
<title>Closures</title>
|
||||
|
||||
<para>
|
||||
The closures of a derivation is a list of all dependencies, recursively,
|
||||
down to the bare minimum necessary to use that derivation.
|
||||
The closures of a derivation is a list of all its dependencies, recursively,
|
||||
including absolutely everything necessary to use that derivation.
|
||||
</para>
|
||||
|
||||
<screen><xi:include href="./03/nix-store.txt" parse="text" /></screen>
|
||||
|
||||
<para>
|
||||
Copying all those derivations to the nix store of another machine makes
|
||||
you able to run "man" out of the box on that other machine. That's the
|
||||
base of nix deployment, you can already foresee the potential when
|
||||
Copying all those derivations to the Nix store of another machine makes
|
||||
you able to run <literal>man</literal> out of the box on that other machine. That's the
|
||||
base of deployment using Nix, and you can already foresee the potential when
|
||||
deploying software in the cloud (hint:
|
||||
<literal>nix-copy-closures</literal> and
|
||||
<literal>nix-store --export</literal>).
|
||||
|
@ -255,16 +255,16 @@
|
|||
<screen><xi:include href="./03/nix-store-tree.txt" parse="text" /></screen>
|
||||
|
||||
<para>
|
||||
With the above command, you can know exactly why a
|
||||
<emphasis role="bold">runtime</emphasis> dependency, being it direct or
|
||||
indirect, has been picked for a given derivation.
|
||||
With the above command, you can find out exactly why a
|
||||
<emphasis>runtime</emphasis> dependency, be it direct or
|
||||
indirect, exists for a given derivation.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Same applies to environments of course. As an exercise run
|
||||
<literal>nix-store -q --tree ~/.nix-profile</literal>, see that the
|
||||
The same applies to environments. As an exercise, run
|
||||
<command>nix-store -q --tree ~/.nix-profile</command>, and see that the
|
||||
first children are direct dependencies of the user environment:
|
||||
the installed derivations, and the manifest.nix.
|
||||
the installed derivations, and the <filename>manifest.nix</filename>.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
|
@ -272,41 +272,42 @@
|
|||
<title>Dependency resolution</title>
|
||||
|
||||
<para>
|
||||
There isn't anything like apt which solves a SAT problem in order to
|
||||
satisfy dependencies with lower and upper bounds on versions. Because
|
||||
there's no need. A derivation X depends on derivation Y, always.
|
||||
There isn't anything like <literal>apt</literal> which solves a SAT problem in order to
|
||||
satisfy dependencies with lower and upper bounds on versions. There's no need
|
||||
for this because all the dependencies are static: if a derivation X depends on a derivation Y,
|
||||
then it always depends on it. A version of X which depended on Z would be a different derivation.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Fancy disrupt</title>
|
||||
<title>Recovering the hard way</title>
|
||||
|
||||
<screen><xi:include href="./03/uninstall-all.txt" parse="text" /></screen>
|
||||
|
||||
<para>
|
||||
Ops, that uninstalled all derivations from the environment, including
|
||||
nix. We are not able to run nix-env, what now?
|
||||
Oops, that uninstalled all derivations from the environment, including
|
||||
Nix. That means we can't even run <literal>nix-env</literal>, what now?
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Environments are a convenience for the user, but Nix is still there, in
|
||||
the store!
|
||||
Previously we got <literal>nix-env</literal> from the environment. Environments
|
||||
are a convenience for the user, but Nix is still there in the store!
|
||||
</para>
|
||||
|
||||
<para>
|
||||
First pick one nix-1.7 derivation:
|
||||
<literal>ls /nix/store/*nix-1.7</literal>, say
|
||||
/nix/store/g21di262aql6xskx15z3qiw3zh3wmjlb-nix-1.7.
|
||||
First, pick one <literal>nix-1.7</literal> derivation:
|
||||
<command>ls /nix/store/*nix-1.7</command>, say
|
||||
<filename>/nix/store/g21di262aql6xskx15z3qiw3zh3wmjlb-nix-1.7</filename>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The first possibility is to rollback:
|
||||
The first option is to rollback:
|
||||
</para>
|
||||
|
||||
<screen><xi:include href="./03/nix-env-rollback.txt" parse="text" /></screen>
|
||||
|
||||
<para>
|
||||
The second possibility is to install nix, thus creating a new generation:
|
||||
The second option is to install Nix, thus creating a new generation:
|
||||
</para>
|
||||
|
||||
<screen><xi:include href="./03/install.txt" parse="text" /></screen>
|
||||
|
@ -316,9 +317,9 @@
|
|||
<title>Channels</title>
|
||||
|
||||
<para>
|
||||
So where are we getting packages from? We said something already in
|
||||
<link linkend="install-on-your-running-system">pill 2</link>.
|
||||
There's a list of channels from which we get packages, usually we use a
|
||||
So where are we getting packages from? We said something about this already in the
|
||||
<link linkend="install-on-your-running-system">second article</link>.
|
||||
There's a list of channels from which we get packages, although usually we use a
|
||||
single channel. The tool to manage channels is
|
||||
<link xlink:href="http://nixos.org/nix/manual/#sec-nix-channel">nix-channel</link>.
|
||||
</para>
|
||||
|
@ -326,20 +327,23 @@
|
|||
<screen><xi:include href="./03/channel-list.txt" parse="text" /></screen>
|
||||
|
||||
<para>
|
||||
That's basically the contents of <literal>~/.nix-channels</literal>.
|
||||
Note: <literal>~/.nix-channels</literal> is not a symlink to the
|
||||
That's essentially the contents of <filename>~/.nix-channels</filename>.
|
||||
</para>
|
||||
|
||||
<note><para>
|
||||
<filename>~/.nix-channels</filename> is not a symlink to the
|
||||
nix store!
|
||||
</para></note>
|
||||
|
||||
<para>
|
||||
To update the channel run <command>nix-channel --update</command>.
|
||||
That will download the new Nix expressions (descriptions of the packages),
|
||||
create a new generation of the channels profile and unpack it under
|
||||
<filename>~/.nix-defexpr/channels</filename>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
To update the channel run <literal>nix-channel --update</literal>.
|
||||
It will download the new nix expressions (descriptions of the packages),
|
||||
create a new generation of the channels profile and unpack under
|
||||
<literal>~/.nix-defexpr/channels</literal>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
That's much similar to apt-get update.
|
||||
This is quite similar to <command>apt-get update</command>.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
|
@ -348,32 +352,32 @@
|
|||
|
||||
<para>
|
||||
We learned how to query the user environment and to manipulate it by
|
||||
installing and uninstalling software. Upgrading software is as straight
|
||||
as it gets by reading
|
||||
installing and uninstalling software. Upgrading software is also straightforward,
|
||||
as you can read in
|
||||
<link xlink:href="http://nixos.org/nix/manual/#idm47361539520832">the manual</link>
|
||||
(<literal>nix-env -u '*'</literal> will upgrade all packages in the
|
||||
(<command>nix-env -u</command> will upgrade all packages in the
|
||||
environment).
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Everytime we change the environment, a new generation gets created.
|
||||
Everytime we change the environment, a new generation is created.
|
||||
Switching between generations is easy and immediate.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Then we queried the store. We inspected the dependencies and reverse
|
||||
Then we leaned how to query the store. We inspected the dependencies and reverse
|
||||
dependencies of store paths.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
We still see symlinks to compose paths from the nix store, our lovely
|
||||
We saw how symlinks are used to compose paths from the Nix store, a useful
|
||||
trick.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Quick analogy with programming languages. You have the heap with all the
|
||||
objects, that's the nix store. You have objects that point to other
|
||||
objects, those are the derivations. Will be this the right path?
|
||||
A quick analogy with programming languages: you have the heap with all the
|
||||
objects, that corresponds to the Nix store. You have objects that point to other
|
||||
objects, those correspond to derivations. This is a suggestive metaphor, but will it be the right path?
|
||||
</para>
|
||||
</section>
|
||||
|
||||
|
@ -382,9 +386,9 @@
|
|||
|
||||
<para>
|
||||
...we will learn the basics of the Nix language. The Nix language is used
|
||||
to describe how to build derivations, and it's the base for everything
|
||||
else including NixOS. Therefore it's very important to understand the
|
||||
syntax and the semantics.
|
||||
to describe how to build derivations, and it's the basis for everything
|
||||
else, including NixOS. Therefore it's very important to understand both the
|
||||
syntax and the semantics of the language.
|
||||
</para>
|
||||
</section>
|
||||
</chapter>
|
||||
|
|
|
@ -4,88 +4,90 @@
|
|||
version="5.0"
|
||||
xml:id="basics-of-language">
|
||||
|
||||
<title>The Basics of Language</title>
|
||||
<title>The Basics of the Language</title>
|
||||
|
||||
<para>
|
||||
Welcome to the fourth Nix pill. In the previous
|
||||
<link linkend="enter-environment">third pill</link> we entered the Nix
|
||||
environment. We installed software as user, managed the profile, switched
|
||||
between generations, and queried the nix store. That's the very basics of
|
||||
nix administration somehow.
|
||||
Welcome to the fourth Nix pill. In the
|
||||
<link linkend="enter-environment">previous article</link> we learned about Nix
|
||||
environments. We installed software as a user, managed their profile, switched
|
||||
between generations, and queried the Nix store. Those are the very basics of
|
||||
system administration using Nix.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The
|
||||
<link xlink:href="http://nixos.org/nix/manual/#chap-writing-nix-expressions">Nix language</link>
|
||||
is used to write derivations. The
|
||||
is used to write expressions that produce derivations. The
|
||||
<link xlink:href="http://nixos.org/nix/manual/#sec-nix-build">nix-build</link>
|
||||
tool is used to build derivations. Even as a system administrator that
|
||||
tool is used to build a derivations from an expression. Even as a system administrator that
|
||||
wants to customize the installation, it's necessary to master Nix. Using
|
||||
Nix for your jobs means you get the features we saw in the previous pills
|
||||
Nix for your jobs means you get the features we saw in the previous articles
|
||||
for free.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The syntax is very uncommon thus looking at existing examples may lead to
|
||||
thinking that there's a lot of magic behind. In reality, it's only about
|
||||
writing utility functions for making things convenient.
|
||||
The syntax of Nix is quite unfamiliar, so looking at existing examples may lead you to
|
||||
think that there's a lot of magic happening. In reality, it's mostly about
|
||||
writing utility functions to make things convenient.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
On the other hand, this same syntax is great for describing packages.
|
||||
On the other hand, the same syntax is great for describing packages, so learning the language
|
||||
itself will pay off when writing package expressions.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<emphasis role="underline">Important</emphasis>: in Nix, everything is an
|
||||
expression, there are no statements. This is common to many functional
|
||||
<important><para>
|
||||
In Nix, everything is an expression, there are no statements. This is common in functional
|
||||
languages.
|
||||
</para>
|
||||
</para></important>
|
||||
|
||||
<para>
|
||||
<emphasis role="underline">Important</emphasis>: values in Nix are
|
||||
immutable.
|
||||
</para>
|
||||
<important><para>
|
||||
Values in Nix are immutable.
|
||||
</para></important>
|
||||
|
||||
<section>
|
||||
<title>Value types</title>
|
||||
|
||||
<para>
|
||||
We've installed nix-repl in the previous pill. If you didn't,
|
||||
<literal>nix-env -i nix-repl</literal>. The nix-repl syntax is slightly
|
||||
different than nix syntax when it comes to assigning variables, but no
|
||||
worries. I prefer playing with nix-repl with you before cluttering your
|
||||
mind with more complex expressions.
|
||||
We've installed <literal>nix-repl</literal> in the previous pill. If you didn't,
|
||||
<command>nix-env -i nix-repl</command>. The <literal>nix-repl</literal> syntax is slightly
|
||||
different to Nix syntax when it comes to assigning variables, but it shouldn't
|
||||
be confusing so long as you bear it in mind. I prefer to start with <literal>nix-repl</literal>
|
||||
before cluttering your mind with more complex expressions.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Launch nix-repl. First of all, nix supports basic arithmetic operations:
|
||||
+, -, and *. The integer division can be done with builtins.div.
|
||||
Launch <literal>nix-repl</literal>. First of all, Nix supports basic arithmetic operations:
|
||||
<literal>+</literal>, <literal>-</literal>, and <literal>*</literal>. Integer division can be
|
||||
done with <literal>builtins.div</literal>.
|
||||
</para>
|
||||
|
||||
<screen><xi:include href="./04/basics.txt" parse="text" /></screen>
|
||||
|
||||
<para>
|
||||
Really, why doesn't nix have basic operations such as division? Because
|
||||
it's not needed for creating packages. Nix is not a general purpose
|
||||
You might wonder why Nix doesn't have basic operations such as integer division. The answer is
|
||||
because it's not needed for creating packages. Nix is not a general purpose
|
||||
language, it's a domain-specific language for writing packages.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Just think that builtins.div is not being used in the whole of our
|
||||
nixpkgs repository: it's useless.
|
||||
Just think - <literal>builtins.div</literal> is not used in the whole of the
|
||||
nixpkgs repository: it's not actually useful if you are writing package expressions.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Other operators are ||, && and ! for booleans, and relational
|
||||
operators such as !=, ==, <, >, <=, >=. In Nix, <, >, <= and
|
||||
>= are not much used. There are also other operators we will see in the
|
||||
Other operators are <literal>||</literal>, <literal>&&</literal> and <literal>!</literal>
|
||||
for booleans, and relational
|
||||
operators such as <literal>!=</literal>, <literal>==</literal>, <literal><</literal>, <literal>></literal>,
|
||||
<literal><=</literal>, <literal>>=</literal>. In Nix, <literal><</literal>, <literal>></literal>,
|
||||
<literal><=</literal> and <literal>>=</literal> are not much used. There are also other operators we will see in the
|
||||
course of this series.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Nix has integer (not floating point), string, path, boolean and null
|
||||
<link xlink:href="http://nixos.org/nix/manual/#ssec-values">simple</link>
|
||||
types. Then there are lists, sets and functions. These types are enough
|
||||
types. Then there are also lists, sets and functions. These types are enough
|
||||
to build an operating system.
|
||||
</para>
|
||||
|
||||
|
@ -101,14 +103,14 @@
|
|||
<screen><xi:include href="./04/relative-path.txt" parse="text" /></screen>
|
||||
|
||||
<para>
|
||||
Nix parsed 2/3 as a relative path to the current directory. Paths are
|
||||
parsed as long as there's a slash. Therefore to specify the current
|
||||
directory, use <literal>./.</literal> In addition, Nix also parses urls.
|
||||
Nix parsed <literal>2/3</literal> as a relative path to the current directory. Expressions will
|
||||
be parsed as paths as long as there's a slash. Therefore to specify the current
|
||||
directory, use <literal>./.</literal> In addition, Nix also parses urls specially.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Not all urls or paths can be parsed this way. If a syntax error occurs,
|
||||
it's still possible to fallback to plain strings. Parsing urls and paths
|
||||
it's still possible to fallback to plain strings. Literal urls and paths
|
||||
are convenient for additional safety.
|
||||
</para>
|
||||
</section>
|
||||
|
@ -117,15 +119,15 @@
|
|||
<title>Identifier</title>
|
||||
|
||||
<para>
|
||||
Not much to say, except that dash (-) is allowed in identifiers. That's
|
||||
convenient since many packages use dash in its name. In fact:
|
||||
There's not much to say here, except that dash (<literal>-</literal>) is allowed in identifiers. That's
|
||||
convenient since many packages use dash in their names. In fact:
|
||||
</para>
|
||||
|
||||
<screen><xi:include href="./04/dash.txt" parse="text" /></screen>
|
||||
|
||||
<para>
|
||||
As you can see, <literal>a-b</literal> is parsed as identifier, not as
|
||||
operation between a and b.
|
||||
a subtraction.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
|
@ -133,183 +135,180 @@
|
|||
<title>Strings</title>
|
||||
|
||||
<para>
|
||||
It's important to understand the syntax for strings. When reading Nix
|
||||
expressions at the beginning, you may find dollars ($) ambiguous in their
|
||||
usage. Strings are enclosed by double quotes ("), or two single quotes
|
||||
('').
|
||||
It's important to understand the syntax for strings. When learning to read Nix
|
||||
expressions, you may find dollars (<literal>$</literal>) ambiguous, but they are very important .
|
||||
Strings are enclosed by double quotes (<literal>"</literal>), or two single quotes (<literal>''</literal>).
|
||||
</para>
|
||||
|
||||
<screen><xi:include href="./04/strings-basic.txt" parse="text" /></screen>
|
||||
|
||||
<para>
|
||||
In python you can use also single quotes for strings like 'foo', but not
|
||||
in Nix.
|
||||
In other languages like Python you can also use single quotes for strings (e.g. <literal>'foo'</literal>),
|
||||
but not in Nix.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
It's possible to
|
||||
<link xlink:href="http://nixos.org/nix/manual/#ssec-values">interpolate</link>
|
||||
whole Nix expressions inside strings with ${...} and only with ${...},
|
||||
not $foo or {$foo} or anything else.
|
||||
whole Nix expressions inside strings with the <literal>${...}</literal> syntax and only that syntax,
|
||||
not <literal>$foo</literal> or <literal>{$foo}</literal> or anything else.
|
||||
</para>
|
||||
|
||||
<screen><xi:include href="./04/interpolate.txt" parse="text" /></screen>
|
||||
|
||||
<para>
|
||||
Note: ignore the foo = "strval" assignment, it's nix-repl special syntax.
|
||||
Note: ignore the <literal>foo = "strval"</literal> assignment, special syntax in <literal>nix-repl</literal>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
As said previously, you cannot mix integers and strings. You explicitly
|
||||
need conversion. We'll see this later: function calls are another story.
|
||||
As said previously, you cannot mix integers and strings. You need to explicitly
|
||||
include conversions. We'll see this later: function calls are another story.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Using the syntax with two single quotes, it's useful for writing double
|
||||
quotes inside strings instead of escaping:
|
||||
Using the syntax with two single quotes is useful for writing double
|
||||
quotes inside strings without needing to escape them:
|
||||
</para>
|
||||
|
||||
<screen><xi:include href="./04/double-quotes.txt" parse="text" /></screen>
|
||||
|
||||
<para>
|
||||
Escaping ${...} within double quoted strings is done with the backslash.
|
||||
Within two single quotes, it's done with '':
|
||||
Escaping <literal>${...}</literal> within double quoted strings is done with the backslash.
|
||||
Within two single quotes, it's done with <literal>''</literal>:
|
||||
</para>
|
||||
|
||||
<screen><xi:include href="./04/escaping.txt" parse="text" /></screen>
|
||||
|
||||
<para>
|
||||
No other magic about strings for now.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Lists</title>
|
||||
|
||||
<para>
|
||||
Lists are a sequence of expressions delimited by space (not comma):
|
||||
Lists are a sequence of expressions delimited by space (<emphasis>not</emphasis> comma):
|
||||
</para>
|
||||
|
||||
<screen><xi:include href="./04/lists.txt" parse="text" /></screen>
|
||||
|
||||
<para>
|
||||
Lists, like anything else in Nix, are immutable. Adding or removing
|
||||
Lists, like everything else in Nix, are immutable. Adding or removing
|
||||
elements from a list is possible, but will return a new list.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Sets</title>
|
||||
<title>Attribute sets</title>
|
||||
|
||||
<para>
|
||||
Sets are an association between a string key and a Nix expression. Keys
|
||||
can only be strings. When writing sets you can also use identifiers as
|
||||
Attribute sets are an association between string keys and a Nix values. Keys
|
||||
can only be strings. When writing attribute sets you can also use unquoted identifiers as
|
||||
keys.
|
||||
</para>
|
||||
|
||||
<screen><xi:include href="./04/set-basics.txt" parse="text" /></screen>
|
||||
|
||||
<para>
|
||||
Note: here the string representation from nix is wrong, you can't write
|
||||
{ 123 = "num"; } because 123 is not an identifier. You need semicolon
|
||||
(;) after every key-value assignment.
|
||||
</para>
|
||||
<note><para>
|
||||
Here the string representation printed in the repl is wrong, you can't write
|
||||
<literal>{ 123 = "num"; }</literal>, because 123 is not an identifier. You also need a semicolon
|
||||
(<literal>;</literal>) after every key-value assignment.
|
||||
</para></note>
|
||||
|
||||
<para>
|
||||
For those reading Nix expressions from nixpkgs: do not confuse sets with
|
||||
For those reading Nix expressions from nixpkgs: do not confuse attribute sets with
|
||||
argument sets used in functions.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
To access elements in the set:
|
||||
To access elements in the attribute set:
|
||||
</para>
|
||||
|
||||
<screen><xi:include href="./04/set-access.txt" parse="text" /></screen>
|
||||
|
||||
<para>
|
||||
Yes, you can use strings for non-identifiers to address keys in the set.
|
||||
Yes, you can use strings for to address keys which aren't valid identifiers.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
You cannot refer inside a set to elements of the same set:
|
||||
Inside an attribute set you cannot normally refer to elements of the same attribute set:
|
||||
</para>
|
||||
|
||||
<screen><xi:include href="./04/set-failed.txt" parse="text" /></screen>
|
||||
|
||||
<para>
|
||||
To do so, use
|
||||
<link xlink:href="http://nixos.org/nix/manual/#idm47361539166560">recursive sets</link>:
|
||||
<link xlink:href="http://nixos.org/nix/manual/#idm47361539166560">recursive attribute sets</link>:
|
||||
</para>
|
||||
|
||||
<screen><xi:include href="./04/set-recursive.txt" parse="text" /></screen>
|
||||
|
||||
<para>
|
||||
This will be very convenient when defining packages.
|
||||
This is very convenient when defining packages, which tend to be recursive attribute sets.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>If expression</title>
|
||||
<title>If expressions</title>
|
||||
|
||||
<para>
|
||||
Expressions, not statements.
|
||||
These are expressions, not statements.
|
||||
</para>
|
||||
|
||||
<screen><xi:include href="./04/if.txt" parse="text" /></screen>
|
||||
|
||||
<para>
|
||||
You can't have only the "then" branch, you must specify also the "else"
|
||||
You can't have only the <literal>then</literal> branch, you must specify also the <literal>else</literal>
|
||||
branch, because an expression must have a value in all cases.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Let expression</title>
|
||||
<title>Let expressions</title>
|
||||
|
||||
<para>
|
||||
This kind of expression is used to define local variables to inner
|
||||
This kind of expression is used to define local variables for inner
|
||||
expressions.
|
||||
</para>
|
||||
|
||||
<screen><xi:include href="./04/let-basic.txt" parse="text" /></screen>
|
||||
|
||||
<para>
|
||||
The syntax is: first assign variables, then "in" expression. The overall
|
||||
result will be the final expression after "in".
|
||||
The syntax is: first assign variables, then <literal>in</literal>, then an expression which can
|
||||
use the defined variables. The value of the whole <literal>let</literal> expression will be
|
||||
the value of the expression after the <literal>in</literal>.
|
||||
</para>
|
||||
|
||||
<screen><xi:include href="./04/let-multiple.txt" parse="text" /></screen>
|
||||
|
||||
<para>
|
||||
Let's write two let expressions, one inside the other:
|
||||
Let's write two <literal>let</literal> expressions, one inside the other:
|
||||
</para>
|
||||
|
||||
<screen><xi:include href="./04/let-nested.txt" parse="text" /></screen>
|
||||
|
||||
<para>
|
||||
With let you cannot assign twice to the same variable. You can however
|
||||
With <literal>let</literal> you cannot assign twice to the same variable. Howver, you can
|
||||
shadow outer variables:
|
||||
</para>
|
||||
|
||||
<screen><xi:include href="./04/let-multiple-assign.txt" parse="text" /></screen>
|
||||
|
||||
<para>
|
||||
You cannot refer to variables in a let expression outside of it:
|
||||
You cannot refer to variables in a <literal>let</literal> expression outside of it:
|
||||
</para>
|
||||
|
||||
<screen><xi:include href="./04/let-scope.txt" parse="text" /></screen>
|
||||
|
||||
<para>
|
||||
You can refer to variables in the let expression when assigning variables
|
||||
like with recursive sets:
|
||||
You can refer to variables in the <literal>let</literal> expression when assigning variables,
|
||||
like with recursive attribute sets:
|
||||
</para>
|
||||
|
||||
<screen><xi:include href="./04/let-reference.txt" parse="text" /></screen>
|
||||
|
||||
<para>
|
||||
So beware when you want to refer to a variable from the outer scope, but
|
||||
it's being defined in the current let expression. Same applies to
|
||||
recursive sets.
|
||||
it's also defined in the current let expression. The same applies to
|
||||
recursive attribute sets.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
|
@ -317,20 +316,20 @@
|
|||
<title>With expression</title>
|
||||
|
||||
<para>
|
||||
This kind of expression is something you hardly see in other languages.
|
||||
Think of it like a more granular "using" of C++, or "from module import
|
||||
*" from Python. You decide per-expression when to include symbols into
|
||||
the scope.
|
||||
This kind of expression is something you rarely see in other languages.
|
||||
You can think of it like a more granular version of <literal>using</literal>
|
||||
from C++, or <literal>from module import *</literal> from Python. You decide
|
||||
per-expression when to include symbols into the scope.
|
||||
</para>
|
||||
|
||||
<screen><xi:include href="./04/with-basic.txt" parse="text" /></screen>
|
||||
|
||||
<para>
|
||||
That's it, it takes a set and includes symbols in the scope of the inner
|
||||
expression. Of course, only valid identifiers from the set keys will be
|
||||
included. If a symbol exists in the outer scope and also in the "with"
|
||||
scope, it will <emphasis role="bold">not</emphasis> be shadowed.
|
||||
You can however still refer to the set:
|
||||
That's it, it takes an attribute set and includes symbols from it in the scope of the inner
|
||||
expression. Of course, only valid identifiers from the keys of the set will be
|
||||
included. If a symbol exists in the outer scope and would also be introduced by
|
||||
the <literal>with</literal>, it will <emphasis>not</emphasis> be shadowed.
|
||||
You can however still refer to the attribute set:
|
||||
</para>
|
||||
|
||||
<screen><xi:include href="./04/with-scope.txt" parse="text" /></screen>
|
||||
|
@ -347,9 +346,9 @@
|
|||
<screen><xi:include href="./04/lazy.txt" parse="text" /></screen>
|
||||
|
||||
<para>
|
||||
Since "a" is not needed, there's no error about division by zero, because
|
||||
Since <literal>a</literal> is not needed, there's no error about division by zero, because
|
||||
the expression is not in need to be evaluated. That's why we can have all
|
||||
the packages defined here, yet access to specific packages very fast.
|
||||
the packages defined on demand, yet have access to specific packages very quickly.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
|
|
Loading…
Reference in a new issue