Single semicolons simply evaluates several expressions and returns the last one, but if you use them in a module definition (like every file is by default), you'll be coerced into using double semis.
The advantage over your version (with the single semicolon) is that in your version, you cannot now create a standard exported module value binding after that single semicolon, because the parser interprets that next let binding as a continuation of the single semicolon expression, so your only hope is to use double semis to escape back to normal module body parser context.
Function bodies (or any other expression really) don't have that same issue, but I might suggest avoiding single semicolons even in that case so that you have fewer edge cases to memorize. Here is the simplest possible convention I can think of that requires the smallest amount of memorization:
- Forget about all semicolons, single or double (just think of ;; as a way to press enter in the top interactive REPL).
- Module bodies (like every file by default) are just exporting a series of bindings. If you want to evaluate an imperative command inside a module body, export its result to "_".
- Function bodies are expressions. If you want to evaluate an imperative command inside a function body (or any other expression), use `let in` like you would for any other temporary variable, but use the variable name "_" and simply don't use it.
The advantage over your version (with the single semicolon) is that in your version, you cannot now create a standard exported module value binding after that single semicolon, because the parser interprets that next let binding as a continuation of the single semicolon expression, so your only hope is to use double semis to escape back to normal module body parser context.
Function bodies (or any other expression really) don't have that same issue, but I might suggest avoiding single semicolons even in that case so that you have fewer edge cases to memorize. Here is the simplest possible convention I can think of that requires the smallest amount of memorization:
- Forget about all semicolons, single or double (just think of ;; as a way to press enter in the top interactive REPL).
- Module bodies (like every file by default) are just exporting a series of bindings. If you want to evaluate an imperative command inside a module body, export its result to "_".
- Function bodies are expressions. If you want to evaluate an imperative command inside a function body (or any other expression), use `let in` like you would for any other temporary variable, but use the variable name "_" and simply don't use it.