[Nix-dev] Attribute selection with default

Nicolas Pierron nicolas.b.pierron at gmail.com
Tue Oct 20 17:14:00 CEST 2009


On Thu, Sep 24, 2009 at 12:51, Eelco Dolstra <e.dolstra at tudelft.nl> wrote:
> Hi all,
>
> Currently there are many places in the Nixpkgs and NixOS expressions where we
> have to select a possibly missing attribute from a set, e.g.
>
>  attrByPath ["extraModules"] [] mainCfg
>
>  getConfig ["python" "db4Support"] true

set ? attr && set.attr

>
> Writing `attrByPath ["a" "b" "c"] default as' is rather verbose and ugly
> compared to selecting an attribute without a default, i.e. `as.a.b.c'.
>
> Since this is fairly common, how about some special syntax for supplying a
> default value to the "." selection operator?  I propose the optional "or"
> keyword following an attribute selection "x.<attrpath>".  E.g.

Arguments are in:
http://www.mail-archive.com/nix-dev@cs.uu.nl/msg02725.html

1/ The "or" operator:

* mainCfg.extraModules or []
* config.python.db4Support or true
* set.attr or false

scope of the default value,

* as.a.b.c or default
* (as.a).b.c or default
* (as.a.b).c or default

Cons:
- Feel like with miss a "and" operator.
- The scoping is not intuitive.
- " or false " can be miss-leading.

Pros:
- Small operator.

2/ The curly braces with question mark:

* mainCfg.{extraModules ? []}
* config.{python.db4Support ? true}
* set.{attr ? false}

scope of the default value,

* as.{a.b.c ? default}
* as.a.{b.c ? default}
* as.a.b.{c ? default}

This operator can be derived into other like:  a.(b.c :- d)  /  a.(b.c ?= d)

Cons:
- Can be interpreted as a function argument with a default value
(don't miss the leading ".")
- Large operator with its braces.
- Can be confused with the hasAttr operator "?".

Pros:
- Scoping is clear

3/ Merging proposals

* mainCfg.extraModules ?: []
* config.python.db4Support ?: true
* set.attr ?: false

scope of the default value,

* as.a.b.c ?: default
* (as.a.b.c ?: default) # equivalent to the previous one
* as.(a.b.c ?: default) # equivalent to the previous one
* as.a.(b.c ?: default)
* as.a.b.(c ?: default)

"?:" is used instead of "or" because "?" is used for testing if an
attribute exists and the common usage of the ternary operator in other
C like languages is "cond ? if-true : if-false" which would mean in
our case:

if-has ?: if-not

Cons:
- "?:" may lead to questions about "cond ? true : false".

Pros:
- small operator
- clear scoping rules

To avoid the "Cons", we can use "?!".  This operator can be named the
" has - not " operator.

-- 
Nicolas Pierron
http://www.linkedin.com/in/nicolasbpierron - http://nbp.name/
Andrew S. Tanenbaum - Never underestimate the bandwith of a wagon full of tapes.



More information about the nix-dev mailing list