Proposal: Standardize the well-known -ROT

Informal

This page is dedicated to discussing this specific proposal

ContributeContributions

EricBlakeavatar of EricBlake [416] Standardize the well-known -ROTProposal2025-10-10 14:18:47

Author:

Eric Blake

Change Log:

2025-10-10 Initial proposal

Problem:

When doing stack-heavy manipulation (without locals), it is not uncommon to want to grab a single cell located underneath a cell pair, modify it, and then pull the cell pair back to the top of the stack. Equivalently, this can be viewed as pushing the single cell back under the cell pair, or undoing the effects of rot.

Several proposed example implementations have relied on use of the word -rot, because it is well-known across a number of Forth implementations, only to need correction when it is pointed out that the standard does not yet provide a single-word solution for this desired stack effect.

Solution:

Standardizing -rot will guarantee that library code can use this word if present for "undoing" a rot without worrying about it having different semantics than what most users have come to expect.

A pure-Forth implementation using other standard words is fairly trivial; therefore the new word can be optional. Note, however, that a native implementation of rot typically needs just 4 register moves (including a temporary); implementing -rot as rot rot would naively require 8 register moves, while a native implementation can easily achieve the same 4-move performance of rot.

The suggested pronunciation "m-rote" matches the package name of the public domain implementation given in theforth.net, where "m" is short for "minus"; however, gforth suggests the pronunciation "not_rote". Keep in mind that the standard already pronounces <> as "not-equals" and 0<> as "zero-not-equals", so I'm reluctant to use the pronunciation "not-" on a word that is spelled with - rather than <>.

Typical use:

The standard itself has already suggested using -rot in NR>.

Other comments on the standard (not yet at the level of formal proposals) have mentioned -rot:

Potential future addition of ?: that can define -rot when it is not present

Potential future addition of 2roll that can implement -rot, 2swap, and 2rot.

Proposal:

Add a new glossary entry:

6.1.____ -ROT "m-rote" CORE-EXT
( x1 x2 x3 -- x3 x1 x2 )

Perform a reverse rotation of the top three stack entries.

Rationale: This operation undoes the effects of `rot`.

Reference implementation:

: -rot ( x1 x2 x3 -- x3 x1 x2 ) rot rot ;

Testing:

t{ 1 2 3 -rot -> 3 1 2 }t

(Editorial note: Other than in the subject, this proposal uses lower-case naming of all words, on the grounds that other proposals in flight deal with either making future Forth case-insensitive on standard words, or with ensuring the standard words are converted to upper-case in renderings as needed.)

EricBlakeavatar of EricBlakeNew Version: Standardize the well-known -ROT

Hide differences

Author:

Eric Blake

Change Log:

2025-10-10 Add more suggested changes and additional links, typography fixes

2025-10-10 Initial proposal

Problem:

When doing stack-heavy manipulation (without locals), it is not uncommon to want to grab a single cell located underneath a cell pair, modify it, and then pull the cell pair back to the top of the stack. Equivalently, this can be viewed as pushing the single cell back under the cell pair, or undoing the effects of rot.

Several proposed example implementations have relied on use of the word -rot, because it is well-known across a number of Forth implementations, only to need correction when it is pointed out that the standard does not yet provide a single-word solution for this desired stack effect.

Solution:

Standardizing -rot will guarantee that library code can use this word if present for "undoing" a rot without worrying about it having different semantics than what most users have come to expect.

Standardizing -rot will guarantee that library code can use this word if present for "undoing" a rot, without worrying about it having different semantics than what most users have come to expect.

A pure-Forth implementation using other standard words is fairly trivial; therefore the new word can be optional. Note, however, that a native implementation of rot typically needs just 4 register moves (including a temporary); implementing -rot as rot rot would naively require 8 register moves, while a native implementation can easily achieve the same 4-move performance of rot.

The suggested pronunciation "m-rote" matches the package name of the public domain implementation given in theforth.net, where "m" is short for "minus"; however, gforth suggests the pronunciation "not_rote". Keep in mind that the standard already pronounces <> as "not-equals" and 0<> as "zero-not-equals", so I'm reluctant to use the pronunciation "not-" on a word that is spelled with - rather than <>.

Typical use:

The standard itself has already suggested using -rot in NR>.

The standard itself has already suggested using -rot in NR> (note that the original forth-2012.pdf did not have section E.15.6.2.1940; I did not research which later revision introduced reference implementations).

The proposal to add find-name to the standard utilizes -rot, resulting in the forth21-1.pdf draft including a blurb listing an [undefined] -rot [if] implementation.

Other comments on the standard (not yet at the level of formal proposals) have mentioned -rot:

Potential future addition of ?: that can define -rot when it is not present

Potential future addition of 2roll that can implement -rot, 2swap, and 2rot.

Potential future addition of 2roll that can implement -rot, 2swap, and 2rot.

Proposal:

Add a new glossary entry:


6.1.____ -ROT "m-rote" CORE-EXT

6.1.---- -rot "m-rote" Core-Ext

( x1 x2 x3 -- x3 x1 x2 )

Perform a reverse rotation of the top three stack entries.

See: 6.1.2160 rot

Rationale: This operation undoes the effects of rot.


In 6.1.2160 rot, add a cross-reference section:

See: 6.1.---- -rot

Other edits needed (based on forth21-1.pdf):

