Why do Hashtbl.find and Map.find take arguments in a different order?

In Hashtbl.find tbl key the table comes first and the key second. But in Map.Make(Ord).find key map the key comes first and the map second. Why the difference?

1 Like

OCaml is both a functional and imperative language, and I believe the difference you’re seeing is between the use of immutable and mutable data structures.

With the immutable Map you work in functional style and it is nice to be able to use the |> operator to chain modifications to the map. Operations that modify the Map return the updated data structure, and chaining works because the previous version of the Map is the last param.

With the mutable HashMap it is more conventional to pass the data structure as the first param. The map is updated in place and not returned. This also allows currying an operation on a map (Hashtbl.find tbl). I don’t know of another reason.

One thing I wonder about is why List.nth is an exception to the rule. It’s an immutable data structure, yet the list param is first.

Interesting, thanks!

I guess the usefulnes of |> for List.nth is limited since it doesn’t return another list, so you wouldn’t as often want to write lst |> List.nth n |> ...? And so maybe in that case the usefulness of currying takes over, so you can write (List.nth lst)?

There is another thread on this topic and apparently some others agree with me that List.nth is not quite right. What I don’t like is that it is inconsistent with other List functions that don’t return lists, like List.mem.

1 Like

Data-first functions also play well with extended indexing operators, which can be nice if you use a lot of hashtables or similar structures. (Not that you couldn’t also use them immutable structures like Map, but I’m not sure if that’s as appealing.)

Good point. Although I’m not sure indexing is less appealing with immutable structures.

No good reason. The standard library is very inconsistent in this respect. This is mostly due to historical reasons (changing the order would break a bunch of code). Putting the container argument last when dealing with immutable data structures encourages currying it, but that’s all, and in any case it is not done systematically either (eg Map.fold or List.fold_right).

Other standard libraries that were designed more recently (eg Core/Base) have gone for full consistency in always putting the main type first.

Cheers,
Nicolas

3 Likes

My understanding of folds is that the “left” or “right” naming is to indicate which order of arguments is used, and maps are implicitly “right” folds. ('a -> 'b t applies t to the left and 'a t -> 'b applies t to the right.) The order of arguments applied to fold f should also be consistent with the order that arguments are applied to f.

The “left” or “right” direction also happens to indicate the order that the elements inside the container are applied to f, which turns out to be the more important detail for most people.