This is the description of warning 27 from the OCaml manual:
27 Innocuous unused variable: unused variable that is not bound with
let
noras
, and doesn't start with an underscore (_
) character.
This warning is turned on by jbuilder --dev
, and I'm curious to know in which cases people find it useful. For me, it's an annoyance to get warnings when I write code like this:
$ utop -w +27 utop # fun (x, y) -> x;; Characters 8-9: Warning 27: unused variable y. - : 'a * 'b -> 'a = <fun>
or like that:
utop # let error loc msg = failwith (loc ^ ": " ^ msg);; val error : string -> string -> 'a = <fun> utop # let rec eval = function | `Plus (loc, a, b) -> eval a + eval b | `Minus (loc, a, b) -> eval a - eval b | `Star (loc, a, b) -> eval a * eval b | `Slash (loc, a, b) -> let denom = eval b in if denom = 0 then error loc "division by zero" else eval a / denom | `Int (loc, x) -> x ;; Characters 33-36: Warning 27: unused variable loc. Characters 73-76: Warning 27: unused variable loc. Characters 112-115: Warning 27: unused variable loc. Characters 287-290: Warning 27: unused variable loc. val eval : ([< `Int of 'b * int | `Minus of 'c * 'a * 'a | `Plus of 'd * 'a * 'a | `Slash of 'e * 'a * 'a | `Star of 'f * 'a * 'a ] as 'a) -> int = <fun>
I know that prepending an underscore to the identifiers as in _loc
suppresses the warnings, but it's not compatible with my notions that:
Using underscores, the code becomes:
(* Here we have _loc or loc depending on whether it's used. *) let rec eval = function | `Plus (_loc, a, b) -> eval a + eval b | `Minus (_loc, a, b) -> eval a - eval b | `Star (_loc, a, b) -> eval a * eval b | `Slash (loc, a, b) -> let denom = eval b in if denom = 0 then error loc "division by zero" else eval a / denom | `Int (_loc, x) -> x
or
(* Here it can be hard to know what _ stands for. *) let rec eval = function | `Plus (_, a, b) -> eval a + eval b | `Minus (_, a, b) -> eval a - eval b | `Star (_, a, b) -> eval a * eval b | `Slash (loc, a, b) -> let denom = eval b in if denom = 0 then error loc "division by zero" else eval a / denom | `Int (_, x) -> x
Unused variable is a warning, not an error. It comes up when you assign to a variable but don't ever read from it. printf() takes a variable argument list. Since you want to print a number, as you've indicated by the "%d", you need to pass an int after. Otherwise, your program will probably crash: printf("%d\n", i);
Unused variable warnings are emitted during compiletime and should be a hint to you as the developer, that you might have forgotten to actually process a value that you have bound to a name. Thats the main reason for the warning.
It is very useful in the monadic code, where instead of the common syntactic let
bindings you're forced to use monadic >>=
bind operator. Basically, where
let x = something in
code
translates to
something >>= fun x ->
code
If x
is not used in code
then only with the 27 warning enabled the latter will be highlighted, while the former will produce a warning by default. Enabling this warning, revealed lots of bugs for us. For example, it showed us that this code is buggy :)
Another source of use cases are higher-order functions, i.e., map
, fold
, etc. It captures one of the most common bugs:
let bug init =
List.fold ~init ~f:(fun acc xs ->
List.fold ~init ~f:(fun acc x -> x :: acc))
Concerning the ugliness, I totally agree that underscores are ugly, but in most cases, this is the main purpose of them - to highlight the suspicious code. Concerning the example, that you're showing, in the modern OCaml it could be easily addressed with the inline records, e.g.,
type exp =
| Plus of {loc : loc; lhs : exp; rhs: exp}
| ...
so that instead of using the underscores, you can just omit the unused field,
let rec eval = function
| Plus {lhs; rhs} -> eval lhs + eval rhs
You can use the same approach without using inline records by sparing some extra space in your program and defining all those records separately. The real-world example.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With