Conventions
This document expands on the Style guide.
Informal recommendations for function names
To name a function, first identify its purpose. If you were to describe this purpose in a sentence, you should be able to identify up to three grammatical items of importance: the verb, the object, and the subject. The subject is usually the actor, the object is usually being acted upon, and the verb defines the action being taken.
When naming a Hare function, use the format “subject_verbobject”, where the subject preceeds the verb and object, separated by an underscore, and the object directly follows the verb. If you can infer the subject or object from context, they may be omitted, so “verbobject”, “subject_verb”, or simply “verb” may be appropriate names.
In the sentence “Sam goes to the store”, “Sam” is the subject, “store” is the object, and “go” is the verb. The equivalent function name would be “sam_gostore”. If we have additional context, for example if this is in the “sam” module, we could call it “sam::gostore”. Or perhaps the object is given by a parameter, in which case “go” is sufficient:
fn sam::go(to: destination) void;
Abbreviating terms is acceptable, such as “str” for “string” or “tok” for “token”.
This approach prefers terseness when unambiguous. Here are some real-world examples:
fn bufio::scantok(stream: *io::stream, delim: u8) ([]u8 | io::EOF | io::error);
fn io::read(stream: *io::stream, buf: []u8) (size | io::EOF | io::error);
fn lex::init(in: *io::stream, path: str) lexer;
Note the arrangement of parameters: the object being acted upon comes first. For example, if you have “source” and “destination” parameters, “destination” should be placed first in the parameter list.
Verbs for allocation strategies
It is useful to communicate the allocation strategy in function names, to lend readability to the implications for Hare’s manual memory management system. The following conventions are recommended.
For functions which initialize a value and return it, either via
allocation or via the stack, name these functions after the object being
initialized. For example, to initialize a SHA-256 hash, you use
crypto::sha256::sha256()
. If a more specific verb than “allocate” or
“initialize” would be appropriate, name the function after that verb.
For example, “open” or “connect” may be more appropriate names than
“file” or “client”.
If a function accepts a pointer to a value as a parameter, and will initialize that value, use the “init” verb to name the function.
For functions which free resources associated with an object, if the object itself is freed, use the verb “free”. If the object itself is not freed, but some other state associated with it, use the verb “finish”.
Informal recommendations for documentation
Consult man haredoc
for technical details regarding documenting Hare
interfaces through comments in the source code.
It is useful to have some linguistic conventions for inline documentation. The following guidelines provide such conventions for any programs which wish to be consistent with the rest of the Hare ecosystem in their approach to API documentation.
All programmer-facing documentation should be written in English, and all public (exported) members should be documented. Not documenting an exported member signals that it is not designed to be used by third-party programs.
Your documentation should be as concise or as long as is necessary. Programmers reading the reference documentation are usually in a hurry, but they also appreciate comprehensive explanations. Aim to be as short as possible without omitting necessary details.
Include a period after the last sentence.
Function documentation should complete the following thought: “This function [does, will, is used to]…”. Examples:
“Insert a new entry into the list”
“Parse the next record from the file”
Type documentation should complete the following thought: “This type is…” or “This type $verbs…”. Examples:
“An error indicating that an invalid sequence was encountered”
“Indicates that more data is required to finish processing”
“Stores the state for an XML parser”
Constant documentation should complete the following thought: “This constant is…”
“The size, in bytes, of an MD5 digest”
“The magic string identifying a PNG file”
Informal recommendations for errors
These recommendations cover programmer-facing errors. User-facing errors have different concerns, for example they may require internationalization.
Each module should provide an error
type which is a tagged union of
all possible errors which might be returned by functions in that module,
and an strerror
function which explains the error as a string. These
strings should be written with “Sentence case” and should not end with a
period. It should also be written so that it makes sense when passed to
fmt::fatal("Error:", example::strerror(err))
.
Write programmer-facing error messages in English. This includes the
return value from strerror
, and also the error messages used in
abort
and assert
expressions.