3

I was trying to write some code using the Int32 library, but I hit a type error:

let x : int = 7;
Int32.abs(x)

This has type:
  int
But somewhere wanted:
  int32

I was a bit surprised by this, because in other languages int is just an alias for int32.

My questions are:

  • What are the integer types available in Reason ML?
  • What are the guidelines for using them?
  • Is there a module for each? (I noticed there is Int32.abs but not Int.abs, for example)
glennsl
  • 28,186
  • 12
  • 57
  • 75
sdgfsdh
  • 33,689
  • 26
  • 132
  • 245

1 Answers1

8

Here's a comparison of the various integer data types available, their type, associated module and literal syntax:

let int       : int       = Pervasives.abs(42);
let int32     : int32     = Int32.abs(42l);
let int64     : int64     = Int64.abs(42L);
let nativeint : nativeint = Nativeint.abs(42n);

Note that Pervasives is opened automatically, so you therefore do not need to have its functions qualified like above.

ìnt is natively 31-bit on 32-bit platforms and 63-bit on 64-bit platforms, and the type you'd use unless you need the exact arithmetic semantics provided by int32, int64 or nativeint. In32, Int64, and Nativeint all contain this (or a similar) note:

Performance notice: values of type int32 occupy more memory space than values of type int, and arithmetic operations on int32 are generally slower than those on int. Use int32 only when the application requires exact 32-bit arithmetic.

I hope that answers your questions.

Edit: When using BuckleScript to compile to JavaScript, which is quite common with Reason, the semantics are slightly different:

  • int32 and int64 behave the same
  • int behaves like int32
  • nativeint is mostly treated like float, with a few exceptions to be more integer-like.

Source: https://bucklescript.github.io/docs/en/difference-from-native-ocaml.html#integers

glennsl
  • 28,186
  • 12
  • 57
  • 75
  • How can 30-bit integers (which would appear to need custom handling on most CPUs) be faster than 32-bit integers? – Bergi Feb 17 '18 at 11:29
  • 2
    Correction: the default `int` type has 31 bits on 32 bit platforms and 63 bits on 64 bit platforms. The missing bit is the tagging bit needed for the GC, which enables an unboxed representation. – Andreas Rossberg Feb 17 '18 at 11:30
  • Indeed, I think you're right and I've updated the answer. Thanks! I got the 30-bit number from "OCaml for the Skeptical", which I apparently shouldn't trust, but can find no information about this in the manual. – glennsl Feb 17 '18 at 11:40
  • @Bergi I think this answers your question (at least much better than I can): https://stackoverflow.com/a/3774467 – glennsl Feb 17 '18 at 11:43
  • @glennsl Ah, thanks a lot for the link. I had kinda expected that in a statically typed language you wouldn't need type tags on primitives, but it seems *O*caml is more dynamic than I know. – Bergi Feb 17 '18 at 12:11
  • 3
    @Bergi, nothing to do with being dynamic but with having a so-called *uniform representation* for all values as single words. That is important to implement parametric polymorphism efficiently, where the type is not fixed. – Andreas Rossberg Feb 17 '18 at 12:48
  • @AndreasRossberg "the type is not fixed" is what I meant by "dynamic" :-) I just had assumed that parametric polymorphism was usually compiled statically into different specialisations. – Bergi Feb 17 '18 at 15:03
  • 1
    @Bergi, I see, but "dynamic" usually means something different in this context, e.g. that actual behaviour can observably depend on what type you get, whereas here the representation is just an implementation detail. Static specialisation only works when you give up on first-class polymorphism and on modular compilation, see C++. – Andreas Rossberg Feb 17 '18 at 17:22