On Sat, 25 Jan 2020, ToddAndMargo via perl6-users wrote: > Hi All, > > Anyone have a workaround to my stolen uint's? > > > constant DWORD := uint32; > (uint32) > > > subset StrOrDword where Str | DWORD; > (StrOrDword) > > > sub x( StrOrDword $item ) { > * say "$item is a " ~ $item.^name; > * } > &x > > > x( "abc" ); > abc is a Str > > > x( 3 ); > Constraint type check failed in binding to parameter '$item'; expected > StrOrDword but got Int (3) > in sub x at <unknown file> line 1 > in block <unit> at <unknown file> line 1 > > > x( 3.UInt ); > Constraint type check failed in binding to parameter '$item'; expected > StrOrDword but got Int (3) > in sub x at <unknown file> line 1 > in block <unit> at <unknown file> line 1 >
Raku allows you to use native datatypes and to constrain variables to refuse anything but some kind of native data. But an uint32 is just 32 bits, no class and no methods attached. If nevertheless you call methods on native values, they will be boxed into objects that actually support methods to be called on themselves. Native integers, signed or not, are boxed into Int. With that in mind, re-read the documentation section about native dispatch [1]. Your sub x has no candidate that statically accepts a native integer. Since you use a subset type, the typecheck is deferred until runtime, but StrOrDword.ACCEPTS has no native integer candidate either, and at that point you lost already, as x(my uint32 $ = 3) would result in the 3 being auto-boxed to be able to check it against `Str | uint32` and because of the boxing, its type is now Int and the check fails. Consider: sub x(uint32 $item) { say "$item is a " ~ $item.^name } x(3); # works, `only` subs auto-unbox the Int literal x(my uint32 $ = 3); # works, a native integer is provided In both cases, "3 is a Int" will be printed, because the class name is obtained by calling a (meta-)method on $x, which triggers boxing to Int. There is no room for a class name in a 32 bits native integer. Now, if you change the signature to something subsetty/dynamic like sub x($item where uint32) both calls fail to dispatch, as explained above. On the other hand, this works because there is an explicit native integer candidate for the dynamic typecheck, so you don't get boxed: sub x($item where -> uint32 { True }) By the way, this has nothing to do with unsigned or signed integers, your signs are not stolen, your values are boxed. The uint32 type is simply not suitable to be typechecked against, as this quintessentially paradoxical line of code tells you: say (my uint32 $ = 3) ~~ uint32; # False Native data is second-class data in a language where everything is an object. If you want a workaround, eschew the subset and provide two candidates for your sub x: one for Str and one for uint32. How do you expect to handle something that may either be a Raku string object or a native integer in a single candidate anyway? Or drop the native integer altogether and use Int until you really need the native thing. Regards, Tobias [1] https://docs.raku.org/language/numerics#Native_dispatch -- "There's an old saying: Don't change anything... ever!" -- Mr. Monk