How to merge two lists into an attribute set?

Hi,

I am fiddling with Stylix and am trying to avoid code repetition so I can more easily tweak a custom style. Stylix takes code like this:

stylix.base16Scheme = {
  base00 = "aaccbb";
  base01 = "ff00cc";
  . . .
}

I am trying to generate such an attribute set from a list or colours, by combining it with a list of attribute names (with map). Each step separately works ok (using map, listToAttrs and nameValuePair) but I cannot get the lists to combine the way that is needed.

Could someone shed some light. or point in the right direction?

If I’m not mistaken, I believe this is what you’re looking for:

# test.nix
let
  pkgs = import <nixpkgs> { };
  inherit (pkgs) lib;

  stylixNames = [
    "base00"
    "base01"
  ];
  colors = [
    "aaccbb"
    "ff00cc"
  ];

  mkColors =
    stylixNames: colors:
    lib.listToAttrs (lib.zipListsWith (name: value: { inherit name value; }) stylixNames colors);
in
mkColors stylixNames colors
$ nix-instantiate --eval --strict test.nix
{ base00 = "aaccbb"; base01 = "ff00cc"; }

Breakdown

First, we use lib.zipListsWith to combine the two lists in the form of { name = "..."; value = "..."; }:

[ { name = "base00"; value = "aaccbb"; } { name = "base01"; value = "ff00cc"; } ]

PS: inherit name value; is just a short way to say name = name; value = value;

Next, we pass the result to lib.listToAttrs, which takes a list of { name = "..."; value = "..."; } attributes as input and gives us the combined attribute set as output:

{ base00 = "aaccbb"; base01 = "ff00cc"; }
1 Like

Thank you very much! Ziplist was indeed what I was looking for. And what a great example of how to approach this: a separate file in combination with entr definitely beats goofing around in nix repl. So also thank you for showing how to get better in nix!

I took the liberty to expand on your answer a bit:

# test.nix
let
  pkgs = import <nixpkgs> { };
  inherit (pkgs) lib;

  hex = "0123456789ABCDEF";
  colors = [
    "aaccbb"
    "ff00cc"
  ];

  mkColors =
    colors:
      lib.listToAttrs (lib.zipListsWith (name: value: { inherit name value; })
        (lib.lists.imap0(i: v: "base0${builtins.substring i 1 hex}") colors) colors);
in
  mkColors colors

The syntax of nix still takes a lot of getting used to :wink:

1 Like

Here are a few more lib functions you might like to be acquainted with:

mkColors =
  colors:
  lib.pipe colors [
    (lib.imap0 (i: value: {
      name = "base${lib.fixedWidthString 2 "0" (lib.toHexString i)}";
      inherit value;
    }))
    lib.listToAttrs
  ];
2 Likes

Nice, thank you! So much to learn :smiley: