Swym
Swym is Laurie Cheers's readability-first hobby language - pronounced "swim", short for "Say What You Mean" - designed backwards from programs its author wanted to be able to write, then reverse-engineered into something implementable. Its two signature ideas are multivalues, in which any expression may return several values that propagate through the surrounding expression, and the etc keyword, which tells the compiler to extrapolate a sequence from two or three worked examples. Its only implementation is a JavaScript interpreter that runs in a web page; it has been dormant since 2017
Created by Laurie Cheers, a game programmer whose public code is otherwise games, tools and Magic: The Gathering simulations - one of his repositories describes its contents as utilities "collected over ten years using Unity". Nothing on his GitHub profile states a nationality or employer, so none is asserted here. Swym is the oldest repository on his GitHub account and appears to have been an entirely solo project: the repository has no other contributors, and every commit in it is his
Swym is a programming language designed to let you, in its author’s words, “Say What You Mean, as clearly and elegantly as possible.” It is pronounced “swim”. It was written, more or less single-handedly and over more than a decade, by Laurie Cheers, a British game programmer, and it exists as an interactive tutorial with an interpreter embedded in the page - which is still online, and still works, sixteen years after the first surviving capture of it.
The design method is the interesting part, and the author states it plainly in the first paragraph of the tutorial:
I designed Swym in a crazy way - I wrote down some programs I wanted to be able to write, regardless of whether they were implementable; and then I reverse-engineered semantics for them. That process showed me how I needed to change the programs, to make them behave more consistently, and to make them parseable. It took about five years of iterating like this, on and off, before the language finally started to gel enough to be implementable.
The wiki’s Getting Started page carried the same paragraph, and both pages illustrate it with the same example - an expression written years before anybody knew how it would work:
1/2 + 2/4 + 3/8 + etc
That is a complete Swym program. It evaluates, on a current build, to 1.9999999999999998.
Two corrections belong at the top, because the catalogue row that brings most readers here gets both of them slightly wrong. Swym is not a concurrent language - there is no thread, task, channel, lock or async construct anywhere in its roughly fifteen thousand lines of implementation, and the documentation never mentions concurrency. And while the “2010” date is right as far as the record goes, it is the date of the earliest surviving web capture, not of the language’s conception: the design was already about five years old by then, and the implementation the world eventually saw on GitHub is a rewrite from 2012.
History and Origins
2010: swym.in
The Internet Archive’s first capture of Swym is dated 31 July 2010, at the domain swym.in. What it captured is recognisably the same document that is served from cheersgames.com/swym/ today: the same title, “Swym - an interactive tutorial”; the same opening about designing the language backwards; nearly the same table of contents - eight sections in 2010, nine by 2013, once “Lists and strings” had been split into separate “Arrays” and “Strings” sections; the same closing “th-th-that’s all I have for now, folks!”
What is different is the implementation underneath it. The 2010 page loads six scripts - swym.js, swymTokenize.js, swymParser.js, swymEtc.js, swymSimpleEval.js and swymStdlyb.js. There is a tokenizer, a parser, the etc machinery and a standard library, and then a simple evaluator that walks the result. There is no compiler and no type checker. Both of those - swymCompile.js and swymTypeCheck.js, today roughly 3,300 and 1,200 lines, the compiler second in size only to the 3,700-line standard library - appear only in 2012.
The surface syntax was different too. Declarations in 2010 used a colon and capitalised names:
List.total: .1st + .2nd + etc;
[1..10].total
Int.Divisor: [1..this].Where{this%it == 0}
Prime: {.Divisor == [1,this]}
[1..50].Where(Prime)
By 2013 the same tutorial had been rewritten to use quoted declarations with =, and by the final build the = had gone too. Three distinct declaration syntaxes in seven years is a fair summary of how settled the language was.
2012: the GitHub rewrite
On 16 March 2012 Cheers created LaurieCheers/Swym. It was the first repository on an account he had held since October 2009, and it remains the oldest of the thirty he has published. Two commits landed that day - “First commit”, then “First real commit!” - and the second brought in the whole rebuilt system: a compiler that lowers the parse tree to an internal executable form, a static type checker that runs before anything executes, the canvas front end, a presentation page and a SyntaxHighlighter brush for the language.
The type checker is not decorative. On a current build, true+1 does not fail at runtime; it fails to compile:
-- Compiling Error --
Line 1:5 - true+1
Argument 'this' was the wrong type during call to function '+'. (true is not of type Int)
and the test file’s “Type system torture” section is full of expressions like (1..3).Type, which answers Int*, and 1.Type, which answers Literal(1) - the checker tracks literal types, not just base types.
2013: the good year, and the last one
Fifty-five of the repository’s ninety-five commits are dated 2013. February brought the first two large programs, Tetris and Alchemy; March brought Breakout, Jelly, a Project Euler test file, a string-syntax overhaul, a type-system cleanup, the MediaWiki extension that made the documentation runnable, and the MIT licence. The Internet Archive first captured the wiki on 27 March 2013. The wiki outlived the burst of activity that produced it: its Main Page was still being edited in September 2014 and its Getting Started page in August 2017.
Then it thinned out. Twelve commits in 2014, mostly the integration of the Ace editor and a new SwymEditor.html front end that could load a program out of its own URL. Three in 2015, the last a December commit titled “Changes from Travelling Salesman advent challenge” - the author using his own language on a seasonal puzzle and repairing what the puzzle broke. Nine in early 2016, almost all on the etc machinery. Two in 2017. The last, on 22 July 2017, is called “Minor tweaks and bug fixes”. Nothing since.
Design Philosophy
The wiki’s Main Page led with the vision statement, hedge included: “Readability-first design: Swym’s vision statement is to be the most readable language ever made. (YMMV.)” The Getting Started page argued the point at more length, and pre-empted the two objections it expected:
Swym’s design goal is to be the most readable language ever made. (Obviously, that’s very subjective, so don’t be surprised if you disagree - especially at first sight. FAQ: No, that’s not the same as trying to look “clean” or “pretty”. Swym has quite a lot of punctuation to help ensure that the program’s structure is clear even when users extend it. FAQ: No, of course not all Swym code will be maximally readable. The language can only provide tools to allow readable code to be written; it cannot enforce it.)
The strategy, in the next sentence, was stated as follows: “The language’s strategy to maximize readability is to let users express their program’s logic using familiar, intuitive high level concepts - such as "each", "all", "none", "etc", "where" - and define their own, with a minimum of fuss.” The influences the author names for the result are “Javascript, Python, Haskell, APL, Lisp, and no doubt others.”
Two smaller principles fall out of this and are worth naming because they are unusual.
Declarations announce themselves. Every identifier being declared is written in single quotes, so 'x' = "hello" declares x and x uses it. The tutorial’s justification is a readability argument rather than a parsing one: “With just this one rule, you can read any Swym program and immediately figure out which bits of code are declaring which identifiers. (This can be surprisingly difficult in some languages!)”
Functions live in their own namespace, and cannot be handed around. A value named half and a function named half coexist, and half.half is legal. The cost is that functions are not first-class - the only thing you can do with a function is call it. Blocks fill the gap, and the tutorial is content with the trade:
although Swym could certainly (semantically speaking) be classed as a functional language, it gently discourages the kind of mind-bogglingly abstract function-munging that sometimes goes on in languages like Haskell.
Key Features
Multivalues
In most languages an expression produces one value. In Swym an expression may produce several, and they propagate outwards through whatever encloses them. The comma is the simplest multivalue operator - (1,2) is one expression with two values - and arithmetic distributes across them:
[1..5].each + 10 → 11 12 13 14 15
(1,2)+(10,20) → 11 21 12 22
Note the second: it is the full cross product, in a defined order, not a pairwise zip. Arrays are the boxed form of a multivalue - the wiki’s summary was “the mental model of arrays is turned on its head. An array is just a multivalue in a box” - so [] collects a multivalue into an array and each unpacks one back out. A multivalued expression written inside an array literal splices its values into position, which is why [10, 1..4, 0] evaluates to the six-element array [10,1,2,3,4,0].
Quantifiers are built on the same mechanism. some and all produce multivalues that a comparison consumes, and the enclosing square brackets resolve the result to a single boolean:
[ all[5..10] >= all[1..5] ] → true
[ all[5..10] > all[1..5] ] → false
[ some[1..10] == all[2..9] ] → false
[ all[2..9] == some[1..10] ] → true
The last two lines are the point. Order is not symmetric, and the tutorial spells the asymmetry out: the first “checks whether there’s just a single value in A that’s equal to all the values in B” - there is none - while the second “checks whether each of the values in B is equal to some value - but not necessarily all the same value - in A”, which there is. The tutorial admits the design was not finished - an earlier build used a prefix / “resolve” operator that the author disliked (“I want them to be auto-resolved reliably enough that you almost never need to use it. I just haven’t found the correct rule for when to do it”). The bracket rule in the final build appears to be the answer he eventually settled on.
etc
etc is the feature the author singled out - “probably the part of Swym that I’m most proud of… the ultimate embodiment of language’s design philosophy: code readability, at the cost of all else.” Writing it in an expression means, in his gloss, “…and so on in the obvious way. You figure it out.”
It must follow an infix operator. The compiler looks back at the surrounding expression, finds the chain of instances of that operator and their arguments, works out how each term differs from the last, and continues the pattern. All of these are real test cases from SwymTests.html, and all of them still produce these answers:
[1..10].{.1st + .2nd + etc} → 55
[1..10].{.1st * .2nd * etc} → 3628800
[1..10].{[[.1st,.2nd], [.3rd,.4th], etc]} → [[1,2],[3,4],[5,6],[7,8],[9,10]]
[1..10].{[.1st, .2nd, .4th, etc]} → [1,2,4,8]
[1..10].{[.1st, .1st+.2nd, etc]} → [1,3,6,10,15,21,28,36,45,55]
[1, 2, 4, etc..<100] → [1,2,4,8,16,32,64]
Line four is the one that shows what is being inferred: two examples give 1-2-3-4, three examples give 1-2-4-8. Line five extrapolates a recurrence - each term is the previous term plus the next element - and produces triangular numbers. And where several things vary at once, each is extrapolated independently: in [[.1st,.2nd], [.3rd,.4th], etc] the compiler deduces 1st-3rd-5th-7th from the first position and 2nd-4th-6th-8th from the second.
The classic application is transposition, defined in one line:
Array.'transpose' { [[.each.1st], [.each.2nd], etc] }
transpose["hello","there","world"] → ["htw","eho","ler","lrl","oed"]
The termination condition is handled separately and, unlike the pattern itself, at runtime: etc..<100 stops when a term would reach 100, and there are etc..<=, etc..>, etc..>= and a repeat-count form etc**10. The 2013 tutorial notes a hard cap - “an etc expression cannot perform more than 1000 iterations… just until the compiler can be made a little smarter about detecting loop termination conditions” - which is the kind of promise that a language abandoned in 2017 does not get to keep.
Patterns
Types, lists and predicate blocks are all patterns, and a pattern is a set of values. Int is a pattern; [1,2,4,8,16] is a pattern containing five values; {it%2 == 0} is a pattern containing the even numbers. A type and a predicate block are interchangeable wherever a pattern is expected:
[1, "hello", true, 7].where(Number) → [1,7]
[1..10].where{it%2 == 0} → [2,4,6,8,10]
[1..10].where{.in[11,5,2]} → [2,5]
The third line is a reminder that this is a moving target. The 2013 tutorial hands a bare list straight to the filter - [1..10,10..1,1..10].Where[3,5] - but the final interpreter rejects that form, and membership in a literal list has to go through in.
The tutorial spells out the correspondence: patterns are sets, where is intersection, [] is the empty set, Value is the universal set, | is union, and Non is complement. It then does what anyone would do with such a system, and constructs Russell’s paradox in three lines - noting cheerfully that asking whether the resulting pattern contains itself means that “on the current implementation that’ll cause a stack overflow”. Value and Non, like the bare-list pattern, are among the pieces the final interpreter no longer recognises.
The unification is not merely cosmetic. The author’s account is that he wanted to iterate over every value of an enumerable type the same way he iterated over a list, got tired of converting between the two, and merged the concepts: “All enumerable types are lists. All lists are enumerable types.”
Cells
A cell is a list element that remembers where it came from - its source list and its index - obtained by calling Cell on a list. It exists so that a filtered list can still answer questions about the original: filter Cell(X) and the survivors report their indices in X, not in the result. Range operators on cells slice the source list rather than producing numbers.
Cells are documented in the “Future Development” section of the tutorial, and the author is candid that they were not working: filtering a list of cells and then slicing it loses the original provenance, “and I haven’t entirely figured out what I want to do about this.” The final interpreter does not recognise the Cell function at all. Somewhere between 2013 and 2016 the feature was taken back out.
Evolution, and a language that outran its own manual
The most instructive thing about Swym is the gap between its documentation and its implementation, because the documentation stopped and the implementation did not.
The tutorial served today at cheersgames.com/swym/index.htm carries a Last-Modified date of 20 March 2013. The eight interpreter scripts served beside it carry Last-Modified dates of 27 January to 7 February 2016. Three years separate them, and in those three years the language changed underneath the page. Loading those 2016 scripts and feeding them the tutorial’s own examples produces errors:
Int.'divisors' = [1..this].where{this%it == 0}
-- Compiling Error -- Invalid declaration.
The = form of function declaration is gone; the working syntax is Int.'divisors' { [1..this].where{this%it == 0} }, or returns for a single expression. The plus-or-minus operator ± - about which the tutorial has a whole paragraph of self-justification, including the tip that “you can type it with Alt-241, which makes a nice easy-to-remember triangle pattern on the numeric keypad” - is not recognised, nor is its ASCII spelling +_. The infix is operator is gone, though is survives as an ordinary function - 7.is(Number) still answers true. Cell is gone. The quantifier syntax changed from / some(A) > every(B) to [ some(A) > all(B) ].
What still works is the core, and it works well. Every example in this article’s Key Features section was executed against both the 2016 scripts from the live site and the 2017 scripts from the repository, and produced the output shown. The accurate specification of the final language is not the tutorial but SwymTests.html: 429 expression-and-expected-output pairs in eighteen labelled sections plus a short pretests block, which is where anyone actually trying to use Swym today would have to start.
Current Relevance
Swym is dormant by any measure that matters. The repository has had no commits since 22 July 2017 and has fifteen stars. There is no release, no tag, no package, no mailing list, no forum, no third-party implementation and no recorded use by anybody other than its author. The wiki that held the reference documentation is gone - cheersgames.com/swym/wiki/ now answers HTTP 500 - and swym.in, the domain the tutorial first appeared on in 2010, has become a Shopify storefront.
What survives is unusually intact for a project of this size. The tutorial page is still served and still runnable in a browser. The GitHub repository is complete, MIT-licensed, and self-contained: ten JavaScript files totalling about 15,000 lines - the eight the tutorial page actually loads come to about 13,000 - with no build step and no dependencies beyond the vendored Ace editor. Loaded into Node.js v26.7.0 with a short shim for window and the script-loading callback, it evaluates programs correctly on a 2026 machine, which is more than most abandoned web-based language experiments manage.
A caution for anyone reading performance into any of this: the author disclaimed it explicitly. “Don’t be surprised if you experience any slowdowns: at the moment this language isn’t optimized at all. Seriously; not. at. all. I decided I preferred getting it working over getting it fast.” No benchmark of Swym has ever been published, and none should be inferred.
Why It Matters
Swym will not be adopted by anyone, and it is not trying to be. Its interest is as an unusually well-documented record of one person’s attempt to answer a question most language designers answer by instinct: what does a language look like if readability is the only thing you optimise for, and you are willing to pay any implementation cost to get it?
The two answers it produced are both worth knowing about. Multivalues are a serious idea - the observation that the array/scalar distinction is a packaging decision rather than a semantic one is APL’s, but Swym takes it further by letting an unboxed multivalue flow through arbitrary expressions and by building quantifiers on top of it, which APL does not. And etc is, as far as this encyclopedia can establish, unique: a compile-time facility for inferring a sequence from worked examples, applied not to numbers but to code, with the compiler independently extrapolating each varying position in an expression. It is exactly the sort of thing that shows up when a language is designed by writing the programs first. Nobody deriving semantics from a type theory would arrive at it; somebody who had already written [[.1st,.2nd], [.3rd,.4th], etc] on paper and refused to give it up would have to.
The rest of the record is a familiar and honest shape for a solo language: a decade of design, one very good year of implementation, a set of demo games, a wiki, a slow fade, and a page that still runs. The author’s own last words in the tutorial are the right note to end on - “Ok, well… th-th-that’s all I have for now, folks! Hope you enjoyed it!”
Timeline
Notable Uses & Legacy
Tetris - "the first ever large Swym program"
A 255-line implementation committed on 13 February 2013 and labelled by its author as the first large program written in the language. It is the point at which Swym stops being a page of one-liners: it declares a Grid struct with width, height and a flat Int array of contents, builds a mutable version of it, maps tile constants to PNG images through a case expression, and renders through SwymCanvas.html. Writing it is visibly what drove the next month's work - the commits either side of it are type-system cleanups and bug fixes found by having a real program to run
Breakout, Alchemy and Jelly
Three more canvas games in the repository - a 75-line Breakout, a 276-line Alchemy and a 130-line Jelly - added across February and March 2013, the Breakout in the same commit as "Cleaned up type system, made Breakout, new string syntax". Between them they are the only evidence of what Swym looked like as a language for writing interactive programs rather than expressions, and they use the mutable side of the language heavily: Number:'ballX' = 50 and friends at the top of Breakout are the first thing in the file
The Project Euler test file
169 lines of solutions to the early Project Euler problems, committed on 17 March 2013 explicitly as test cases. They read as an argument for the language - problem 1 is the single line sum( [1..<1000].where{.divisibleBy(3) || .divisibleBy(5)} ) - but they also exercise the imperative half, with buildArray, while loops and push used to generate Fibonacci numbers and prime factorisations. They are the closest thing Swym has to a benchmark suite, and the commit message concedes what they were really for: "and associated bugfixes"
SwymTests.html, the automated test page
The project's regression suite, and by some distance its most complete specification: 429 runTest calls, each an expression and its expected output, grouped into a short "pretests" block plus eighteen labelled sections - Basic Arithmetic, Basic Logic, Basic Constants, Basic Strings, Basic Functions, Sequences, JSON, Type system torture, Builtins, Destructuring, Variables, Etc keyword, Quantifiers, Overloaded Functions, Errors, Structs, Tuples and Future Work. Because the tutorial on the website was frozen in 2013 while the language kept moving, this file is the only accurate record of the syntax the final interpreter actually accepts
The Swym Wiki and its MediaWiki extension
A MediaWiki installation at cheersgames.com/swym/wiki with a custom extension, committed on 20 March 2013, that turned every code block on every documentation page into a live, editable Swym console. Its Main Page listed the reference material - operators, data types, keywords, the standard library nicknamed "Stdlyb", a cheat sheet - under a "Reference" heading, and kept a separate "Major features" list whose first entry was "Readability-first design: Swym's vision statement is to be the most readable language ever made. (YMMV.)" The wiki is dead; the Internet Archive's March 2013 captures are what is left of it