mirror of
https://github.com/anoma/juvix.git
synced 2024-11-29 21:32:43 +03:00
143 lines
3.9 KiB
Markdown
143 lines
3.9 KiB
Markdown
# Juvix coding style guidelines for the standard library and Anoma apps
|
|
|
|
## Definitions
|
|
|
|
- _enumeration type_ is an inductive type whose all constructors have zero
|
|
arguments
|
|
|
|
## General rules
|
|
|
|
- always use the formatter
|
|
- don't use unicode, except perhaps for judoc
|
|
- avoid `Pair`
|
|
- prefer enumeration types with meaningful constructor names over booleans,
|
|
e.g., instead of using `Bool` define:
|
|
|
|
```
|
|
type Transferability :=
|
|
| Transferable
|
|
| NonTransferable;
|
|
```
|
|
|
|
## Imports
|
|
|
|
- all imports at the beginning of the file
|
|
- explicit names for imported identifiers (`import X open using {iden1; iden2}`)
|
|
- exception: `import Stdlib.Prelude open` and `import Anoma open` are allowed
|
|
|
|
## Names
|
|
|
|
- types: upper camel case (`Nat`, `PublicKey`)
|
|
- functions, constructors, etc: lower camel case (`tokenLogic`, `transferLogic`)
|
|
- exception: constructors of enumeration types: upper camel case
|
|
|
|
```
|
|
type BalanceFactor :=
|
|
| --- Left child is higher.
|
|
LeanLeft
|
|
| --- Equal heights of children.
|
|
LeanNone
|
|
| --- Right child is higher.
|
|
LeanRight;
|
|
|
|
type Ordering :=
|
|
| LessThan
|
|
| Equal
|
|
| GreaterThan;
|
|
```
|
|
|
|
- instances: lower camel case with `I` at the end: trait + type + `I`, e.g., `instance eqNatI : Eq Nat := ..`
|
|
- boolean check functions: start with `is` (`isWhatever`)
|
|
- record constructors: `mk` + type name (`mkResource`)
|
|
- meaningful descriptive long names for arguments of public functions, e.g., `element`, `list`, `initialValue`
|
|
- exception: common abbreviations allowed: `fun`, `acc`, `elem`
|
|
- exception: generic functions whose arguments have no specific meaning, e.g.,
|
|
|
|
```
|
|
id {A} (x : A) : A := x
|
|
```
|
|
|
|
- short names like `x` are okay for local definitions
|
|
|
|
## Function signatures
|
|
|
|
- put everything to the left of `:` in type signatures, with _full_ meaningful names for arguments
|
|
- temporary exception: when needed for termination, argument can be moved to the right of `:`
|
|
- even when the argument type is moved to the right, give a descriptive argument name in the type:
|
|
|
|
```
|
|
isMember {A} (testEq : A -> A -> Bool) (element : A) : (list : List A) -> Bool
|
|
```
|
|
|
|
## Type variables
|
|
|
|
- type variables uppercase (upper camel case, like with types)
|
|
- higher-order type variables also upper camel case (`F : Type -> Type`)
|
|
- implicit type variables: use short version `{A}` in function signatures on the left
|
|
- prefer `{A B}` over `{A} {B}` in function signatures
|
|
- meaningful type variable names for more "high-level" functions where this makes sense
|
|
|
|
Example:
|
|
|
|
```
|
|
split
|
|
{ResourceType}
|
|
{{Convertable ResourceType}}
|
|
{{HasOwner ResourceType}}
|
|
{{HasQuantity ResourceType}}
|
|
{{HasTransferability ResourceType}}
|
|
{{TransactionConvertable ResourceType ResourceType}}
|
|
(self : KeyPair)
|
|
(toSplit : ResourceType)
|
|
(quantitiesAndReceivers : List (Pair Nat PublicKey))
|
|
: Result StandardError Transaction :=
|
|
...
|
|
```
|
|
|
|
But we can use a short name `A` in:
|
|
|
|
```
|
|
find {A} (predicate : A -> Bool) : (list : List A) -> Maybe A
|
|
```
|
|
|
|
## Pattern matching
|
|
|
|
- use `case` whenever possible; matching on multiple values handled with pairs
|
|
- don't use pattern matching with side conditions when there is an `else` side condition -- convert to an `if` in the body instead
|
|
- don't pattern match on `Bool` -- use `if` instead
|
|
|
|
## Application
|
|
|
|
- don't use "pipes" (i.e., `|>`, `<|`, `>>`, `<<`, etc.)
|
|
- exception: there is a "natural" data processing pipeline in several steps, e.g.,
|
|
|
|
```
|
|
map (+ 1) >> filter (< 0) >> sum
|
|
```
|
|
|
|
- use iterators `for` , `map`, etc., instead of the function application syntax with `fold`, etc.
|
|
- use named application when reasonable
|
|
|
|
## Type definitions
|
|
|
|
- use ADT syntax
|
|
- every constructor on a separate line
|
|
- give meaningful names to constructor arguments
|
|
|
|
Example:
|
|
|
|
```
|
|
type BinaryTree (A : Type) :=
|
|
| leaf
|
|
| node@{
|
|
left : BinaryTree A;
|
|
element : A;
|
|
right : BinaryTree A
|
|
};
|
|
```
|
|
|
|
## Documentation
|
|
|
|
- the documentation string should be an English sentence
|
|
- mention the meaningful argument names in the function's judoc
|