In E.15.6.2.---- find-name, delete the lines:

[UNDEFINED] -rot [IF]
: -rot ( a b c -- c a b )
ROT ROT
;
[THEN]

In E.17.6.2.2255 substitute, delete the lines:

[UNDEFINED] -rot [IF]
: -rot
\ a b c -- c a b
ROT ROT
;
[THEN]

Reference implementation:

: -rot ( x1 x2 x3 -- x3 x1 x2 ) rot rot ;

Testing:

t{ 1 2 3 -rot -> 3 1 2 }t

(Editorial note: Other than in the subject, this proposal uses lower-case naming of all words, on the grounds that other proposals in flight deal with either making future Forth case-insensitive on standard words, or with ensuring the standard words are converted to upper-case in renderings as needed.)

ruvavatar of ruv

Concerning the name -rot

There is only one historically established standard word (other than "-" itself) whose name begins with a minus sign: "-trailing" .

This word name etymology is: "subtract-trailing-spaces"

  • the part "spaces" is omitted as obvious (therefore "trailing" becomes a nominalized adjective);
  • the verb "to subtract" is represented by the minus sign;

In other known words a leading minus sign also means "to subtract". For example, -trailing-garbage in Forth-2012, -text in Forth-83 Uncontrolled reference words (not a part of the Forth-83 standard word set).

That's why I don't like the name «-rot» for a word that does a reverse rotation.

Other options for naming:

  • unrot, from "unrotate";
  • derot, from "derotate";
  • rev, from "reverse rotate";

Maybe someone can suggest something else?

EricBlakeavatar of EricBlake

Other options for naming:

Using rev for this is too short for my tastes. I would rather use rev in the functional programing sense of reversing a list, perhaps as in ( 5 6 7 3 rev -- 7 6 5 ), ( 4 5 6 7 4 rev -- 7 6 5 4 ).

Of the others you suggested, unrot is nicer than derot to my ears as a native English speaker.

I spent some time playing with the idea in Google Gemini, asking if it could think of alternative names. Its first suggestion was unrot; it also suggested b-rot or brot (backwards-rotate). When I pressed Gemini harder to give me a link that uses b-rot, it gave up and pointed me to https://www.forth.org/forth_intro/unrot.htm and gave an excuse that because -rot is so much more common than other spellings, and despite -rot not being a standard word, Gemini could not find references to use of other spellings. Quoting Gemini, "While I learned the concepts and names for many variants of stack operations, my inability to find an existing URL for B-ROT strongly indicates that it is not a public term. It is possible it was used in a private project, a local dialect of Forth, or a closed-source system that is not indexed on the public web.". Then Gemini tried to convince me that Forth-94 had -rot in its optional tools extension word-set (a lie), before conceding that -rot exists in code samples even before Forth-94 existed. At this point, I can't trust whether Gemini is accurate or hallucinating about b-rot.

Gemini did seem to locate a number of URLs to FIGForth and other implementations of ": -rot rot rot ;" with provenance back to the late 70s, even though it could not find evidence of Chuck Moore ever using -rot. Even if we don't like the naming etymology if we were designing from scratch, -rot really does have the most use in existing Forth variations. At some point, we have to decide whether the standards body should be in the business of prescribing new behavior rather than documenting existing behavior.

That said, a page named "unrot" on forth.org vs. the package on theforth.net named "mrot" vs. gforth's pronunciation "not_rot" vs. Jonesforth calling it "nrot" means that even if we do name it -rot, we have to decide what pronunciation we want. And if "unrot" is the most popular pronunciation, how hard would it be to convince implementations like gforth to add unrot as an alias to -rot just for the better etymology?

Less common, I have seen at least one Forth fork that had -roll as the inverse to roll; by your naming, unroll would be a better spelling. However, unroll is a common enough term in compiler optimizations (duplicating the body of a short loop for fewer branches) that it seems like a shame to apply it to the unrelated meaning of "inverse roll". (I actually like your proposal of poke as an inverse to pick; roll requires so much more work than pick that I'm just fine if there is no inverse for roll in the standard)

ruvavatar of ruv

I agree, of the options considered, the best pronunciation is "unrot", and the best name, I think, is unrot.

Rationale:

  • this name is more consistent with the "un-rot" pronunciation and the naming conventions used in other standard word names;
  • in general, names without special characters are better than with special characters (if the special character does not have a special meaning);
    • note that a leading minus means "to subtract".

whether the standards body should be in the business of prescribing new behavior rather than documenting existing behavior.

In fact, the standards body is also in the business of prescribing new behavior — there are numerous examples of this. Regarding existing practices, I believe it should not standardize bad practices (including unfortunate/inconsistent names).

In this case, a possible solution is to standardize unrot and add a requirement: "If the Forth system provides the word -rot, that word shall have the same semantics as specified for unrot in this glossary entry".

Standardized in this way, it allows programs to do the following:

[undefined] unrot [if] [defined] -rot [if]
synonym unort -rot
[else]
: unrot rot rot ;
[then] [then]

Or simply:

[undefined] unrot [if]
: unrot rot rot ;
[then]

And if "unrot" is the most popular pronunciation, how hard would it be to convince implementations like gforth to add unrot as an alias to -rot just for the better etymology?

It seems, there is no need to convince implementations, as this word is optional.


As for the word inverse to roll — I agree, there is no need for such a word.

Reply New Version