Est. 1989 Intermediate

Lotus Formula

The functional, list-oriented @function language that Ray Ozzie built for Lotus Notes in 1989 by borrowing the formula compiler from the Lotus 1-2-3 spreadsheet - a spreadsheet language transplanted into documents, views, and groupware

Created by Ray Ozzie at Iris Associates, under contract to Lotus Development Corporation

Paradigm Functional, list-oriented, domain-specific (expression language with @functions and @commands)
Typing Dynamic, weak (text, number, time-date, and lists of those; automatic promotion of scalars to lists)
First Appeared 1989
Latest Version Shipped with HCL Notes/Domino 14.5 (June 2025)

Lotus Formula is the name under which programming-language catalogs record the @function-based formula language of Lotus Notes: a small, functional, list-oriented expression language that Ray Ozzie created at Iris Associates and that shipped with Notes Release 1.0 on December 7, 1989. It is a spreadsheet language by ancestry - Ozzie borrowed the formula compiler and decompiler from Lotus 1-2-3 - but a document language by purpose. Where a 1-2-3 formula computes a number in a cell, a Notes formula decides which documents appear in a view, what a field defaults to, whether a paragraph is hidden from a given user, or which records an agent should modify.

The language is known by several names. Lotus and IBM manuals call it simply the “formula language”; developers call it “@Formula” (pronounced “at-formula”) because nearly every construct begins with an @ sign; catalogs that index it as a Lotus product call it Lotus Formula. This encyclopedia has separate entries under two of those names - Notes @Formula and Formula Language - that cover the language as it is used inside Notes today. This page takes the catalog’s framing as its subject: the language as a Lotus language, born from the 1-2-3 spreadsheet, shaped by the company’s formula tradition, and belonging to an era that ended when IBM retired the Lotus name in 2013. The catalog’s classification of it as a functional language in the spreadsheet category, and its status as dormant, are all explained by that framing, and this page examines each.

History & Origins

Lotus and the @function tradition

Lotus 1-2-3, released in January 1983, made the @function the signature of the Lotus house style. Where VisiCalc had a small set of functions written as @SUM, 1-2-3 expanded the library and made formulas the center of the product; by 1989, the year Notes appeared, 1-2-3 was on Release 2.2 and Release 3, and the 1-2-3 macro language was among the most widely used end-user programming facilities of its day. Any product that came out of Lotus in that decade carried the expectation that users would write @IF(...), @LEFT(...), and @SUM(...).

Ray Ozzie was inside that culture. After working at Software Arts, the company behind VisiCalc and TK!Solver, he was recruited to Lotus in 1983 by Mitch Kapor to lead the team building Symphony, Lotus’s integrated word processor, spreadsheet, database, and graphing package. He left the following year with a different product in mind - a networked collaboration system modeled on the PLATO Notes discussion system he had used as a student at the University of Illinois - and founded Iris Associates on December 7, 1984. Lotus funded the work under a development contract in exchange for the option to buy the rights to the product.

Building the language for Notes

Notes needed a way for application designers - not C programmers - to express the logic of a document database: which documents belong in a view, how a computed field gets its value, how a field’s input should be validated. Ozzie’s solution was to reuse what Lotus already had. According to the language’s own documentation and its Wikipedia history, he took the formula compiler and decompiler from 1-2-3 and repurposed them. Formulas were compiled to a compact binary form stored inside the design element (a view, form, or field) and decompiled back to text for editing, exactly as 1-2-3 stored a formula in a cell.

What he changed was the language’s center of gravity. A spreadsheet formula language is about numbers; Notes had to process the contents of documents, which meant text, names, dates, and - above all - lists. Reportedly drawing on his earlier use of Icon and Lisp, Ozzie made the list the language’s fundamental data structure. Every value in the language is, in effect, a list: a text field with one value is a one-element text list, and the operators and functions are defined so that they apply element-wise across lists without loops. That design is what makes the language functional in character, and it is why catalogs classify it that way even though it also has side-effecting @commands.

Notes 1.0 shipped on December 7, 1989, with the formula language as its only built-in programming language. For its first seven years, every Notes application - the discussion databases, document libraries, and approval workflows that defined early groupware - was programmed entirely in formulas.

Lotus, IBM, HCL

