Since no one answered, I can start and then people can correct me when I say something wrong.
If you at need any of the predicates in library(pairs), then you should probably use pairs. Since Jan made sort/4 available, pairs are no longer necessary for sorting by a key – before that, you had to do the little dance described in the keysort/2 docs. But pairs are still useful. Read the docs to library(pairs) for ideas.
Then, if you compare foo(bar) to foo-bar, you are actually comparing foo(bar) to -(foo, bar). They are conceptually the same, which is why some predicates would accept either. I am struggling to find a good general rule, but in some cases it is easier/cleaner to use the one, and in some cases, the other. foo(bar) is slightly smaller, so if you have many, that could make a difference. If you use the term for indexing, foo(bar) should in theory be a bit more efficient than foo-bar (but please don’t believe me and do your own profiling).
One last thing: if you actually need to “unpack” the key and the value at run time, I have always assumed that foo-bar is the better choice. If you have foo(bar) and you need the foo, than you’d have to do Term =.. [Key, Value] which seems a bit unnecessary?
If you don’t mind restricting yourself to SWI-Prolog, dicts are a handy way of handling options. I use library(optparse) and then the following code to convert between the options list from opt_arguments/3 and a dict – this avoids using memberchk(key(Value), Opts) and instead directly using Opts.key.