CS51: Introduction to Computer Science II Spring, 2018 CS51: OCAML STYLE GUIDE
CS51: Introduction to Computer Science II Spring, 2018 CS51: OCAML STYLE GUIDE STUART M. SHIEBER Contents 1. Formatting 2 1.1. No tab characters 2 1.2. 80 column limit 2 1.3. No needless blank lines 3 1.4. Use parentheses sparely 3 1.5. Spacing for operators and delimiters 3 1.6. Indentation 4 1.6.1. Indenting if expressions 4 1.6.2. Indenting let expressions 4 1.6.3. Indenting match expressions 5 2. Documentation 5 2.1. Comments before code 5 2.2. Comment length should match abstraction level 5 2.3. Multi-line commenting 5 3. Naming and declarations 6 3.1. Naming conventions 6 3.2. Use meaningful names 6 3.3. Function declarations and type annotations 7 3.4. Avoid global mutable variables 7 3.5. When to rename variables 7 3.6. Order of declarations in a structure 8 4. Pattern matching 8 4.1. No incomplete pattern matches 8 4.2. Pattern match in the function arguments when possible 8 4.3. Pattern match with as few match expressions as necessary 9 4.4. Misusing match expressions 9 4.5. Avoid using too many projection functions 10 4.5.1. Don’t use List.hd or List.tl at all 10 Date: January 29, 2018. This style guide is reworked from a long line of style guides for courses at Princeton, University of Pennsylvania, and Cornell, including Cornell CS 312, U Penn CIS 500 and CIS 120, and Princeton COS 326. All this shows the great power of recursion. (Also, the joke about recursion was stolen from COS 326.) CS51: OCaml Style Guide 5. Verbosity 10 5.1. Reuse code where possible 10 5.2. Do not abuse if expressions 11 5.3. Don’t rewrap functions 11 5.4. Avoid computing values twice 12 6. Other common infelicities 12 This guide provides some simple rules of good programming style, both general and OCaml-specific, developed for the Harvard course CS51. The rules presented here tend to follow from a small set of underlying principles. Consistency: Similar decisions should be made within similar contexts. Brevity: “Everything should be made as simple as possible, but no simpler.” (attr. Albert Einstein) Clarity: Code should be chosen so as to communicate clearly to the human reader. Transparency: Appearance should summarize and reflect structure. Like all rules, those below are not to be followed slavishly but seen as instances of these underlying principles. These principles may sometimes be in conflict, in which case judgment is required in finding the best way to write the code. This is one of the many ways in which programming is an art, not (just) a science. This guide is not complete. For more recommendations, from the OCaml developers themselves, see the official OCaml guidelines. 1. Formatting Formatting concerns the layout of the text of a program on the screen or page, such issues as vertical alignments and indentation, line breaks and whitespace. To allow for repeatable formatting, code is typically presented with a fixed-width font in which all characters including spaces take up the same horizontal pitch. 1.1. No tab characters. You may feel inclined to use tab characters (ascii 0x09) to align text. Do not do so; use spaces instead. The width of a tab is not uniform across all renderings, and what looks good on your machine may look terrible on another’s, especially if you have mixed spaces and tabs. Some text editors map the tab key to a sequence of spaces rather than a tab character; in this case, it’s fine to use the tab key. 1.2. 80 column limit. No line of code should extend beyond 80 characters long. Using more than 80 columns typically causes your code to wrap around to the next line, which is devastating to readability. 2 Spring, 2018 1.3. No needless blank lines. The obvious way to stay within the 80 character limit imposed by the rule above is to press the enter key every once in a while. However, blank lines should only be used at major logical breaks in a program, for instance, between value declarations, especially between function declarations. Often it is not necessary to have blank lines between other declarations unless you are separating the different types of declarations (such as structures, types, exceptions and values). Unless function declarations within a let block are long, there should be no blank lines within a let block. There should absolutely never be a blank line within an expression. 1.4. Use parentheses sparely. Parentheses have many purposes in OCaml, including constructing tuples, grouping sequences of side-effect expressions, forcing higher precedence on an expression for parsing, and grouping structures for functor arguments. Clearly, parentheses must be used with care, as they force the reader to disambiguate the intended purpose of the parentheses, making code more difficult to understand. You should therefore only use parentheses when necessary or when doing so improves readability. let x = function1 (arg1) (arg2) (function2 (arg3)) (arg4) let x = function1 arg1 arg2 (function2 arg3) arg4 On the other hand, it is often useful to add parentheses to help indentation algorithms, as in this example: let x = "Long line ..." ^ "Another long line..." let x = ("Long line ..." ^ "Another long line...") Similarly, wrapping match expressions in parentheses helps avoid a common (and confusing) error that you get when you have a nested match expression. Parentheses should never appear on a line by themselves, nor should they be the first visible character; parentheses do not serve the same purpose as brackets do in C or Java. 1.5. Spacing for operators and delimiters. Operators (arithmetic operators like + and *, the typing operator :, type forming operators like * and ->, etc.) should be surrounded by spaces. Delimiters like the list item delimiter ; and the tuple element delimiter , are followed but not preceded by a space. let f (x : int) : int * int = 3 * x - 1, 3 * x + 1 ;; let f (x: int): int*int = 3* x-1, 3* x+1 ;; Judgement can be applied to vary from these rules for clarity’s sake, for instance, when emphasizing precedence. let f (x : int) : int * int = 3*x - 1, 3*x + 1 ;; 3 CS51: OCaml Style Guide 1.6. Indentation. Indentation should be used to encode the block structure of the code as described in the following sections. It is typical to indent by two xor four spaces. Choose one system for indentation, and be consistent throughout your code. 1.6.1. Indenting if expressions. Indent if expressions using one of the following methods, depending on the sizes of the expressions. For very short then and else branches, a single line may be sufficient. if exp1 then veryshortexp2 else veryshortexp3 When the branches are too long for a single line, move the else onto its own line. if exp1 then exp2 else exp3 This style lends itself nicely to nested conditionals. if exp1 then shortexp2 else if exp3 then shortexp4 else if exp5 then shortexp6 else exp8 For very long then or else branches, the branch expression can be indented and use multiple lines. if exp1 then longexp2 else shortexp3 if exp1 then longexp2 else longexp3 Some use an alternative conditional layout, with the then and else keywords starting their own lines. if exp1 then exp2 else exp3 This approach is less attractive for nested conditionals and long branches. 1.6.2. Indenting let expressions. Indent the body of a let expression the same as the let keyword itself. let x = definition in code_that_uses_x This is an exception to the rule of further indenting subexpression blocks to manifest the nesting structure. let x = definition in code_that_uses_x 4 Spring, 2018 The intention is that let definitions be thought of like mathematical assumptions that are listed before their use, leading to the following attractive indentation for multiple definitions: let x = x_definition in let y = y_definition in let z = z_definition in block_that_uses_all_the_defined_notions 1.6.3. Indenting match expressions. Indent match expressions so that the patterns are aligned with the match keyword, always including the initial (optional) |, as follows: match expr with | first_pattern -> ... | second_pattern -> ... Some disfavor aligning the arrows in a match, arguing that it makes the code harder to maintain. However, where there is strong parallelism among the patterns, this alignment (and others) can make the parallelism easier to see, and hence the code easier to understand. Use your judgement. 2. Documentation 2.1. Comments before code. Comments go above the code they reference. Consider the following: let sum = List.fold_left (+) 0 (* Sums a list of integers. *) (* Sums a list of integers. *) let sum = List.fold_left (+) 0 The latter is the better style, although you may find some source code that uses the first. Comments should be indented to the level of the line of code that follows the comment. 2.2. Comment length should match abstraction level. Long comments, usually focused on overall structure and function for a program, tend to appear at the top uploads/s3/ cs51-introduction-to-computer-science-ii-spring-2018-cs51-ocaml-style-guide.pdf
Documents similaires
-
21
-
0
-
0
Licence et utilisation
Gratuit pour un usage personnel Attribution requise- Détails
- Publié le Oct 22, 2021
- Catégorie Creative Arts / Ar...
- Langue French
- Taille du fichier 0.1458MB