The corporate history of the language is the history of its owners. Lotus bought Iris outright in 1994 for approximately US$84 million. IBM bought Lotus in 1995 for approximately US$3.5 billion, a purchase widely reported as being principally about Notes. Notes Release 4, in January 1996, added LotusScript as a second language, and Release 4.5 (December 1996) began adding Java support; from then on formulas were one language among several rather than the only one. In 2013 IBM dropped the Lotus name, and Release 9 shipped as IBM Notes. In December 2018 IBM announced the sale of Notes and Domino to HCL Technologies in a US$1.8 billion deal that closed in July 2019, and the product has since shipped as HCL Notes and HCL Domino, most recently version 14.5 on June 17, 2025.

Design Philosophy

The language’s design follows from three decisions.

Formulas belong to design elements, not to a program. In a spreadsheet, a formula belongs to a cell. Ozzie generalized the idea: in Notes, a formula belongs to a view (its selection formula), a column (its value formula), a field (its default-value, input-translation, and input-validation formulas), a paragraph (its hide-when formula), a button, or an agent. There is no main program. The application is the set of design elements, each carrying the formulas that govern it, and the Notes runtime evaluates the right formula at the right moment. A developer building a Notes application writes hundreds of small formulas rather than one large program.

Everything is a list. Because Notes documents are collections of multi-valued fields, the language treats a scalar as a one-element list and defines its operators over lists. "A" : "B" : "C" is a three-element text list; adding a number to a list adds it to each element; comparing two lists compares them pairwise. Most tasks that would need a loop in a procedural language become a single expression over a list - the same philosophy that drives array languages and the higher-order functions of Lisp, applied to office documents.

Expressions, not statements. A formula is a sequence of expressions separated by semicolons, and its value is the value of the last one. Conditional logic is an expression (@If), assignment is an expression (:=), and even the keywords that break the pattern - SELECT, FIELD, DEFAULT, ENVIRONMENT, REM - are only five in number. The language had no loops at all until 2002, and its designers regarded that as a feature: a formula was meant to be short, declarative, and evaluated in a bounded amount of time.

Key Features

@Functions and @Commands

The vocabulary divides in two. @Functions compute values: @Left, @Right, @Middle, @Trim, and @ProperCase for text; @Sum, @Round, and @Abs for numbers; @Now, @Today, @Adjust, and @Date for time; @UserName, @Name, and @UserRoles for identity; @DbLookup and @DbColumn for reading other databases. @Commands perform user-interface actions - @Command([FileSave]), @Command([EditDocument]), @Command([ViewRefreshFields]) - and can appear only in formulas that run in the client.

REM "Compute a display name from separate fields";
first := @Trim(FirstName);
last := @Trim(LastName);
@If(first = ""; last; last + ", " + first)

List processing

The list operators are the language’s most distinctive feature. : builds a list. Ordinary operators act pairwise; the same operators prefixed with * act on every combination (a “permuted” operation).

REM "Pairwise addition gives the two-element list  A1 : B2";
pairwise := ("A" : "B") + ("1" : "2");
REM "Permuted addition gives every combination  A1 : A2 : B1 : B2";
permuted := ("A" : "B") *+ ("1" : "2");
REM "@Elements returns 3; @Member returns 2, the position of y in the list";
count := @Elements("x" : "y" : "z");
position := @Member("y"; "x" : "y" : "z");
REM "@Implode joins a list into text: a, b, c   (@Sort is a Release 6 addition)";
@Implode(@Sort("c" : "a" : "b"); ", ")

@Explode splits text into a list, @Implode joins a list into text, @Unique removes duplicates, @Subset takes a prefix or suffix, and @Replace performs list-wise substitution. Before 2002 these functions and the permuted operators were the only way to iterate, which pushed Notes developers into a functional, whole-collection style of thinking.

View selection and the SELECT keyword

The single most-written formula in Notes is a view selection formula:

SELECT Form = "Invoice" & Status = "Open" & @Adjust(DueDate; 0; 0; 30; 0; 0; 0) < @Today

Every document in the database is tested against it, and the ones that return true appear in the view. Because selection formulas are evaluated by the server’s indexer over potentially millions of documents, the bounded, loop-free nature of the original language was a practical virtue rather than an abstract one.

Comparison with the 1-2-3 formula language

