Stdlib and use of Base, Core etc

Ok guys, new here and new to ocaml.
I’m using linux and 4.08.1 with the jane street core and tring to follow RWO.

So, question.

I use print_int and receive depreciation warnings in utop and when compiling.
Use of Array.make also requires the use of prepending as in Stdlib.Array.make and Stdlib.print_int and these are just a few examples.

I’m sure I read somewhere that in haskell, we can import a lib ‘as’ something or alias it or something.

My question is, is it just my use of JS Core/Base etc that has over ridden the use of the aforementioned and it’s ok to call said functions by prepending Stdlib or is there a way I’m not aware of?

1 Like

There is no thing such as importing in OCaml (it is a notion of a build system), but you can alias a module, e.g.,

module X = Stdlib.Array

you can also open a module namespace to be able to use its definitions without a fully qualified name.

Base and deprecation warnings

So first of all, let me explain what is happening underneath the hood so that you can make your own assessments of the situation :slight_smile:

The Janestreet Base library is using a special script during the build time that collects all the definitions from the OCaml standard library and reexports them in the Base module with the deprecated annotation. Their motivation is simple - one shouldn’t mix two standard libraries.

Unfortunately, it is not immediately obvious what you should use since the deprecation warning is just saying that it should not be used with no alternatives provided. Moreover, sometimes there is even no alternative.

In our case, the alternative for the Stdlib’s I/O functions is provided by another Janestreet’s library called stdio, e.g.,

open Stdio 

let () = print_endline "Hello, world"

Now, print_endline comes from the Stdio module and it is now legit. Unfortunately, either by omission or by intention, the print_int function is not provided by this library. My suggestion, would be to use printf as a more universal and versatile tool for printing, e.g.,

open Stdio

let () = printf "6 x 9 = %d\n" 42

In general, if you still want to use a deprecated function, then you can use the [@@@warning] attribute to hush the warnings, e.g., you can just issue [@@@warning "-3"] in utop (or on toplevel of your program) and won’t see any more deprecation warnings. You can use those attributes on a more fine-granular manner and attach them to particular definitions, e.g., you can re-export print_int, e.g.,

let print_int = Stdlib.print_int [@@warning "-3"]

and then use print_int without any more warnings.

Concerning the Array.make, you shall use the Array.create function instead.

2 Likes

Thanks for the comprehensive reply. Most is clear and as you say, depreciation’s are being called without listed alternatives.

Now, regards Array.make, I did read a number of now older posts and blogs that ocaml used to call Array.create but this was depreciated some years ago in favour of Array.make.

I get # Stdlib.Array.make 10 ‘A’;;

  • : char array = [|A; A; A; A; A; A; A; A; A; A|]`

But strangely, this works…
let v = Array.make_matrix 4 3 0;;

val v : int array array = [|[|0; 0; 0|]; [|0; 0; 0|]; [|0; 0; 0|]; [|0; 0; 0|]|]

I’ll figure it out.

BTW: Array.create does work, thanks.

Array.create 10 ‘A’;;

  • : char array = [|A; A; A; A; A; A; A; A; A; A|]
    `

Well, yes, Stdlib.Array.create was deprecated in the OCaml Standard library in favor of Array.make long time ago (but create was never removed). Since that time, the OCaml community more or less adopted the create as the default name for the value constructor. (A good example, is Stdlib’s Array.make_float which is deprecated in favor of Array.create_float).

But all this confusion is about the OCaml Standard Library, not Janestreet’s suit of libraries, which are much more consistent. In fact, they will even break code in favor of consistency. And this brings us back to the original problem - you’re using both libraries and this is a bad idea since it increases you cognition burden - you have to learn twice as more libraries and twice as more conventions (quite different conventions).

So my suggestion, stick to Janestreet’s libraries and try to do things in their way. Whenever you get the warning that tells you that you accidentally picked the standard library, do not ignore it and try to find the alternative provided by the Base/Core/etc. If in doubt, don’t hesitate to ask. The documentation is scarce and oftentimes is outdated, but we are here to help :slight_smile:

Pro tip: use triple backticks to delimit your code.

1 Like

I don’t know about Core, but create vs. make does have a consistent meaning in the Stdlib as far as I know: create creates an uninitialised value, whereas make creates one and initialises it. That’s what Array.{make, create_float} do, as long as String.{make, create}, Bigarray.*.create and so on.

3 Likes

Yep, I was trying to recall the difference yesterday, but my memory failed me :slight_smile: Yes, indeed that was the reason for having two different names, thanks for pointing it.

Concerning Janestreet libraries, I can’t observe this kind of convention, most of the time they use create, even for Bytes.create and String.create. There is only one inconsistent exception to this rule, the Array.make_matrix function (which is the stdlib’s Array.make_matrix) and no Array.create_matrix provided at all (so it is impossible to create an uninitialized array of floats.

2 Likes