On Friday, October 31, 2014 8:22:36 PM UTC-5, henrik lindberg wrote:

[...]

Yet again someone was bit by the automatic String to Numeric conversion 
> that is in Puppet (and also in --parser future). 
>
>

I must confess to a certain dark amusement at Puppet struggling with its 
weak-typing legacy and moving more and more in the direction of strong 
typing.  Not that I am in any way happy about these difficulties, but I'm 
an old-school dinosaur, and weak typing has never seemed like such a great 
idea to me.

[...]

We fixed PUP-3602 by not converting strings that are floating point 0 
> with exponential part and we also do not convert values that are 
> floating point infinite in Ruby (e.g. 4e999 and such). This is a crutch 
> though, and it is only a matter of time until someone stumbles over the 
> next SURPRISE ! 
>
>

Indeed so.  If you rely on heuristics to choose behavior then you have to 
accept that sometimes the wrong behavior will be chosen.  In this case, it 
is purely a guess that a string starting with "0e[digit]" is not meant to 
be interpreted as a number.

 

> The best cure is naturally to never do String to numeric conversion.



What about numeric to string conversion?  I guess Puppet doesn't do that 
automatically now, so maybe this isn't the time to start, but that *is* an 
alternative approach to mixed string/number comparison.

 

> And 
> we wonder what people feel about that. Should we go for this in Puppet 
> 4.0.0 (and have a 3.7.4 release as the last of the 3x series where this 
> behavior is implemented when using --parser future). 
>
>

I think avoiding automatic string to numeric conversion is consistent with 
forbidding bare strings starting with a digit.  It would be a lot better, 
though, if in the context of the manifest it were clearer which expressions 
are strings and which are numeric.  That's no problem for literals, of 
course, but none of this is interesting in the case where all the values 
involved are literals.  I (think I) understand that with the P4 parser and 
evaluator it will be possible to declare types specifically enough to 
address that issue, but it is also my understanding that expressions won't 
*necessarily* have formal types specific enough for that.

It is highly desirable to give manifest authors sufficient control over 
conversions to avoid unwanted ones, but it is not altogether clear to me 
whether the best approach is to nix all automatic string-to-number 
conversions.  A lot of existing manifests rely on such conversions, since 
they used to be the only alternative.  P4 is at liberty to break backward 
compatibility, but maybe a little less breakage would be wiser?



> There has also been a number of other suggestions how to fix this, that 
> are less appealing, and for the sake of not having to waste anyone's 
> time, here they are, with the reasons why they are not so appealing. 
>
> * Only convert if LHS is a Number. This makes the order of the 
> comparison matter and then ($x == $y) != ($y == $x) which is really bad. 
>
>

Yuck.

 

> * Add === operator to compare both type and value. This is a slippery 
> slope since we probably want Integer and Float to compare equal - say 
> 0.0 and 0. It adds yet another operator, and we have to decide what 
> case, selector and in should use since there is no way to specify if one 
> or the other should be used. 
>
>

I agree that as proposed, the '===' operator would be troublesome.  There 
is always the alternative, though, of keeping '==' as it is, and making 
'===' simply perform a comparison without string/number conversion.  I 
think 'case', selector, and 'in' behavior are collectively a red herring, 
though: if '===' were adopted in any form then 'case', selector, and 'in' 
behavior would still be whatever is specified for them, whether that's 
their current behavior or a variant one based on '==='.  There is no 
requirement that that behavior be selectable between different senses of 
equality.

I'm not necessarily advocating that solution, but I think it's appropriate 
to take a careful, unbiased look at all the alternatives.  I'm not certain 
they're all on the table, yet.  For example, how about this:

* The value of an expression may be converted to a different type only to 
the extent that the target type is consistent with the expression's *formal* 
type.

For example, if a class parameter is declared to be type String then it's 
value cannot be automatically converted to Numeric or any of its subtypes, 
but if it is type Scalar or Object and happens to *contain* a string, then 
the string value *can* be automatically converted to a number (a Float, for 
instance).  That could yield backward compatibility for existing manifests 
that do not declare types, while still allowing authors to control the 
allowed conversions.

 

> Instead, since we already have sprintf for value to string conversion, 
> and there is a scanf in Ruby which does the conversion the other way, we 
> can simply add that function to core puppet for value conversion. 
>
> We could also add to_number(s), or to_number(s, format_string). 
> When doing that though, we risk ending up with a plethora of to_xxx 
> functions, and we could instead offer one more universal 
> convert_to(Type, value, options) function e.g. 
>
> # best effort, or fail 
> convert_to(Number, value) 
>
> # only if it is an integer, or fail 
> convert_to(Integer, value, {base => 10}) 
>
> # convert integer to hex string with some extra text (the sprintf way) 
> convert_to(String, value, {format => "Hex %x"}) 
>
> # convert to array of string (give full control over all 
> # nested conversions. 
> # 
> convert_to(Array[String], value, { 
>    Integer => { format => "0x%x" }, 
>    Float   => { format => "%#.4G" }}) 
>
> # etc. 
>
>

I do think there need to be type conversion facilities in some form.  I'm 
inclined to like the idea of a generic facility based on types, as opposed 
to a host of specific conversion functions.

 

> So - "Boldly break all the (s)t(r)hings"? 
>
>

I don't know how costly it would be to implement, but I rather like the 
combination of control, flexibility, and backward compatibility that could 
be afforded by using formal types to limit the scope of allowed 
conversions, instead of altogether forbidding (some) automatic conversions.


John

-- 
You received this message because you are subscribed to the Google Groups 
"Puppet Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to puppet-dev+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/puppet-dev/7196dd2f-5b30-4f6e-8655-b6bdd5e518fe%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to