Hi Rowan, Although I understand your concerns, I wouldn't consider them a roadblock for this feature. My rationale is that `is_numeric` has been with PHP for so long that I don't think we would ever be able to have a `numeric` type-hint that doesn't align with it, which imho means we either have it or we don't, a 3rd option where a possible type-hint that is inconsistent with the function seems worse than not having it. I fully agree with your concerns that it might not fully represent what the developer wants, but I would make a judgement call when using it the same way developers have to make a judgement call when using `is_numeric`. It might allow far more than you want, but there seems to be enough use-case that it fits where the downside is negligible or even insignificant. My point is that I don't look at the language validation to protect my code against unexpected values and I can setup validation to deal with that. What complicates things is that I want to avoid having a force-cast which is not safe for my usage because I want to preserve `null` while not having to disable strict_types.
On Tue, Jun 2, 2020 at 5:47 PM Rowan Tommins <rowan.coll...@gmail.com> wrote: > Hi Marco, > > On Tue, 2 Jun 2020 at 16:10, Deleu <deleu...@gmail.com> wrote: > > > > > The primary intent would be to safely pass around input that usually > comes > > from HTTP, CI or Database. Whenever interacting with these data > providers, > > string is a common format. `is_int` will not return true for integer > values > > that are string, instead we need to rely on `is_numeric`. > > > > > The problem with is_numeric() is that it uses an extremely broad definition > of "numeric", which is not often what you actually want - for instance, > is_numeric("-2.56E-90") returns true. > > The case I frequently see is much stricter: the variable should either be > an integer, or a string representation of an integer. Whenever this comes > up, I struggle for what the correct check actually is: > > * is_int($x) won't accept any strings > * is_numeric($x) will accept far too much > * an int type annotation with strict_types=0 is similar to is_numeric; in > strict_types=1 it's the same as is_int > * (int)$x will never give an error (meaning it's oddly easy to accidentally > _suppress_ errors by trying to make code run under strict_types=1) > * (int)$x != 0 is sometimes good enough, as long as zero is not a valid > value (if you use this when accepting Unix timestamps, for instance, Jan > 1st 1970 is going to be rejected!) > * ctype_digit( (string)$x ) is confusing to read (the cast is required to > accept actual integers, and the name is odd out of its intended context); > it will also reject any negative numbers, which may or may not be desirable > > The only suitable built-in function I'm aware of is filter_var, which has a > pretty horrible API: > > if ( filter_var($x, FILTER_VALIDATE_INT) !== false ) ... > > In the common case that you want to cast the variable to int on success (to > pass to a strictly typed function), you would need to do something like > this: > > $x = filter_var($x, FILTER_VALIDATE_INT); > if ( $x === false ) { > throw new TypeError; > } > > I would love to see the language have a built-in short-hand for that, in > the form of some kind of "strict cast", e.g.: > > $x = (int!)$x; > > or: > > $x = (strict int)$x; > > Once converted in that way, you could safely pass to a parameter marked int > in strict mode, so wouldn't need a new pseudo-type. > > > Regards, > -- > Rowan Tommins > [IMSoP] > -- Marco Aurélio Deleu