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.