AspectLotus 1-2-3 formulasLotus/Notes formula language
HomeA cell in a worksheetA design element: view, form, field, agent, button
Central data typeNumberText list
Argument separatorComma: @IF(A1>0,"yes","no")Semicolon: @If(Total > 0; "yes"; "no")
ReferencesCell addresses (A1, B2..B9)Field names (Total, Status)
IterationImplicit over rangesImplicit over lists; explicit loops only from Release 6
Side effectsNone (macros are separate)FIELD assignment and @Commands
CompilationCompiled per cell, decompiled for displayCompiled per design element, decompiled for editing - the same compiler lineage

Evolution

1989-2001: the original engine

For its first thirteen years the language changed only by accretion: new @functions arrived with each release, notably @DbLookup and @DbColumn for cross-database access, and web-oriented functions once the Domino server began serving Notes applications over HTTP in the Release 4.5 and 4.6 era (1996-1997). The compiler at the core remained the one derived from 1-2-3, and the language kept its original restrictions - temporary variables could be assigned once, lists could not be indexed, and there were no loops.

2002: the Release 6 rewrite

Notes/Domino 6, released in September 2002, replaced the engine. Damien Katz, then a developer on the Notes team at Lotus/IBM, rewrote the formula evaluator and used the opportunity to extend the language. IBM’s 2002 developer article “Enhancements to the formula language in Domino 6” catalogs the changes:

  • Loops: @For, @While, and @DoWhile, with @Nothing to suppress a loop’s result
  • Runtime evaluation: @Eval executes a formula held in a text string, and @CheckFormulaSyntax validates one
  • List functions: @Sort (with custom comparison), @Transform (apply a formula to every element), @Compare, @Count, and list subscripting with Categories[n]
  • Portable field code: @GetField, @ThisName, and @ThisValue
  • Error handling: @IfError
  • Web support: @WebDbName, @URLEncode, @URLDecode
  • Language rules: temporary variables may be reassigned, assignments may nest, braces delimit REM comments and constants
REM {Release 6 style: a loop and a transform};
total := 0;
@For(n := 1; n <= @Elements(Amounts); n := n + 1;
     total := total + Amounts[n]);
doubled := @Transform(Amounts; "x"; x * 2);
@Text(total) + " / " + @Implode(@Text(doubled); ",")

Katz later wrote about the project in a 2005 blog post, “Formula Engine Rewrite”, remembered less for its technical detail than for its account of the anxiety of replacing a component that every Notes application in the world depended on. The IBM article states that performance improved with the new engine; no published benchmark accompanies that claim, so the size of the improvement should not be quoted. What can be said is that the rewrite preserved backward compatibility with formulas written since 1989 while adding the constructs the language had lacked.

2002-present: stability

Since Release 6 the language has been stable. Later releases added @functions for new platform features but did not change the syntax or semantics. HCL’s Domino Designer documentation for version 12 through 14.5 still documents the language in full, including the note on each Release 6 function that it was “new with Release 6” - a small sign of how little has changed since.

Current Relevance

The formula language is, as of 2025, a supported and documented part of HCL Notes/Domino 14.5. Any organization still running Domino applications - and many large enterprises, government bodies, and financial institutions reportedly built decades of workflow on it - is running formula code every time a view is opened. The language has no life outside that platform: there is no open-source implementation, no standalone interpreter, and no Docker image, and its compiled form has never been publicly specified.

The catalog status of dormant is therefore a statement about the language as a Lotus language. The Lotus brand was retired in 2013, the Lotus 1-2-3 spreadsheet from which the compiler came was discontinued in 2013 with support ending in 2014, and the Notes platform itself, while maintained, has been in long decline against web and cloud collaboration tools since the mid-2000s. The language is not dead - it ships, it is documented, and it is used - but it is no longer evolving, and the community that once produced conference sessions and books about @formula tricks has largely dispersed. Its practical future is bound to the maintenance life of Domino.

Why It Matters

Lotus Formula is worth studying for three reasons.

It is a rare case of a spreadsheet language transplanted into a different domain. The formula compiler that drove 1-2-3’s cells was re-aimed at documents, and the result showed that the spreadsheet model - small formulas attached to things, evaluated on demand, written by end users rather than programmers - could organize an entire application platform. Notes applications were built by administrators and power users in the same way 1-2-3 models were built by accountants, and that low barrier was a large part of why Notes spread.

