[RFC] GNU Algol 68 Coding Guidelines
Jose E. Marchesi
jemarch@gnu.org
Mon Jan 12 12:53:11 GMT 2026
> What a wonderful conversation to begin!
:)
> I have a few observations following Jose's below.
>
> Before I dive in, I find my style preferences (in any programming language)
> are a result of the short/wide screen on most computers these days, so I
> lean into practices that promote vertical compactness:
>
> - prefer long lines (not to the point of ridiculousness, but I certainly
> don't have a problem with 130 or 150 characters or so) to short lines that
> force continuation
I don't like long lines, personally. I keep my own working environment,
which is the Linux console, with a biggish font that let me have around
75 characters per physical line. Long lines make it more difficult to
track your progress vertically. This also applies to books and
documentation.
> - minimize the number of empty lines
There we agree.
> - don't put "begin" (after a proc declaration), "struct", "then",
> "else", "elsif", "do" etc on a line by themselves
I also agree here, but unlike you, I like to put them at the head of the
subordinate phrase, not at the tail of the header:
if a > 10
then blah
else bleh
fi
Otherwise, how do you reconcile the "fixed indentation steps" that you
favor with not having "else" in its own line?
if a > 10 then
blah else
bleh
fi
Also, how do you achieve constant indentation steps without putting
"begin" in its own line?
> - in any long enclosed clause think about a comment at the end that
> indicates what I (think I) am closing off, for example "fi { if foo /= 42 }"
Every time I find myself looking at such long enclosed clauses, I can't
avoid but wondering whether the code couldn't be rewritten to use
shorter clauses.
That said, I have nothing against putting comments like:
if a > 10
...
fi { a > 10 }
But I don't do it myself.
> - etc
>
>
> On Sun, Jan 11, 2026 at 3:27 PM Jose E. Marchesi <jemarch@gnu.org> wrote:
>
>>
>> Hello people!
>>
>> Since we are about to start writing Algol 68 for libga68, and probably
>> other supporting libraries, I thought it would be a good idea to write
>> down a set of coding conventions.
>>
>> Of course these mainly depend on personal taste, and it is for certain
>> that it will not be possible to keep everyone happy, but I would really
>> appreciate to get some feedback. The goal is to achieve readability and
>> compactness.
>>
>> Salud!
>>
>> ---
>>
>> _ __ ___
>> / \ / /_ ( _ )
>> / _ \| '_ \ / _ \ GNU Algol 68 Coding Guidelines
>> / ___ \ (_) | (_) |
>> /_/ \_\___/ \___/
>>
>>
>>
>>
>> Jose E. Marchesi
>> January 12, 2026
>>
>>
>> Please send suggestions and proposals related to
>> this document to algol68@gcc.gnu.org
>>
>>
>> This document contains a set of conventions and recommendations for
>> writing Algol 68 code which is part of ga68, the GNU Algol 68
>> compiler. As with any coding conventions, the goal is to achieve a
>> coherent style among the codebase.
>>
>> Algol 68 is probably the programming language with the most carefully
>> and lovingly designed syntax ever made. It can be verbose when it is
>> convenient for the programmer, and also extremely compact while
>> keeping an astounding high level of readability. These conventions
>> aim to make a good use of that.
>>
>> Feel free to adopt our guidelines for your own Algol 68 project,
>> partially or entirely.
>>
>> In what follows we make extensive use of Algol 68 terminology, which
>> may be confusing at first for the uninitiated reader. The Algol 68
>> Jargon File provides definitions for many of the terms used in the
>> context of the Algol 68 programming language and associated
>> technologies. If you find yourself wondering about "frobyts" or
>> "enclosed clauses", please look them up in the jargon file. The file
>> is available online in the www and, in Gentoo, as manpages once you
>> install the app-doc/a68-jargon package. Just type `man 7algol frobyt'
>> in the terminal, for example.
>>
>> => https://jemarch.net/a68-jargon The Algol 68 Jargon File
>>
>> Additionally, in this document we use the term "space" and "spaces" to
>> refer to "typographical display features", i.e. spaces, tabs and
>> newlines. These characters are of no significance and do not alter
>> the meaning of the program when they appear between symbols, outside
>> of string and character denotations, but they have a great impact on
>> the readability of the code and are the main tool for formatting.
>>
>> ## Stropping
>>
>> The GNU Algol 68 compiler supports two stropping regimes:
>>
>> * The "classic" UPPER stropping, which is one of the standard
>> stropping regimes defined in the Standard Hardware Representation
>> for Algol 68. This regime uses upper-case letters to encode bold
>> letters and lower-case letters to encode non-bold letters.
>>
>> * The "modern" SUPPER stropping, which is a GNU extension. This is
>> the standard stropping regime in GCC, and its rules are similar to
>> the naming conventions widely used in many modern programming
>> languages. The resulting programs have a very modern feeling.
>>
>> In GCC we use SUPPER stropping only. The only instance of UPPER
>> stropping are in test cases. Some of the guidelines and
>> considerations in this document may also be useful in programs using
>> UPPER stropping.
>>
>
> I like the whole SUPPER stropping concept. I think it would be good to
> have a piece of code (say copied from the RR) "officially" SUPPER stropped
> as an example, complete with mode / structure, operator and any other
> notably different practices from UPPER, PERIOD, QUOTE etc stropping.
Thats a good idea.
> I am a fan of camel case so to the extent we feel we can collectively
> accommodate either camel case or _ it might be good to have examples of
> both - even if there is a greater preference for one or the other.
>
>>
>> ## Formatting
>>
>> The placement of spaces and empty lines in the program text plays an
>> important role when it comes to readability.
>>
>> ### Empty lines
>>
>> Empty lines are often used in programs to separate logical parts in a
>> sequence of statements or expressions. This avoids the code to look
>> like walls of text, which are somewhat difficult to read. This of
>> course also applies to Algol 68, but in a much less degree due to the
>> exceptionally clean syntax of the language. Therefore we favor a
>> compact formatting to a reasonable extent.
>>
>> Please be frugal with empty lines, especially within enclosed clauses.
>>
>
> Absolutely! Too many blank likes obscures what is going on because it's
> impossible to get a reasonable amount of code on a screen, especially in
> some of the ornate IDEs that are out there.
>
>>
>> It is not necessary nor advisable to have separated "declaration
>> parts" in serial clauses, because declarations can appear anywhere.
>> However empty lines may still be useful to group related declarations
>> together.
>>
>
> I'm a big fan of declaring a reference as close as possible to where it is
> used, and attempting to keep its use compact; or better still put the whole
> thing in a procedure or operator.
>
> As for immutable values, declaring them further away from where they are
> used is only a problem insofar as it causes additional mental stress
> carrying extra values around in one's head.
>
>>
>> It is often better to use an explanatory comment rather than an empty
>> line, again especially within enclosed clauses.
>>
>> ### Spaces before parentheses
>>
>> Do not put spaces before open-parentheses in routine calls.
>>
>
> Agreed.
>
>>
>> But make sure to always put a space between `union' or `struct' and
>> the open parenthesis that follows in declarers.
>>
>
> Agreed.
>
>>
>> Likewise, please put a space before the open parenthesis when the
>> enclosed clause in a cast is a closed clause.
>>
>
> Agreed.
>
> Also when using ( as the brief form of begin, if, case, put a space before
> it.
I don't think that is a good idea. The brief forms are mostly used in
formulas. So this would involve:
this space is covered by another rule, space after dyadic operator
in non-parenthesized formulas
_
2 * ( (a > 0 | 10 | 20) + 5)
_
but do we want this space? I think not.
>>
>> Examples:
>>
>> ```
>> { No space before open-parentheses in calls }
>> puts(fixed(count,0) + "'n");
>>
>> { Space between `union' or `struct' and `(' }
>> mode Number = union (int,long int,real,long real)
>>
>> { Space before '(' in casts }
>> ref JSON_Fld (fields) := field;
>> ```
>>
>> ### Spaces after parentheses
>>
>> When writing routine texts always place a space between the formal
>> parameters pack and the mode of the value yielded by the routine.
>>
>
> Agreed.
>
>>
>> When writing operator and procedure declarators do not put a space
>> between the parameter modes pack and the mode of the yielded value.
>>
>
> Agreed.
>
>>
>> Also in declarers, do not put a space after `op' or `proc' and the
>> parameter modes pack.
>>
>
> I'm not averse to this, but I don't understand the point.
The reason why I like to avoid these spaces in declarers is to help
quickly identifing them as declarers. Compare:
proc(string)void error;
---------------- -----
declarer var
with
proc (string) void error := (string s): puts (s);
---- -------- ---- -----
de cla rer var
or
ref proc(string)void error;
--- ---------------- -----
-------------------- var
declarer
with
ref proc (string) void error;
--- ---- -------- ---- -----
--- ------------------ var
----------------------
declarer
>>
>> ```
>> { Space after formal parameters pack in routine text }
>> json_foreach_elem(a, (ref JSON_Val v) void: len +:= 1)
>>
>> { No space after parameters pack in procedure and operator
>> declarators }
>> proc(string)void error;
>>
>
> In the line just above, is the no space between proc and ( a result of your
> procedure call rule previously? Or is this a separate rule?
It is the rule above "Also in declarers, do not put a space after `op'
or `proc' and the parameter modes pack."
>
>> ```
>>
>> ### Spaces within packs
>>
>> With "pack" we refer to the following source constructs which are
>> collections of other constructs enclosed between `(' and `)' symbols:
>>
>> * The actual parameters in a call.
>> * The formal parameters in a routine text.
>> * The fields in a struct mode declarator.
>> * The modes of the united modes in an union mode declarator.
>> * The modes of the parameters in an operator or procedure declarator.
>>
>> Spaces are optional after commas in packs when both the preceding and
>> following symbols are tags.
>>
>> Put a space after commas in packs when the next construct is not a
>> tag, but only if the preceding construct is a tag.
>>
>> Do not put spaces before commas in packs.
>>
>
> I like the above taken as a whole. Looking at your examples below I find
> the text quite readable.
>
> I wonder if things like Symbol a,b would work as well if it were Symbol
> aReallyLongVariableName,anotherReallyLongVariableName?
You cannot have upper-case letters in tags in SUPPER stropping.
So it would be:
Symbol a_really_long_var_name, another_long_var_name
>
>>
>> Examples:
>>
>> ```
>> { Spaces are optional around commas surrounded by tags }
>> process(socket, resp, fragmented);
>> process(socket,resp,fragmented);
>> op E = (Symbol a,b) bool: a = b;
>> op E = (Symbol a, b) bool: a = b;
>>
>> { Space after commas separating a non tag and a tag }
>> op E = (Symbol s, Word w) bool: s E w;
>> mode M = struct (int i, real r);
>>
>> { No spaces in commas separating non tags }
>> proc(int,string,[]real)int callback;
>> op(intint)int handler;
>> mode Data = union (void,bool,int)
>> ```
>>
>> ### Spaces in row displays
>>
>> Within row displays spaces are optional after commas, but please never
>> put spaces before commas.
>>
>> ```
>> { Spaces are ok after commas in row-displays }
>> []int a = (1,2,3);
>> []int b = (1, 2, 3);
>> []string names = ("jemarch",
>> "mnabipoor",
>> "pietr0");
>> ```
>>
>> Agreed
>
>
>> ### Spaces in formulas
>>
>> Do not put spaces after monadic operators whose representation is not
>> a bold word.
>>
>> However, if the monadic operator is represented by a bold word, always
>> put a space between the operator and the operand, even when the
>> operand starts with a parenthesis.
>>
>> Always put spaces before and after dyadic operators if the formula is
>> not parenthesized. Spaces are optional if the formula is
>> parenthesized, provided the operator is not represented by a bold
>> word.
>>
>
> I like the above but again I wonder if spaces separating names and
> operators are not more advisable when the names are long?
Not sure I follow. Could you give an example of this?
>
>>
>> Examples:
>>
>> ```
>> { No space after non-bold monadic operators }
>> int i = -10;
>>
>> { Always a space after bold monadic operator }
>> int i = ABS (base + offset)
>>
>> { Spaces in dyadic opeator }
>> total := a + b;
>> index := cnt +:= 1;
>> total := (a + b);
>> index := (cnt +:= 1);
>> total := (a+b);
>> index := (cnt+:=1)
>> ```
>>
>> ### Spaces in bounds
>>
>> Do not put spaces after the bounds of a declarer.
>>
>> Also, do not put spaces directly within the bounds of a declarer,
>> unless for indentation purposes. Since bounds can contain any unit,
>> the general rules apply within these.
>>
>
> Agreed.
>
>>
>> Examples:
>>
>>
>> ```
>> { No spaces after bounds in declarers }
>> mode List = [10]int,
>> MatrixList = [10][3,3]int,
>> Numbers = []union (int,real);
>>
>> { No spaces directly within bounds in declarers }
>> mode MyString = [1:10@]MyChar,
>> DynamicTable = [read_int(10, 20),
>> read_int(10, 20)]char;
>> ```
>>
>> ### Spaces in indexers and trimmers
>>
>> Algol 68 allows using `(' and ')' instead of '[' and ']' in bounds and
>> slices to represent the SUB and BUS symbols. This is supported by ga68
>> via the `-fbrackets' command-line option in order to ease the porting
>> of old code, and it is disabled by default. Please always use square
>> brackets for indexing in new code.
>>
>> While indexing and trimming a multiple, never put a space between the
>> indexed tertiary and the SUB symbol.
>>
>> Do not put spaces direcly within indexers and trimmers, unless for
>> indentation purposes. As an exception to this rule, you can put a
>> single space before the "at" operator `@' if desired.
>>
>
> Agreed. For consideration, do we reject the following use of a space after
> a SUB?
>
> a[ 1] := "foo";
> a[ 2] := "bar";
> ...
> a[ 9] := "goz";
> a[10] := "furb";
> ...
>
> Ie for emphasizing the sequential nature of the index values?
I think that is fine. It is covered by "unless for indentation
purposes"?
>
>>
>> Examples:
>>
>> ```
>> { No space between tertiary and '[' }
>> int i = a[i];
>> int i = a[10:20]
>>
>> { No direct spaces within trimmers and indexers, but before @ }
>> []int a = b[2:5@10];
>> []int c = d[10:20 @1];
>> ```
>>
>> ## Comments
>>
>> Use "foo" to refer to formal parameters when documenting procedures or
>> operators.
>>
>> Use `whatever' to refer to any other source construct that is not a
>> formal parameter.
>>
>
> Just to be clear, those marks around whatever above, are they single
> apostrophes? Because in the above the leftmost looks like the "open
> apostrophe" and the rightmost looks like the single apostrophe.
Yes, these are ` and '.
There is a long tradition in GNU for using ` and ' for quoting. Some
people think these don't look good when using certain fonts, and prefer
using some of the Unicode apostrophes instead. But I personally dislike
using non-ASCII characters in "actionable" content. Like, nowadays, you
cannot easily search for the end of a quoted message from GCC if your
locale is unicode. It sucks :(
>
>>
>> Examples:
>>
>> ```
>> int error_hash = 0;
>>
>> { Return a hash code for the string "s", or `error_hash' if the string
>> is too long. }
>>
>> proc hash_string (string s)
>> ```
>>
>> ## Syntactic Conventions
>>
>> ### Closed clauses
>>
>> Algol 68 allows using `(' an `)' instead of `begin' and `end' to
>> delimit closed clauses. In fact, parenthesized expression in other
>> programming languages are realized in Algol 68 with closed clauses, in
>> a very orthogonal way. Both forms are useful and can generally be
>> used according to the programmer's taste. However, this section
>> contains a few guidelines and recommendations on this regard.
>>
>> Do not use parentheses for closed clauses that span in a single line,
>> regardless of the context. Having `begin' and `end' symbols in the
>> same line looks weird and confusing.
>>
>
> I'm confused by the above - do you mean "DO use parentheses..."?
Yeah, typo. Just corrected it.
>
>>
>> As a general rule, always use parentheses in closed clauses that are
>> operands in a formula. Exceptionally, using `begin' and `end' in
>> formula operands may be preferable if the operand contains many
>> declarations and units, and only if it spans for more than one line.
>> In this case, however, plese consider factoring the code in the
>> operand into a routine and replace it with a procedure call.
>>
>
> Reasonable!
>
>>
>> The preferred indentation for a closed clause whose contents span for
>> more than one line, and that uses `begin' and `end' symbols as
>> delimiters, is to indent the contents right at the right of the
>> `begin' symbol. The `end' symbol shall then be placed in its own
>> line, with the same indentation level than the opening symbol.
>>
>
> I'm a big fan of indents every constant N spaces (and not because I agree
> with Python's perspective of making indents lexically significant).
As mentioned above, my problem with constant indentation steps in Algol
68 is that it doesn't play well with "then", "in", "do", "else" etc,
even if you put them as tails.
> Also, people like me who read their emails with non-fixed-width fonts just
> don't get the impression of alignment using the proposed scheme.
Hehe, reading code with not monospaced fonts is _both_ a sin and a
penance ;)
>
>>
>> If the closed clause contains empty lines then it is ok to put the
>> first unit or declaration in the line after `begin'. This usually
>> happens when the closed clause is the body of a long routine text.
>>
>
> I don't like multiline closed clauses that hang something out after the
> 'begin' as I find it's kind of invisible.
Yes I somewhat agree.
The reason for this rule is that:
begin foo;
bar;
baz
end
looks like one thing. But:
begin foo;
bar;
baz
quux
end
looks like two disconnected things. Doing:
begin
foo;
bar;
baz
quux
end
alleviates the problem a bit IMO.
>
>>
>> The preferred indentation for a closed clause whose contents span for
>> more than one line, and that uses `(' and `)' symbols as delimiters,
>> is to indent the contents right at the right of the `(' symbol. The
>> ')' symbol finishing the closed clause shall not be placed in its own
>> line.
>>
>
> Again I'm much more of a fan of constant width indents. Particularly small
> indents are very hard to spot (like this one space to accommodate a ( on
> the previous line.
>
> To me this is especially true with a reference declaration which should be
> highly visible and aligned with the code that uses it immediately
> following.
>
>>
>> ```
>> { No `begin' and `end' in the same line }
>> int i = 2 + (3+4);
>> int i = 2 + (int i = random(); i % 10 );
>> bool test = case v in (string): (puts (s); true) out false esac;
>>
>> { Closed clauses as formula operands }
>> int i = 2 + (int cnt := 0;
>> to UPB data[@1] do cnt +:= 1 od;
>> cnt)
>> int j = 2 + begin int cnt := 0;
>> to UPB data[@1] do cnt +:= 1 od;
>> cnt
>> end
>>
>
> Reading this in a proportionally spaced font, the first instance of "to
> UPB..." is aligned with the "+" on the previous line; the second is aligned
> with the "e" in "begin".
>
> I know I indicated at the beginning of my comments that screen geometry
> encourages me to avoid making any extra lines, butI prefer this approach
>
> int i = 2 + (
> int cnt := 0;
> to UPB data[@1] do cnt +:= 1 od;
> cnt)
> int j = 2 + begin
> int cnt := 0;
> to UPB data[@1] do cnt +:= 1 od;
> cnt
> end
I find that style rather confusing.
>
>>
>> { Closed clause with no empty lines }
>> proc parse_number = int:
>> begin int num := 0;
>> while num := num * 10 + ABS ch - ABS "0";
>> isdigi(getachar)
>> do ~ od;
>> ungeachar(ch);
>> num
>> end;
>>
>
> Again in my proportionally spaced font world, the "w" of "while" appears
> under the "i" in "begin"; the "i" in "isdigi" appears between the "l" and
> the "e" of "while".
>
> Plus there's that "int num := 0;" hiding next to the "begin" which (in my
> opinion) should have itself been on the previous line, like this:
>
> proc parse_number = int: begin
> int num := 0;
> while num := num * 10 + ABS ch - ABS "0";
> isdigi(getachar)
> do ~ od;
> ungeachar(ch);
> num
> end { parse_number };
Yes that "hidding" is what makes me sometimes to do this intead:
{ Closed clause with no empty lines }
proc parse_number = int:
begin
int num := 0;
while num := num * 10 + ABS ch - ABS "0";
isdigi(getachar)
do ~ od;
ungeachar(ch);
num
end;
What about this:
If the closed clause contains empty lines, or if the line preceding
the closed clause would have the effect of "hiding" the first line in
the closed clause, then it is ok to put the first unit or declaration
in the line after `begin'. This usually happens when the closed
clause is the body of a long routine text.
and the example:
{ Closed clause with no empty lines }
begin int fd = fopen ("data', file_o_rdonly")
puts ("first line: " + fgets (fd, 0));
fclose (fd)
end;
>
>
>> { Closed clause with empty lines }
>> proc main_proc = int:
>> begin
>> { Auxiliary procs }
>> proc aux1 = int: ...;
>> proc aux2 = int: ...;
>>
>> { Computation }
>> aux1;
>> aux2;
>>
>> { Result }
>> aux1 + aux2
>> end
>>
>
> In the above I prefer that the "begin" follow the "int:" and a space, like:
>
> proc main_proc = int: begin
>
> I see no additional clarity achieved by putting the "begin" on its own
> line.
Well thats the traditional two schools:
foo {
}
vs.
foo
{
}
I come from a GNU background, so I favor the second :)
Kernel hackers would favor the first.
>
>>
>> { Indentation of closed clauses using `(' and `)' delimiters }
>> (int num := 0;
>> while num := num * 10 + ABS ch - ABS "0";
>> isdigi(getachar)
>> do ~ od;
>> ungeachar(ch);
>> num)
>> ```
>>
>
> I don't think I would ever do the above with '(' and ')'. I think of the
> use of those marks in relation to shorter spans of code, particularly if
> the value of 'num' is to be consumed rather than (apparently) being thrown
> away here; or alternatively, decide never to use 'begin' and 'end'.
That example was missing a line:
{ Indentation of closed clauses using `(' and `)' delimiters }
proc parse_number = int:
(int num := 0;
while num := num * 10 + ABS ch - ABS "0";
isdigi(getachar)
do ~ od;
ungeachar(ch);
num)
Now I realize I am missing a section:
### Procedure and operator declarations
In procedure and operator declarations, if the body of a routine text
starts with 'begin', put it at the same indentation than the `pub',
`proc' or `op'. Otherwise, indent it three spaces to the right
relative to the `pub' `proc' or `op'.
Examples:
```
{ Body of routine is a `begin'..`end' closed clause }
proc checked_div = (int a,b) int:
begin
if b = 0 then fatal ("div by zero") fi;
a % b
end;
{ Body of routine does not start with `begin' }
proc checked_div = (int a,b) int:
(b = 0 | fatal ("div by zero"); skip | a % b);
{ Body of routine is not a closed clause }
proc checked_div = (int a,b) int:
if b = 0
then fatal ("div by zero"); skip
else a % b
fi;
```
>
>>
>> ### Conditional clauses
>>
>> If a conditional clause is small enough to fit in a single line
>> without occupying most of it, just do it.
>>
>
> I'm not keen on a rule like "without occupying most of it". I would lean
> more in the direction of complexity; if a conditional clause (or really any
> enclosed clause) is still clear and not of excessive length when written on
> a single line, just do it.
>
> By "clear" here I mean that it doesn't benefit by having the then-part,
> else-part etc separated out to increase the readability / clarity.
Agreed. I have adopted your wording.
But not any enclosed clause, because this doesn't apply to
`begin'..`end' closed clauses :)
>
>>
>> Start the enquiry clause in the if-part of a conditional clause right
>> after the `if' symbol, not in the next line.
>>
>
> Agreed!
>
>>
>> The serial clauses in the then- and if-parts of the conditional clause
>> shall be indented five positions right, which is the length of both
>> the `then' and `else' symbols plus one.
>>
>
> Again, I prefer the constant width indent. Also I don't like seeing 'then'
> on its own line as I don't feel it offers any additional clarity.
Again, how do you handle the `else' without having it alone in its own
line?
>>
>> The first declaration or unit in the tehn- and if-parts shall be
>> placed in the same line than the `then' and `else' symbols,
>> respectively.
>>
>
> Again I don't care for this as stuff immediately following 'begin', 'then',
> 'else', 'do' etc in a multi-line construct tend to disappear from my
> consciousness.
>
>>
>> Place the `fi' closing symbol in its own line, with the same
>> indentation level than the matching `if'. The exception to this rule
>> is when the conditional clause has no else-part and the then-part
>> spans for a single line that is not too long. In that case, place the
>> `fi' in the same line than `then'.
>>
>
> The above doesn't work for me because the then-part is never on its own
> line.
>
>>
>> Examples:
>>
>> ```
>> { Very small conditional clause in a single line }
>> if idx < 0 then fatal("invalid idx") fi
>>
>> { Short conditional-clause with `fi' in the same line
>> than `then' }
>> if argc /= 3
>> then puts("expected two arguments'n") fi
>>
>> { A conditional-clause that spans for several lines }
>> if a > 10
>> then puts("truncating");
>> a := 10
>> fi
>> ```
>>
>
> In the above in proportionally spaced text the "a" appears under the "n" of
> 'then'.
>
>>
>> ### Loop clauses
>>
>> If a loop clause is small enough to fit in a single line without
>> occupying most of it, just do it.
>>
>> If a loop clause spans to two lines, and the second line is not too
>> long, you can put `od' in the same line than `do'.
>>
>> If a loop clause spans to several lines, please put the `do' symbol in
>> its own line, indented to the same level than the clause's frobyts.
>>
>
> Same general mild disagreements as for the 'if' previously.
>
>>
>> Examples:
>>
>> ```
>> { Very short loop-clause in a single line. }
>> for a to argc do puts ("arg: " + argv[a]) od;
>>
>> { Short loop-clause with `od' in the same line than `do' }
>> for i from LWB a to UPB a
>> do total +:= a[i] od
>>
>> { A loop-clause that spans for several lines }
>> while NOT exit
>> do string cmd = get_command;
>> process_command(cmd)
>> od
>> ```
>>
>> ### Case and conformity clauses
>>
>> Do not write a case or conformity clause in a single line, unless
>> you are using the brief form. Unlike conditional and loop clauses,
>> these are difficult to read.
>>
>> Please put the `in', `out' and `ease' symbols in their own lines, with
>> the same indentation level than the matching `case'.
>>
>> Start the choices right after the `in' symbol, in the same line. All
>> the choices may fit in a single line. If they don't, please put each
>> choice in its own line.
>>
>
> You can probably figure out my renegade perspective by now:
>
> - 'case' and 'in' always appear on the same line
> - 'ouse' and 'in' always appear on the same line
> - things only ever follow 'in' if the whole expression fits on one line
>
>
>> ```
>> { Short case clause }
>> case i
>> in 100, 200, 300 out 0 esac;
>>
>
> So for me this would be ok as:
>
> case i in 100, 200, 300 out 0 esac;
>
> -or-
>
> (i | 100, 200, 300 | 0);
>
> -or-
>
> case i in
> 100, 200, 300
> out
> 0
> esac;
>
>>
>> { Long case clause }
>> case i
>> in 100,
>> 200,
>> 300
>> ouse i % 100
>> 100,
>> 200,
>> 300
>> esac;
>>
>
> You're missing an 'in' for your 'ouse'. For me this would be
Fixed.
{ Long case clause }
case i
in 100,
200,
300
ouse i % 100
in 100,
200,
300
esac;
>
> case i in
> 100,
> 200 ,
> 300
> ouse i % 100 in
> 100,
> 200,
> 300
> esac;
>
>
>> { Long conformity clause }
>> case v
>> in (void): "empty",
>> (bool b): (b|"true"|"false"),
>> (string s): s
>> esac
>> ```
>>
>
> For me this would be
>
> case v in
> (void): "empty,
> (bool b): (b | "true" | "false"),
> (string s): s
> esac
Yes I actually also prefer that with spaces within.
I added this:
### Spaces in brief clause forms
It is generally a good idea to have spaces around `|' and `|:' within
the brief forms of conditional clauses, case clauses and conformity
clauses.
When the brief forms are very short and the units are number
denotations, it may be more clear to not use spaces, especially when the
form is an operand in a formula.
Examples:
```
{ Space around | and |: in brief forms }
(v | (void): "empty", (bool b): (b | "true" | "false"))
{ No spaces may be more readable sometimes }
int n = 2 + (c>3|10|20);
```
>>
>> ### Contracted declarations
>>
>> Please don' be shy to use contracted forms of declarations. They can
>> make the program much more readable and they make it easier to add new
>> declarations, because they prevent writing the same text again and
>> again.
>>
>
> Agreed. Somehow as well I think that there is merit in trying to keep
> related declarations together and I would call your examples below
> "related" based on the names declared. My reason for this "relatedness"
> idea is that if it becomes time to convert some code into a procedure, it's
> easier to find the related declarations and excise them along with the code.
>
>>
>> However, care should be taken when declarin operators and procedures.
>> In these cases, contracted declarations should only be used when
>> declaring very short, one or two lines long routines. The last
>> routine in the list of joined declarations can be a bit longer.
>>
>> Examples:
>>
>> ```
>> { Contracted declarations lead to compact and very
>> readable code }
>> int disconnected = 0, connected = 0, unknown = 2;
>> pub ref JSON_Val json_no_val = nil,
>> ref JSON_Elm json_no_elm = nil;
>> ref JSON_Fld json_no_fld = nil;
>>
>> { Use contracted declarations for short routines }
>> op + = (States ss, State s) States: MoreStates (heap States := ss, s),
>> + = (Transitions ts, Transition t) Transitions:
>> MoreTransitions (heap Transitions := ts, t)
>> ```
>>
>> ### Brief clause forms
>>
>> The obvious context where to use the brief forms of conditional, case
>> and conformity clauses is when these clauses appear as operands in
>> formulas. They match well with parenthesized closed clauses.
>>
>> It is also ok to use brief forms of clauses out of formulas,
>> especially inside case and conformiy clauses. But please be careful,
>> as brief forms may be confused sometimes.
>>
>
> Agreed, but in general I think using brief forms should either lean to
> making compact and readable or a wholesale avoidance of the long form
> (which is probably kind of extreme).
>
>>
>> Examples:
>>
>> ```
>> { Brief forms in formulas }
>> int res = (a=0|fatal("div by zero"); skip|den/a);
>>
>
> I find the above too compact for readability; I like spaces around the "|"
> and "|:" forms.
I changed this example, according to the new rule above.
>
>>
>> { Brief forms out of formulas }
>> for i to ELEMS str
>> do char newline = REPR 10, tab = REPR 9, c = str[i];
>> (c = "\" | res +:= "\\"
>> |: c = newline | res +:= "\n"
>> |: c = tab | res +:= "\t"
>> | res +:= c)
>> od
>> ```
>>
>
> I would not use the brief forms here. I find in the above code it takes a
> few reads to realize that the goal is to append to 'res'. My way would be:
>
> for i to ELEMS str do
> char newline = REPR 10, tab = REPR 9;
> char c = str[i];
> if c = "\" then
> res +:= "\\"
> elif c = newline then
> res +:= "\n"
> elif c = tab then
> res +:= "\t"
> else
> res +:= c
> fi
> od { for i to ELEMS str }
>
> Then I would probably notice that the objective of the do ... od is to
> append a character to 'res' and refactor to
>
> for i to ELEMS str do
> char newline = REPR 10, tab = REPR 9;
> char c = str[i];
> res +:= (c = "\" | "\\" |: c = newline | "\n" |: c = tab | "\t" | c)
> od
Yes that is a bad example, because the loop clause doesn't return a
value.
>
>>
>> ## Naming
>>
>> Unlike most other programming languages, which are not stropped, in
>> Algol 68 it is possible to have tags with the same name than reserved
>> words, by appending an underscore character to the tag. For example, a
>> tag `if' can be written as `if_'. It is important to note that the
>> trailing underscore is not part of the tag: it is just a stropping
>> artifact. This is always better than contriving artificious synonyms
>> that are often confusing or too long. A copying routine has arguments
>> "from" and "to"? Call them `from_' and `to_'. A struct mode has fields
>> "in" and "out"? Call them `in_' and `out_'.
>>
>
> Just because I hate typing _ so much, I would more likely choose parameter
> or field names that disambiguated with other letters, but I take your
> point.
>
>>
>> Please use fully uper-case bold words for operator indicants. This
>> makes it easier for text editors to highlight them in a different
>> style than mode indicants, and look more symmetrical in case of dyadic
>> operators. For example, use `IN' and not `In'.
>>
>
> Is 'IN' really an operator? I think not. Maybe 'ABS' would be a better
> example?
It could be an operator. But yes I changed to ABS / Abs, it is a better
example.
> To this I would add "_ or camelCase - choose one". I would also strongly
> prefer capitalizing the first letter of a mode.
You cannot use camelCase in tag in SUPPER stropping.
>
>>
>> ## Programing style
>>
>> This section contains some recommndation on the usage of the
>> facilities of the language.
>>
>> ### Writing routines
>>
>> Use routines liberally! Routines are cheap, very easy to write thanks
>> to the excellent Algol 68 syntax for routine texts, and first-class
>> citizens in the language. They also have access to the lexical
>> environment. So if you find yourself wanting to write a macro in
>> order to repeat some little calculation, just write a small procedure
>> or operator instead.
>>
>
> To the above I would add
>
> - choose identifiers that are expressive of meaning in order to clarify
> both the intent of the procedure or operator and the code written that uses
> it
> - consider using overloaded operators in preference to procedures with
> united mode parameters to encourage users of the operator to create new
> versions of the operator for different parameter types, rather than leaving
> the users trying to figure out how to hack the united mode definition
I added these to the document.
> - consider using procedures with united mode parameters that are not
> declared in a separate mode declaration unless there is to be more than one
> such procedure
I added:
The high level of orthogonaliy of Algol 68 combined with the
structural type equivalence and the nice compact syntax of declarers
makes mode names way less relevant than in many other programming
languages. In particular if a routine takes a parameter that is an
united mode, and that particular united mode is either not used
anywhere else or very short, just write the declarer, you don't have
to name it first.
>
>> Please make good use of the lexical block structure of the programming
>> language: is is there to be used. In little local auxiliary routines,
>> never add arguments just to pass a value thas is in the environment:
>> make the routine access the value itself.
>>
>
> I would temper the above by the distance between the routine declaration
> and the declaration of the parameter it accesses outside itself.
I changed to:
Please make good use of the lexical block structure of the programming
language: is is there to be used. In little local auxiliary routines,
do not add arguments just to pass a value thas is in the environment,
unless the declaration of the later is very far away from the routine
text: make the routine access the value itself.
>
>>
>> ### Nihils
>>
>> Never use `nil' directly in identity relations; it is very error
>> prone. It is better to define "nihils" for all reference modes that
>> are likely to appear in one.
>>
>
> This is SUPER IMPORTANT. I have shot myself in the foot so many times with
> this that it's amazing I can still crawl.
>
>>
>> Examples:
>>
>> ```
>> mode Node = ...;
>> ref Node no_node = nil;
>> while n :/=: no_node do ... od
>> ```
>>
>
> Thanks Jose! Please know that I will bow to the majority even though my
> preferred style differs occasionally from your rules above.
Your feedback is _priceless_, thank you!
More information about the Algol68
mailing list