I’m trying to debug a module I’m writing with builtins.trace
, but it’s being more complicated than I anticipated.
Let’s say I have a module:
{ config, lib, pkgs, modulesPath, ... }:
{
config =
let
some-list = lib.attrsets.mapAttrsToList (n: v: {
some-attr = "${n} ${v}";
}) { n1 = "v1"; n2 = "v2"; };
in {
users.mutableUsers = builtins.trace (some-list) false;
};
}
This will print
trace: [ <code> <code> ]
because builtins.trace
(for whatever reason?) evaluates its first argument only shallowly.
Changing the trace
expression to:
builtins.trace (builtins.toJSON some-list) false;
helps a lot, but as soon as one tries to print a long list or a structure with some complexity the output is completely unreadable, and it’s not like it can easily be piped into jq
(I mean… &| grep ^trace: | sed 's/trace: //' | jq
works*, but there must be a “better” way?)
(*) in fish shell, IDK about bash</code></code>
edit: It’s not like I specifically want JSON output: any format will do (ideally, nix would be nice)
Try
builtins.deepSeq
: something likebuiltins.trace (builtins.deepSeq some-list some-list) false
According to the manual, it evaluates its first argument deeply and returns the second.
The nix language is lazy by definition. In your example, the code on your let block is never fully evaluated (executed), because it is never needed. Hence,
[ <code> <code> ]
is the only possible outcome.</code></code>
I figured that much :) I was wondering about the “best” (recommended? idiomatic?) way to get some decent/usable output instead of
<code>
or unformatted JSON (frombuiltins.toJSON
).</code>For simple things like this, I usually just use the REPL to prototype the function