This file lists two broad categories of style issues for Dylan. One category, called "Recommended", contains style points to which Gwydion programmers should adhere, as opposed to "must adhere". If someone sometimes, or even always, breaks a recommended style point, then others must to be tolerant of that deviation. You must not modify the original author's code purely to satisfy an urge to convert the original author's style to your own. The second category, called "Mandated", contains style points to which Gwydion programmers must adhere. If you find someone has deviated from a mandated style point, then you may convert the code to be the mandated style. Recommended Indent level You should use a two-space indentation. Each time code needs to be further indented, you should use one indent level, which is two spaces. Indent wrapping slot descriptions When a slot description wraps to a new line in a "define class" form, the extra lines should be indented one extra indent level. Using /// comments If you use /// comments, they should only be used between top-level declarations. /// comments can be used for logical page headers, inter-function comments, code section introductions (logical page headers), etc., for example: ... end method; /// order-espresso -- Method for Exported GF. /// /// This method orders espresso at carts on the corner when it is /// raining. If it is not raining, this method delegates to /// next-method. /// define method order-espresso (vendor :: , #next next-method) => (); ... end method; Many programmers do not like others to use /// comments. Rob noted that if these are only used between top-level declarations, where the /// indicates a comment of wider scope (as over a whole definition or logical page), then the Gwydion environment should be able to display such comments however any particular user wants to see them. Using /* ... */ If you use /* ... */ comments, they should only be used at the beginning of a file or the beginning of a logical page so that their use is highly localized. This prevents them from showing up surprisingly in random places throughout a file of code. Using /*...*/ comments should go away once the Gwydion environment has a means for linking general commentary to logical units of code. This issue has absolutely nothing to do with using /*...*/ to temporarily exclude code fragments. Wrapping function definition headers When a function header wraps (that is, a "define generic" or a "define module" declaration), you should either break the line within the parameter list or between the name and the parameter list. If you break the line between the name and parameter list, or perhaps after the parameter list, then you should indent any extra lines one extra indent level. There is one exception: the first line of the return values specification may be indented only one space. The following are examples of recommended style: define method some-longer-name-for-effect (one :: , two :: , ...) => (result1 :: , result2 :: ); statement1; statement2; ...; end method; define method some-longer-name-for-effect (one :: , two :: , ...) => (result1 :: , result2 :: ); statement1; statement2; ...; end method; Indent keyword parameters beyond #key token If there is more than one keyword parameter specified in a function declaration, then all keyword parameter specifications should line up with the first specification. The following is an example: define method foo (foo :: , #key start :: = 0, stop :: = foo.size) ... If a parameter list that contains a #key wraps, then you should wrap the parameter list before the #key token. Wrapping variable and constant definitions When a variable or constant definition wraps, you should break the line before the = token: define constant western-culture :: = north-america-mask | south-america-mask | europe-mask; Using "end " to terminate statements You should use "end ", rather than just "end", whenever there is sufficient vertical space between the beginning and the end of the statement to hinder readability. Some programmers like to use "end " religiously, but those same programmers only use "end" when using "end " would make a single-line statement wrap onto a new line. Programmers may add the "" to an "end" if they feel the code was hard to visually scan, but programmers should not add ""s to all "end"s in someone else's code just because they like that style. This policy is consistent with adding additional comments to someone else's code to help readability. Horizontal space for columnization or other visual effects You should NOT use horizontal spacing to columnize aspects of Dylan code, or to present other visual effects within the program. If you do this, you should do it rarely. The one exception to this rule is the "Indent keyword parameters beyond #key token" recommendation. Keyword syntax You should only use keyword notation for symbols in function calls and function declarations. You can also use keyword notation in slot descriptions within "define class", where you are supplying a symbol to be the key for an initialization argument. When a symbol is a value, such as a default value in a declaration or an argument value in a call, you should use symbol notation, not keyword notation. The following are examples of recommended style: define method reposition (stream :: , offset :: , #key from: = #"start") define method foo () ... bar(x, y, color: #"red"); ... end method; // In this example, required-init-keyword: would always be in // keyword notation, and "foo:" is the item to which this style // recommendation speaks. // define class slot gag, required-init-keyword: foo:; end; // // Or ... // define class slot gag, required-init-keyword: #"foo"; end; Blank comment line between introductory comments and definitions You should include a blank comment line between the introductory comments for a function and the function definition. This applies to any top-level declaration for which you supply an introductory comment. The following is an example: // Blah blah blah GINGER blah blah blah. // define ... Wrapping case statements (applies to select too) If any single branch of a case statement wraps, then you should wrap every branch. In practice, there are common exceptions to this recommendation. When wrapping a case statement, you should wrap it after the '=>' token. There should be no exceptions to this recommendation. The following exhibit the recommended style: case test1 => expression1; test2 => expression2; end; case test1 => statement1; statement2; test2 => statement1; statement2; end; Using #t for 'otherwise' in case statements You should not use #t for 'otherwise' in case statements. Wrapping 'for' clauses When an =/then clause needs to wrap, you should wrap before the '=' and before the 'then'. Both the '=' and the 'then' should be indented one extra indent level: // Correct. // ... nested levels ... for (some-index = initialization-expression(x, y, z) then stepper(u, v, w)) stuff(some-index); end; // Incorrect. // ... nested levels ... for (some-index = initialization-expression(x, y, z) then stepper(u, v, w)) stuff(some-index); end; Mandated Function name and open paren The "define generic" or "define method" declarations must have a space or newline between the name of the definition and the parameter list. At any function call site, the name and open paren must be adjacent, with no intervening characters. Wrapping let statements If a let statement wraps, you must put the equal sign on a new line and indent it one extra indent level. Terminate statements with semicolons Semicolons are terminators and must appear wherever they are optional, except as covered by the "Single-line statements" mandate. Single-line statements Single-line statement, such as if-else, must not have any internal semicolons. If a single-line statement requires an internal semicolon, then you must break the statement into multiple lines. For example, the following would be illegal in Gwydion style: let x = if (some-test) foo(); 3; else 5; end; let x = if (some-test) foo(); 3 else 5 end; let f = method (a, b) foo(); #f; end; These should be formatted as follows (ignoring the "end if" issue): let x = if (some-test) foo(); 3; else 5; end; let f = method (a, b) foo(); #f; end; Most programmers felt this rule, by its nature of eliminating multiple statements within a block on a single line, made code much more readable. Wrapping arithmetic/boolean expressions You must wrap long expressions before operators and indent the operators with one extra indent level from the beginning of the expression. Note, assignments are considered to be "statements", and the "expression" that wraps is the code on the right-hand side of the assignment operator. Therefore, the first two examples below are considered to be approved style, but the third is not: my-local := big-computation(arg1, arg2) + another-hairy-long-calculation(arg3, arg4, arg5) my-local := (big-computation(arg1, arg2) + another-hairy-long-calculation(arg3, arg4, arg5)) my-local := big-computation(arg1, arg2) + another-hairy-long-calculation(arg3, arg4, arg5)