I've been slowly learning Nim and have come up with something I like to do with Python, which is log things.
This is a simple script that will create 'input', 'output', and 'logs' directories, which are separated by date / time inside those directories. Not sure if this will help anyone else, but I really like things like this:
import os, streams, strformat, times
proc logging(message: string, log_dir: string) =
var stream = newFileStream(&"{log_dir}/logs.txt", fmAppend)
try:
echo(&"[INFO]: {message}")
stream.writeLine(&"[INFO]: {message}")
except IOError:
echo(&"[ERROR]: {message}")
stream.writeLine(&"[ERROR]: {message}")
finally:
stream.close()
var now = times.now()
var date = now.format("MM-dd-yyyy")
var hms = now.format("HH-mm-ss")
var timestamp = &"{date}_{hms}"
var directories = ["input", &"input/{timestamp}", "output", &"output/{timestamp}", "logs", &"logs/{timestamp}"]
for directory in directories:
if not dirExists(directory):
createDir(directory)
echo(&"[INFO]: Created directory: {directory}")
else:
echo(&"[INFO]: Directory already exists: {directory}")
logging(&"Created directories: {directories}", directories[5])
I still haven't gotten a firm grasp on the difference between proc and functions, as they seem pretty similar, save for the weird equals sign on the proc. I'm still wrapping my head around Nim, but it's fun. Coming from a Python background, all the let / var stuff will take some getting used to (reminds me too much of Javascript).
Anyway, here it is. I tried to make the variable names in such a way that the code pretty much explains itself. However, if anyone wants me to walk them through the code, I'll be happy to do so.
Your code is readable to the point of needing no explanation. Well done. I believe the up-to-date idiom for importing from the standard library is to make it explicit:
import std / [os, streams, strformat, times]
I'm less certain about which is idiomatic when it comes to try/finally versus defer (https://nim-lang.org/docs/manual.html#exception-handling-defer-statement). This guidance may not be helpful at all since you're trying to handle an IOError explicitly; and defer does not allow that level of granularity.
In addition to what @blackmius said about proc/func, I would add this. If you aren't yet familiar with functional programming, do learn about it sooner rather than later. I'm not plugging the language Haskell, but the book Learn You a Haskell is a fun and free read. And learn about the benefits of writing funcs where possible, tolerating procs where necessary.
Nice work!
I don’t have much to add re: the other replies you’ve received but wanted to mention nim-chronicles
https://github.com/status-im/nim-chronicles
It’s a robust logger written in Nim and could make for an interesting study as you learn more about the language.