How to gracefully deal with missing attributes

This righfully gives an error ({ a = 2; }.b): error: attribute 'b' missing, at (string):1:19.

Is there a way to catch these, so that my function may continue trying whether an attribute exists?

This also fails: builtins.tryEval ({ a = 2; }.b) with the same error.

Context of this problem, I am comparing versions of packages between an overlayed attribute set and the same attribute set without the overlay. As the overlay may add new packages, they are not necessarily existing in the base attribute set.

3 Likes

You can use ? to query the presence of a key, and or to provide a default value should the key be missing. The following assertions are true:

assert ({ a = 2; } ? b) == false;
assert ({ a = 2; }.b or 5) == 5;

See Introduction for reference

4 Likes

How about this solution:

let 
 attr = { a=2; }; 
in if builtins.hasAttr "b" attr 
  then attr.b 
  else false
3 Likes

OMG I should have been able to figure this out :smiley: Thank you, I do use ? to provide defaults, and I did not think about it in that case! I did not know about or. I also did not know about builtins.hasAttr!

Thank you I have now 3 ways to solve this problem \o/

1 Like

I tend to see the ? used for default values in attr sets arguments to functions as a bad coincidence (or unfortunate reuse) of operators, as that ? is closer to the or operator.

1 Like