On 2012-14-09 20:31, Eric Sorenson wrote:
> Hi, there's an issue that came up recently in the 3.0RCs -- Big thanks to Erik Dal�n for reporting it in #16221 -- that involves a behaviour change to part of the DSL. In a nutshell, this code:
>
> define foobar ($param='Hello world') {
> notice($param)
> }
> foobar { 'test': param => undef }
>
> in 2.7, causes 'Hello world' in the notice. In 3.x, it's nothing. As I said in the bug, this seems more correct to me -- I've overriden the default with an explicit 'undef', taking off the default. The same thing goes for invoking parameterised classes with undef arguments, which is perhaps more ambiguous (example from matthaus):
>
> class toplevel (
> $maybe = false,
> $optional = undef ) {
> if ($maybe) {
> class { toplevel::secondlevel: optional => undef }
> }
> }
>
> In order to make use of the default for the `optional` parameter in toplevel::secondlevel, you'd now need to either test in `toplevel` whether `$optional` was passed into it, or have toplevel::secondlevel use an `$optional_real` value inside it, similar to what's commonly done to append to defaults that are array values.
>
> The closest thing to documentation around this suggests the new behaviour is what's intended <
http://docs.puppetlabs.com/puppet/2.7/reference/lang_classes.html#overriding-resource-attributes>:
>
> You can remove an attribute�s previous value without setting a new one by overriding it with the special value undef:
>
> class base::freebsd inherits base::unix {
> File['/etc/passwd'] {
> group => undef,
> }
> }
>
> So, I'm trying to determine whether this is a widespread pattern or an edge-case. Do you expect 'param=>undef' to be the same as not specifying param at all, or for the receiver to "see" the undef?
>
> Eric Sorenson -
eric.s...@puppetlabs.com
> PuppetConf'12 - 27-28 Sep in SF -
http://bit.ly/pcsig12
>
When we discussed this earlier, I also felt that the new behavior was
correct; settings something to undef erases the value, and if you want
the default, simply do not set the value.
However, seeing the examples, and thinking about it - if the change is
accepted it means it will be difficult to parameterize certain things -
what if there are many optional settings and some intermediary logic
takes a mix of parameters and needs to pass those on? Without the
ability to "end up with the default", but still enable passing a value,
there would need to be many different permutations selected with if
statements - and that would not be pretty. Alternatively, have the same
literal default values (which is not good as they would have to be kept
in sync).
Ideally, for this situation, using a literal 'default' would make the
code less confusing. I.e using the first example:
define foobar ($param='Hello world') {
notice($param)
}
foobar { 'test': param => default }
If this is implemented, it is possible to: set a new value, erase the
value, or use the default value if one is present.
... this is however a bigger thing to implement. Meanwhile, it may be
better to keep the somewhat mysterious behavior in 2.7.
Still feel that the behavior "undef erases the value" is a less
surprising result.
Regards
- henrik