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… &amp;| 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)

  • pranaless@beehaw.org
    link
    fedilink
    arrow-up
    3
    ·
    1 year ago

    Try builtins.deepSeq: something like builtins.trace (builtins.deepSeq some-list some-list) false

    According to the manual, it evaluates its first argument deeply and returns the second.

  • ck_
    link
    fedilink
    arrow-up
    2
    ·
    edit-2
    1 year ago

    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>

    • gomp@lemmy.mlOP
      link
      fedilink
      arrow-up
      1
      ·
      edit-2
      1 year ago

      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 (from builtins.toJSON).</code>

      • ck_
        link
        fedilink
        arrow-up
        2
        ·
        1 year ago

        For simple things like this, I usually just use the REPL to prototype the function