It was an early mainstream functional language. From 1989 onward, when most business software was programmed in COBOL, C, or BASIC, the growing population of Notes application designers was writing list-comprehension-style expressions with implicit iteration, first-class lists, and no assignment - not because they had read about functional programming, but because the language made that the natural way to work. Damien Katz’s Release 6 additions, @Transform in particular, are recognizably map.

And it is a link in a chain that runs from VisiCalc to CouchDB. Ozzie carried the @function from Software Arts and Lotus into Notes; Katz carried the Notes model of replicated, schema-free documents into CouchDB in 2005, and from there into the document-database movement. The formula language sits in the middle of that lineage - the piece of 1-2-3 that lived on inside groupware for more than three decades.

Timeline

1983
Lotus 1-2-3 Release 1 ships in January with cell formulas and a library of @functions (@SUM, @IF, @VLOOKUP and others) - the spreadsheet formula language whose compiler would later be reused for Notes. The same year Ray Ozzie joins Lotus to lead development of Symphony
1984
Ray Ozzie leaves Lotus and founds Iris Associates in Westford, Massachusetts on December 7, funded by Lotus under a development contract. Tim Halvorsen, Len Kawell, and Steve Beckhardt - former PLATO colleagues - join in January 1985
1989
Lotus Notes Release 1.0 ships on December 7, Iris's fifth anniversary. Its formula language - built on the compiler and decompiler borrowed from 1-2-3 but redesigned for string and list processing - drives view selection, computed fields, and form logic from the first release
1994
Lotus Development buys Iris Associates outright for approximately US$84 million, ending the author-publisher contract under which Notes and its formula language had been developed
1995
IBM acquires Lotus Development Corporation for approximately US$3.5 billion, a purchase widely reported as being chiefly about Notes. The formula language becomes part of IBM's software portfolio
1996
Notes Release 4 ships in January and introduces LotusScript, a BASIC-derived procedural language, alongside the formula language. Formulas remain the required language for view selection and column values; LotusScript takes over complex procedural logic
2002
Notes/Domino 6 ships in September with a formula engine rewritten by Damien Katz. The language gains loops (@For, @While, @DoWhile), runtime evaluation (@Eval), list functions (@Sort, @Transform, @Compare, @Count), reassignable temporary variables, list subscripting, and @IfError - the largest change to the language since 1989
2005
Damien Katz publishes his 'Formula Engine Rewrite' blog account of the Release 6 work (reportedly in January), and the same year begins CouchDB, a document database whose design he described as inspired by his years working on Lotus Notes
2013
IBM retires the Lotus brand: Release 9, shipped in March, is the first version sold as IBM Notes rather than Lotus Notes. The formula language continues unchanged in name and syntax, but the 'Lotus' era of the language ends
2018-2019
IBM announces on December 6, 2018 that Notes and Domino will be sold to HCL Technologies as part of a US$1.8 billion deal; the transfer completes in July 2019
2023
HCL Notes/Domino 14 is released on December 7 - 34 years to the day after Notes 1.0 - with the formula language still documented as a first-class development language
2025
HCL Notes/Domino 14.5 ships on June 17, the latest release in which the formula language is supported

Notable Uses & Legacy

Notes view selection and column formulas

Every view in a Notes/Domino database is defined by a SELECT formula that decides which documents it contains and by column formulas that compute what is displayed. Since 1989 there has been essentially no way to build a Notes view without writing in this language

Domino agents and workflow automation

Scheduled and triggered agents written in formula language select and modify batches of documents - routing approvals, archiving, and cleaning data - in the corporate workflow applications that made Notes a fixture of enterprise IT through the 1990s and 2000s

Domino web applications

When Domino became a web server in the late 1990s, formulas were extended for HTTP-facing work; Domino 6 added @WebDbName, @URLEncode, and @URLDecode specifically so formula code could generate and parse web URLs

Apache CouchDB's design lineage

Damien Katz, who rewrote the formula engine for Notes/Domino 6, went on to create CouchDB in 2005, a document database he described as inspired by his work on Notes - carrying the Notes model of replicated, schema-free documents into open source

Language Influence

Influenced By

Lotus 1-2-3 Icon Lisp

Running Today

Run examples using the official Docker image:

docker pull
Last updated: