expressões Nix
Uma expressão Nix é como qualquer expressão de linguagem de programação: qualquer coisa que seja avaliada como um valor ou uma função. Um valor nesse caso também pode ser uma lista ou um conjunto. Como um módulo Nix (arquivo com extensão .nix
) pode conter qualquer expressão Nix, você esperaria que o arquivo de configuração NixOS ( /etc/nixos/configuration.nix
) contivesse uma única expressão Nix como seu conteúdo de arquivo.
O arquivo de configuração do NixOS contém uma expressão Nix do formulário:
{config, pkgs, ...}: { /* various configuration options */ }
Se você olhar de perto, verá que é uma função , porque as funções seguem o formulário pattern: form
. Você também pode ver que é uma função que aceita um conjunto e retorna um conjunto. Por exemplo, se você tiver uma função f = {x, y}: {a = x + y;}
, poderá chamá-la como f {x=1; y=2;}
e recuperar um conjunto {a=3;}
.
Isso significa que quando você chama nixos-rebuild switch
, algo chama a função dentro do arquivo de configuração NixOS com o conjunto que deve conter os atributos config
e pkgs
.
importações
Seguindo o exemplo de ./hardware-configuration.nix
, a maneira simples de extrair a lista de pacotes em um módulo separado packages.nix
é apenas extrair a opção environment.systemPackages
e colocar a opção ./packages.nix
into imports
. Seu /etc/nixos/configuration.nix
ficaria assim:
{ config, ... }:
{
imports =
[ # Include the results of the hardware scan.
./hardware-configuration.nix
# Include the package list.
./packages.nix
];
# SOME STUFF
# SOME STUFF
}
Seu /etc/nixos/packages.nix
seria semelhante:
{ pkgs, ... }:
{
environment.systemPackages = with pkgs; [ emacs gitFull ];
}
Como isso funciona? Quando você executa nixos-rebuild switch
, o processo que avalia expressões Nix e decide instalar pacotes e assim por diante chama configuration.nix
com um conjunto de atributos, alguns dos quais são config
e pkgs
.
Ele encontra o atributo imports
dentro do conjunto retornado, portanto, ele avalia cada expressão Nix nos módulos que imports
contém com os mesmos argumentos ( config
, pkgs
, etc).
Você deve ter pkgs
como um argumento (ou, tecnicamente falando, um atributo de um conjunto, que em si é um argumento) de uma função em packages.nix
, porque, da perspectiva da linguagem Nix, o processo pode ou pode não chamar a função com o conjunto que contém pkgs
. Se não, a que atributo você se referiria ao executar with pkgs
?
Você também deve ter reticências, porque a função pode ser chamada com outros atributos, não apenas pkgs
.
Por que não há pkgs
em configuration.nix
? Você pode tê-lo, mas se você não se referir a ele em nenhum lugar do arquivo, você pode omiti-lo com segurança, já que as reticências o incluiriam de qualquer maneira.
Atualizando um atributo chamando uma função externa
Outra maneira é apenas fazer uma função que retorna um conjunto com algum atributo, e o valor desse atributo que você colocaria dentro de environment.systemPackages
. Este é seu configuration.nix
:
{ config, pkgs, ... }:
{
imports =
[ # Include the results of the hardware scan.
./hardware-configuration.nix
];
# SOME STUFF
environment.systemPackages = import ./packages.nix pkgs;
# SOME STUFF
}
Seu packages.nix
:
pkgs: with pkgs; [ emacs gitFull ]
import ./packages.nix pkgs
significa: carregue e retorne a expressão Nix em ./packages.nix
e, como é uma função, chame-a com um argumento pkgs
. with pkgs; [ emacs gitFull ]
é um com expressão , ele traz o escopo da expressão antes do ponto-e-vírgula para a expressão após o ponto-e-vírgula. Sem isso, seria [ pkgs.emacs pkgs.gitFull ]
.