Raku / nqp

NQP
Other
336 stars 131 forks source link

`nqp::isnum` returns 0 for everything Rakudo considers a `Num` #824

Closed ab5tract closed 3 months ago

ab5tract commented 3 months ago

nqp::isnum appears to be pretty broken, at least from the use case of an (ahem, the) HLL:

> r 'use nqp; my Num $f = 11.1e0; dd :istype(nqp::istype($f, Num)), :isnum(nqp::isnum($f))'
:isnum(0)
:istype(1)

> r 'use nqp; my num $f = 11.1e0; dd :istype(nqp::istype($f, Num)), :isnum(nqp::isnum($f))'
:isnum(0)
:istype(1)

> r 'use nqp; my num32 $f = 11.1e0; dd :istype(nqp::istype($f, Num)), :isnum(nqp::isnum($f))'
:isnum(0)
:istype(1)

> r 'use nqp; my num64 $f = 11.1e0; dd :istype(nqp::istype($f, Num)), :isnum(nqp::isnum($f))'
:isnum(0)
:istype(1)
raiph commented 3 months ago

Nums aren't nums, so perhaps it makes sense that nqp::isnum returns 0 for Nums:

use nqp;

say nqp::isnum(Num); # 0
say nqp::isnum(num); # 1

That said:

multi qux (Num) { 'Num' }
multi qux (num) { 'num' }

my num $foo = 42e0;

say qux $foo; # num

say $foo.WHAT; # (Num)

say $foo.VAR.WHAT; # (NumLexRef)

my num \bar = $foo; # Type check failed in binding; expected num but got Num (42e0)
ab5tract commented 3 months ago

@raiph Other nqp operations that are documented as expecting num arguments happily accept the whole Num tower.

This is not ~sensible~ useful behavior in my opinion:

> r 'use nqp; dd :isnum(nqp::isnum(my num $n = 5e0))'
:isnum(0)

> r 'use nqp; dd :isnum(nqp::isnum(num))'
:isnum(1)

Whereas nqp::isnanorinf acts like this:

> r 'use nqp; dd :isinf(nqp::isnanorinf(my num $n = Inf))'
:isinf(1)

> r 'use nqp; dd :isinf(nqp::isnanorinf(my num64 $n = Inf))'
:isinf(1)

> r 'use nqp; dd :isinf(nqp::isnanorinf(my Num $n = Inf))'
:isinf(1)

You raise an interesting dynamic, but that is a bit beyond the scope of this issue IMO.

niner commented 3 months ago

This is working as intended. The is* nqp ops are all very strict and do REPR checks. NQP is our low level language and these ops by design don't do any magic to just DWIM. They are for when you really need to know whether something is a low level type (int, str, num). Other nqp ops are more forgiving because they may auto-unbox. Num for example has a num $!value attribute that is a box target, so unboxing will just return this contained low level num.