# Making Constructor set fields with Default

Sometimes, we'd like to make a template template
that behave in different ways for different fields.
For example, let's suppose that we want our `Constructor` template
to be able to set fields to their default values,
and not take them as arguments.

We can do this with an explicit conditional for each field:
```rust
# use derive_deftly::define_derive_deftly;
define_derive_deftly! {
   Constructor:

   impl<$tgens> $ttype where $twheres {
     $tvis fn
        // This is the function name, same as before.
        ${if tmeta(constructor(newfn)) {
            ${tmeta(constructor(newfn)) as ident}
          } else {
            new
          }
        }
     (
       // These are the function arguments:
       $(
          ${when not(fmeta(constructor(default))) } // (1)
          $fname: $ftype ,
        )
     ) -> Self {
          Self {
              $( $fname:
                  ${if fmeta(constructor(default)) {
                    ::std::default::Default::default() // (2)
                  } else { $fname } }
                 , )
          }
      }
   }
}

use derive_deftly::Deftly;
#[derive(Deftly)]
#[derive_deftly(Constructor)]
struct Foo {
    #[deftly(constructor(default))]
    s: Vec<String>,
    n: u32,
}
```

Here we're using a new construct:
[`$when`][x:when].
It's only valid inside a loop like `$( ... )` or `${for ...}`.
It causes the output of the loop to be suppressed
whenever the condition is not true.

The condition in this cases is `not(fmeta(constructor(default)))`.
(See `// (1)`.)
You've seen `fmeta` before;
it's true when a given attribute is present on the current field.
The [`not`][c:not] condition
is just how we express negation.
All together, this `$when` keyword causes each field
that has `#[deftly(Constructor(default))]` applied to it
to be omitted from the list of arguments
to the `new()` function.

> Note at `// (2)` that we're using `::std::default::Default::default()`,
> rather than calling `Default::default()` unconditionally.
> Remember, macros expand at the position where they are invoked,
> and it's possible that we'll be invoked in a module
> that has been built [without the standard prelude][no_implicit_prelude].

<!-- TODO: Write a further section about hardening macros against weird
      environments, then link to it here. -->

Besides `$not`,
you can use other boolean operators in conditions too:
there is an
[`any(...)`][c:any]
that is true
whenever at least one of its arguments is true,
and an
[`all(...)`][c:all]
that is true
when _all_ of its arguments are true.

[c:all]: https://docs.rs/derive-deftly/latest/derive_deftly/doc_reference/index.html#c:all
[c:any]: https://docs.rs/derive-deftly/latest/derive_deftly/doc_reference/index.html#c:any
[c:not]: https://docs.rs/derive-deftly/latest/derive_deftly/doc_reference/index.html#c:not
[x:when]: https://docs.rs/derive-deftly/latest/derive_deftly/doc_reference/index.html#x:when
[no_implicit_prelude]: https://doc.rust-lang.org/reference/names/preludes.html#the-no_implicit_prelude-attribute
