Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Comparison of Rant 3 and Ranty

Rant 3 (deprecated as of June 2020) was released in April 2017. Since then, several critical design flaws have been identified in the language. Ranty aims to address all of those flaws while retaining the ergonomics of the original design.

Ranty is a fork of Rant 4, which was intended as a ground-up rewrite (in Rust) from the original Rant developer but sadly appears to have been abandoned before a stable release could be completed.

It is important to note that Rant 3 code is not forwards-compatible with either Rant 4 or Ranty. Similarly, Ranty extends Rant 4 but should not be assumed interoperable with it. All three should be regarded as separate languages.

Feature breakdown

Feature nameRant 3Ranty
Runtime platform.NET-onlyNative
Blocks
Block weights
Selectors(named only)
Queries
Output channels
Hints/sinks
Variables(via stdlib only)
Variable access fallbacks
Operators(via stdlib only)
Named functions
Anonymous functions
Piping
Variable capture in functions
Variadic function parameters(stdlib functions only)
Optional function parameters(stdlib functions only)
Parameter spread notation
Collection initializers
Conditional expressions
Slice notation
Dependency management
(packages)

(modules)
Resource management
(packages)

(data sources)
Print support for non-string values
Automatic number formatting
Explicit global accessors
Explicit parent scope accessors (descoping)
Unit type
Babylonian cuneiform support

(✅ = implemented; ❌ = not implemented)

Multiple outputs

Rant 3 allowed programs to produce multiple outputs via channels. That design mostly compensated for the lack of first-class collection literals, but it also made nested scopes harder to reason about because inner scopes could not work with more than one active output at a time.

Ranty removes channels in favor of ordinary value flow. If a program needs to produce several results, it can return a list, tuple, or map instead of writing to parallel outputs.

Resource management

Rant 3 used .rantpkg package files to bundle programs and string tables. That required a separate packaging step and combined code loading with data loading.

Ranty splits those concerns:

  • modules handle code dependency management;
  • data sources handle external data access.

See Modules, Module Resolvers, and Data Sources.

Querying

Rant 3 included a built-in query system for filtering and printing entries from packaged string tables.

Ranty removes query expressions from the language itself. The equivalent workflow is to pull data through a module or data source and then manipulate it with ordinary language features and stdlib functions. See Modules and Data Sources.

Variables

Variables in Rant 3 were mostly manipulated through standard-library functions such as [v], [vn], and [vs].

Ranty replaces that system with accessors, giving variables, keys, indices, descoping, and fallbacks a consistent language-level syntax.

Example

Before:

# Rant 3 syntax
[vn: foo; 1]
[vn: bar; 2]
[add: [v: foo]; [v: bar]]
# -> 3

After:

# Ranty syntax
<$foo = 1; $bar = 2>
<foo> + <bar>
# -> 3

Printing values

Rant 3 effectively treated printed output as strings only. Working with numbers and collections often required specialized helper functions because values would not naturally flow through the runtime as structured types.

Ranty prints and carries structured values directly. Lists, tuples, maps, numbers, selectors, functions, and nothing all participate in ordinary evaluation without being flattened to strings first.

Functions

Rant 3 distinguished between native functions and user-defined subroutines, and those lived in different conceptual spaces.

Ranty has a single function type for named functions, lambdas, and stdlib callables. Functions can be stored in variables, passed around, returned, and captured like other values. The language also supports lambda expressions, which Rant 3 did not.

Collections

Rant 3 had list and map types, but creating them relied on stdlib helpers, which made collection-heavy code harder to read and less composable.

Ranty adds collection initializer syntax, so lists, tuples, and maps can be created directly inside expressions without temporary variable plumbing.

Variadic and optional parameters

Rant 3 only supported variadic and optional parameters on native functions.

Ranty allows user-defined functions and lambdas to declare optional and variadic parameters directly, including default values for optional parameters and both * and + variadic forms.

Selectors

Rant 3 kept selectors in a separate named object space that lived for the duration of the program. Reusing or discarding them required explicit naming and lifecycle management.

In Ranty, selectors are ordinary values of type selector. They can be created once, stored in variables, shared across blocks, or created inline for one-off use.

Examples

Reusing a selector

Before:

# Rant 3 syntax
[x:foo;locked]
{a|b|c|d|e|f|g|h}
[x:foo;locked]
{1|2|3|4|5|6|7|8}

After:

# Ranty syntax
<%sync = [mksel: one]>
[sel: <sync>] {a|b|c|d|e|f|g|h}
[sel: <sync>] {1|2|3|4|5|6|7|8}

Single-use selector

Before:

# Rant 3 syntax
[x:foo;deck][rep:each]{A|B|C|D|E|F|G|H}
[xdel:foo]

After:

Ranty syntax:
[sel: deck] [rep: all] {A|B|C|D|E|F|G|H}