
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 :: <outdoor-espresso-cart>,
	                               #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 :: <class-1>, two :: <class-2>, ...)
	     => (result1 :: <type1>, result2 :: <type2>);
	   statement1;
	   statement2;
	   ...;
	 end method;

	 define method some-longer-name-for-effect
	     (one :: <class-1>, two :: <class-2>, ...)
	  => (result1 :: <type1>, result2 :: <type2>);
	   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 :: <simple-object-vector>,
	                    #key start :: <fixed-integer> = 0,
			         stop :: <fixed-integer> = 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 :: <integer>
	   = north-america-mask | south-america-mask | europe-mask;

   Using "end <mumble>" to terminate statements
      You should use "end <mumble>", 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
      <mumble>" religiously, but those same programmers only use "end" when
      using "end <mumble>" would make a single-line statement wrap onto a
      new line.  Programmers may add the "<mumble>" to an "end" if they feel
      the code was hard to visually scan, but programmers should not add
      "<mumble>"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 :: <stream>, offset :: <integer>,
	                           #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 <frob>
	   slot gag, required-init-keyword: foo:;
	 end;
	 //
	 // Or ...
	 //
	 define class <frob>
	   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)
