[RFC] GNU Algol 68 Coding Guidelines
chris hermansen
clhermansen@gmail.com
Mon Jan 12 19:31:35 GMT 2026
Good morning everyone,
Jose, this is all such a worthwhile discussion! I want to reiterate I'm
fine to bow to the decision of others; my main reason for commenting
further is to clarify my position in case it's useful.
On Mon, Jan 12, 2026 at 4:54 AM Jose E. Marchesi <jemarch@gnu.org> wrote:
>
> > 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.
>
The difference in preferences may be at least somewhat related to name
choices. I sometimes find my choice for names tends to the lengthy and
therefore that my lines get longer. Also I tend to use a smaller font that
gives me room for manœuvre. I seldom use anything other than a GNOME
terminal for coding (I do have one Java project I inherited in NetBeans but
that has mostly confirmed my overall distaste for complex IDEs). My
terminal window is typically a big chunk of a 1920x1080 window; when I'm
writing new code that doesn't involve looking at anything else, it's the
entire screen.
Having said that, I feel it's better to break really long lines where "it
makes sense" and even consider double indents on the following line to show
that it's a continuation (this is a default formatting thing that NetBeans
does that I like).
I take your point about lines that are too long for comfortable reading. I
think that "too long" is somewhat language dependent as well and also
relates to the length of name choices.
>
> > - 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?
>
This is a fun point! To me "then" is punctuation separating the condition
from what to do about it but "else" is counterpart to "if" and so belongs
at the same indentation level as "if"
if a > 10 then
blah
else
bleh
fi
You see this in C, Java when the then-part and else-part are single
statements
if (a > 10)
blah
else
bleh
and (the cursèd) Python
if a > 10:
blah
else:
blah
and an interesting take on it with Go which requires { }
if a > 10 {
blah
} else {
bleh
}
Back in the 1980s and 1990s when I still did a lot of work in Pascal I used
to write
if a > 10 then begin
blah
end else begin
bleh
end
Back to C and Java for a minute, I really dislike seeing
if (a > 10)
{
blah
}
else
{
bleh
}
Aaaaaaaaaaaaaaaaaaaanyway speaking of taking up too much vertical space!
I would prefer to write
if a > 10
then
blah
else
bleh
fi
than have variable indentation levels or stuff stuck on the same line after
then and else.
>
> 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 can be the case, but sometimes there is just a lot to get done
between, for example:
if land_cover_type = non_vegetated then
{ many tens of things to check and calculate }
elif land_cover_type = herbaceous then
{ many tens of things to check and calculate }
elif land_cover_type = shrub then
{ many tens of things to check and calculate }
else { forest }
{ many tens of things to check and calculate }
fi { forest}
(over-sharing my own problem space here)
> 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.
>
Sorry I wasn't clear, I was advocating
2 * ((a > 0 | 10 | 20) + 5)
2 * (a > 0 | 10 | 20)
and the like. I don't feel the need for spacing in a sequence of opening
nor closing parentheses,
Are you following me?
>
> >>
> >> 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
>
Hmm I see your point. I think I generally use the form
proc error = (string s) void:
put(s)
and have only used the other form when passing a proc as a parameter or in
a structure declaration. But in those few cases I have always spaced it
out more.
I can live with the "compact" form.
>
> >>
> >> ```
> >> { 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."
>
Understood!
>
> >
> >> ```
> >>
> >> ### 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
>
I seem to feel I read that as a possibility in some text but I can't find
it now. I suppose I was extrapolating from these paragraphs in the
documentation:
For example, RecRset, Rec_Rset and RECRset are all different ways to
> represent the same
> mode indication. This allows to recreate popular naming conventions such
> as CamelCase.
> As in the other stropping regimes, the casing of the letters and the
> underscore characters
> are not really part of the mode or operator indication.
To me "CamelCase" would refer to a mode and "camelCase" would refer to a
name declared to be of mode "CamelCase".
I feel I should put in a good word for allowing names to include upper case
letters as long as they aren't the first letter, which I have come to
prefer over using _. I find the _ character difficult to type without
interrupting my flow as my right "pinky" stabs away at a few wrong choices
before hitting the right one (there's entirely too much stuff going on in
the upper right quadrant of the keyboard).
>
> >
> >>
> >> 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?
>
I'm suggesting that those of us who seem to find ourselves using long names
are not serving ourselves well by expressions like:
foo := a_really_long_variable_name+another_really_long_variable_name
better to use a space before and after `+' here to increase the readability
foo := a_really_long_variable_name + another_really_long_variable_name
> >
> >>
> >> 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"?
>
Cool!
>
> >
> >>
> >> 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 '.
>
Ok, understood.
>
> 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 :(
>
I see your point. I have never explicitly used the "left single quote"
except where it's operator-like, for example in the shell where it's used
to cause evaluation of an expression.
One thing that regularly annoys me is when I'm writing about a programming
language in some text processor that converts leading apostrophe and quote
to left single quote and left double quote at the beginning of a quoted
phrase and right single quote and right double quote at the end of a
phrase, because then the code snippet can't be copied, pasted and run. But
that's not immediately relevant to your point above.
>
> >
> >>
> >> 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.
>
I like this as modified.
>
> >
> >>
> >> 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.
>
I think we have a different conceptual basis here. For me the purpose of
the indent is emphasizing the fact that the clause is enclosed, not the
nature of the enclosure. So
if a > 10 then
b := 42
fi;
if b = 42 then
c := 99
elif b = 0 then
c := 999
else
c := 9999
fi;
for i from 1 to 99 while a[i] /= "blort" do
uppercase(a[i])
od;
x := case i in
100,
200,
300
out
999
esac
I use the above approach because in my mental space "then" goes with "if"
or "elif"; "for", "from", "to", "while" and "do" go together; "in" goes
with "case" or "ouse".
When the expressions between "if" or "elif" and "then" or between "while"
and "do" are long or complex I don't have a problem breaking it up on
multiple lines.
I use vi and its auto-indent capability which leaves me consistently
aligned code at constant N spaces. I don't know how to set it up so that
it indents variably depending on the length of the preceding element that
opens the enclosed clause.
Two things that occur to me as potential disadvantages of variable
indents. The first is that having a different number of spaces leading
indents looks vertically messy to me. The second is that moving code
snippets around may require re-indenting (for example moving from a "then"
indent level to a "begin" indent level, when it's time to move code into a
procedure).
>
> > 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 ;)
>
True! But also in textbooks such as McGettrick Algol 68 code is set in
proportionally spaced fonts!
I have a friend, retired now, who during his working life mainly used email
for communicating about code. He still uses pine, or mutt or some such
with monospaced fonts. In my case, the majority of my email is non-code,
so the odd time when I'm including code, I change the font for that
assuming my correspondent is also using HTML mail formatting.
Of course in a serious list like this one I am the odd person out for using
proportionally spaced fonts, but at least I try to not top post :-)
>
> >
> >>
> >> 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.
>
I see your point. For me the need for spaces only occurs when there is
also the need for comments whose presence indicates why there is a need for
spaces:
begin
{ calculate the number of seconds needed to travel to the moon assuming
V0 is 110% minimum earth escape velocity }
several lines of code;
{ calculate the moment where we need to initiate braking to be captured
in a lunar orbit }
several more lines of code;
{ calculate the amount of air needed to make the journey, adding a 50%
safety factor }
a few more lines of code
end
All of which would be better handled with three procedures with explanatory
names.
>
> >
> >>
> >> 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.
>
We'll probably start to see more opportunities for this when we all start
to use more lambdas
each delimited line("test.csv", "|", (String line, []String fields, Int
linecount) Void: begin
String to map := fields[1], from map := fields[2];
if contains key(ht,from map) then
set val(ht, from map, STRVAL(get val(ht,from map)) + ";" + to map)
else
set val(ht, from map, to map)
fi
end);
int i = 2 +
>
> >
> >>
> >> { 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;
>
I prefer mine to the above, but I prefer the above to
...
begin int num := 0;
...
if that helps!
>
> 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;
>
I still prefer
begin
int fd = fopen ("data', file_o_rdonly")
puts ("first line: " + fgets (fd, 0));
fclose (fd)
end;
But as I said I can live with the above.
>
> >
> >
> >> { 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.
>
In my view of the universe, you are driving this bus and I am but a rowdy
passenger in the back; so I bow to your preferences!
>
> >
> >>
> >> { 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)
>
I would never do that. To me the ( should live in the same place as
"begin" would live. I've never really been satisfied with the ) taking a
different position than the "end" would take, but I can live with that.
>
> 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;
> ```
>
The above seem consistent to me given that here the leading "(" on the line
following "proc" in the second example is the brief "if" and not a "begin".
>
>
> >
> >>
> >> ### 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 :)
>
Sure, because ideally if the enclosed clause surrounded by "begin" and
"end" is that simple, it's probably better with "(" and ")". Is that
right?
>
> >
> >>
> >> 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?
>
if conditional-expression then
then-part-computations
else
else-part-computations
fi
That is I want "else" on its own line because it begins the alternative to
"if", not the alternative to "then"; "then" is just the token that closes
off the conditional-expression.
>
> >>
> >> 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);
> ```
>
Possibly. I come down to the same two reasons for avoiding this as with
the more general case previously: 1) it may be easier to refactor using
regular expressions if spaces are around things like "|" and 2) the "|" can
be obscured by longer names and/or more complicated expressions.
But I see how your bigger-font shorter-lines than my situation can lead you
to this.
>
>
> >>
> >> ### 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.
>
Ok. But even if it were an "if" - "fi" I think I would follow the same
reasoning path, which diverges from your point here but I feel strongly
that one of Algol 68's strengths is in "everything is an expression" which
allows me to minimize the number of places in my code where a value is
updated.
>
> >
> >>
> >> ## 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.
>
I think IN is already spoken for by CASE / OUSE?
>
> > 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.
>
(crying symbol) but I WANT to!!!
>
> >
> >>
> >> ## 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.
>
I like it!
>
> >
> >> 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.
>
I like it!
>
> >
> >>
> >> ### 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!
>
Wow, well I really appreciate the opportunity to provide it, and the kind
way in which you respond.
--
Chris Hermansen · clhermansen "at" gmail "dot" com
C'est ma façon de parler.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://gcc.gnu.org/pipermail/algol68/attachments/20260112/be15f3ef/attachment-0001.htm>
More information about the Algol68
mailing list