Why does Hash.size return Int32 and not UInt32?

I don’t reason about runtime part for now , but about compile-time part:
It is easy to modify example so it is still needed to iterate array manualy:

i = arr.size-1
while i >= 0
  yield(arr[i]) #block can add elements to array 
  i-=some_fun(arr[i]) # we skip some elements depending on  the value of processed element.
end

if I understand correctly it would have to be rewritten to something like

return if arr.size == 0
i = UInt32.new(arr.size)-1
loop do
  yield(arr[i])
  v = some_fun(arr[i]) 
  break if v > i
  i -= v
end

That would be one approach, albeit rather cryptic. Nothing should stop you from having a traditional Integer value of your preferred size and signedness to be casted from an Array#size result. The idea is that if you need math, you use types that support math, and a size should be comparable, but a) immutable and b) not easily operated upon.

In C++ you have #size : UInt32 and #ssize : Int32

In Crystal we could have #size : Int32 and #usize : UInt32.

It could be great and everyones will be happy :D

IMHO I prefer unsigned values for length.

2 Likes

In that case implementation will take few lines and can even live in shard.

Shard can even expose opaque Size type for those who don’t want to be able to do math with it.

2 Likes

One of the goals was to reduce the number of unions generated when mixing types of Ints. That is the reason to populate more with Int32 rather than UInt32 even when the value will indicate a non negative quantity.

At the end of the day both have a range of valid values. Whether it is 0 or some far away negative number the compiler can’t do much in compile time to detect when you are reaching to the limits.

Both types can be used today with overflow as an opt-in, eventually overflow will become the default.

I tend to use UInt more in binary related code as others. All maths I try to use it with signed versions since calculation might to weird things (like * -1).

The problematic line is when you want huge containers that will hold a Int64 amount instead of Int32. The std lib is built with Int32 in mind.