4

The Nim Tutorial page states:

Lossless Automatic type conversion is performed in expressions where different kinds of integer types are used.

So, I thought that creating an int in the range of a uint8 would allow me to pass it to procs expecingt an uint8.

However, the following code raises the annotated errors:

import random

proc show(x: uint8) {.discardable.} = echo x

let a: int = 255
show(a)  # type mismatch: got (int) but expected one of proc show(x: uint8)

let b: uint8 = random(256)  # type mismatch: got (int) but expected 'uint8'
show(b)

I am very confused by the first one, which is telling me it expected a procinstead of an int. The second one is clearer, but I expected an autoconversion at this point, since random generates an int in the uint8 range (0..256) (documentation).

Is there a way to convert int to uint8?

GeckStar
  • 1,136
  • 1
  • 14
  • 22
  • 1
    You can convert `int` to `uint8` manually: `show(uint8(a))`, `let b = uint8(random(256))`. But this issue should probably be reported to Nim bug tracker. – uran Jun 05 '17 at 11:17
  • So it's the expected behaviour and I have to cast it like user uran said? If yes, then what is the automatic type conversion mentioned in the tutorial? – GeckStar Jun 05 '17 at 14:32
  • 1
    Sorry I removed my comment willing to elaborate more. I think the manual is referring to converting a value of a type which is a subset of another type. For example, conversion of uint8 to uint16. If you have a variable and would like to convert it to a type it may not fit into, you have to convert explicitly, yes. But if you have a constant which the compiler knows fits into the required type, then the conversion is automatic. – endragor Jun 05 '17 at 14:37
  • "an int in the range of a uint8"--type checks are done at compile time, when the value isn't known.The whole point of lossless automatic type conversion is that the source type is guaranteed to fit into the target type regardless of the value, so it's safe. Storing `int` into `uint8` is not safe, so you have to say you want to do that with a cast. No cast is needed for, say, storing an `int8` into an `int`. As for the error message, you're being too literal -- it shows you the signature, rather than just 'uint8' -- more info rather than less. BTW, 256 won't fit in `uint8`, so you have a bug. – Jim Balter May 04 '20 at 23:15

1 Answers1

6

The random proc is defined to return an int. The fact that the max value is 256 in this example is not encoded in the type system (it could have been if random was taking static[int] as an argument).

"lossless conversion" means that a value of a smaller integer type can be converted to a value of a larger integer type (e.g. from int8 to int32). In the examples here, you are trying to perform a conversion in the other direction. You can get around the errors by making the conversions explicit:

let a = uint8(rand(256))
show a
# or
let b = rand(256)
show uint32(b)

p.p. you don't need to add the discardable pragma to procs which don't return values.

zah
  • 5,314
  • 1
  • 34
  • 31