OCaml function name as string
Asked Answered
P

3

6

I sometimes write functions that make the assumption that some arguments cannot occur. If they do, this is a bug and I fail:

let foo = function
 | 0 -> ()
 | _ -> failwith "foo: bad argument"

If I rename the function later on, I have to remember to also change the string. Is there a way to do this in a more systematic manner? My mind wanders around solutions like

| _ -> failwith (FUNCTION_NAME ^ ": bad argument")

where FUNCTION_NAME is a string variable that the compiler or interpreter will instantiate. But I have no idea whether something like this even works in OCaml. If not, is there a best practice?

Privily answered 16/11, 2015 at 15:20 Comment(5)
not a duplicate but somehow related to thisManzoni
If you use assert false or similar the resulting error message will contain file and line number information. Perhaps that's adequate for this case?Blok
For insights on how to properly use assert, see #22562066Armalla
@SteveVinoski Assertions are adequate for sure since I will in many cases have to go back to the failing line anyway. I was just curious if there was a more direct way. I like to do some bookkeeping before I fail (the example is somewhat over-simplified in that regard) and having the function name available would be nice. If that's not possible, I'll have to stick with assertions.Privily
The thing is in Ocaml most functions don't have a name, in something as simple as 1+1 there are two functions one of which doesn't have a name: (+) is the function that has a name and (+) 1 is the one that doesn't. For this reason line numbers are a lot better.Piercy
G
14

There is a set of values available for debugging and error reporting.

OCaml 4.12 introduced __FUNCTION__:

val __FUNCTION__ : string

__FUNCTION__ returns the name of the current function or method, including any enclosing modules or classes.

They might be useful if you don't want to use assert false as suggested by @SteveVinoski.

__LOC__ : string
__FILE__ : string
__LINE__ : int
__MODULE__ : string
__POS__ : string * int * int * int

There are also fancier forms that you can use to wrap an expression to determine its extent in the source.

These are documented in the Stdlib module.

Gynarchy answered 16/11, 2015 at 15:54 Comment(0)
P
1

I think you should try as much as possible to use more specific types so that the compiler can prevent you from calling your functions with invalid input. If you really don't find a way to tell the type system what you want, try harder, and if you really can't, then use assert which as Steve told you will give you some precious debugging information (file and line number are much more useful than function name since chances are high your function doesn't have a name).

Piercy answered 16/11, 2015 at 15:51 Comment(0)
P
1

Since 4.12.0, __FUNCTION__ will return the function name.

There are also a number of other debugging variables defined in Stdlib:

val __LOC__ : string
val __FILE__ : string
val __LINE__ : int
val __MODULE__ : string
val __POS__ : string * int * int * int
val __FUNCTION__ : string
val __LOC_OF__ : 'a -> string * 'a
val __LINE_OF__ : 'a -> int * 'a
val __POS_OF__ : 'a -> (string * int * int * int) * 'a
Progenitor answered 6/1, 2022 at 19:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.