ESPLORA
Accesso richiesto
Indietro

Getting started with recalc

Introduction

Spreadsheets are everywhere: in businesses, labs, universities, and homes. But they’re also notoriously error-prone. Studies show that many spreadsheets contain errors. Errors that sometimes go unnoticed until it's too late. That is partly because spreadsheets, while immensely popular, lack robust ways to catch errors before they matter.

At the same time, programming spreadsheets is awkward. Anything that goes beyond basic data science may quickly become a VBA hack or the like. Major spreadsheet formula languages grew organically. Some spreadsheet software caught up with the need for higher-level abstractions and implement LAMBDA. But it has become apparent that there is no clear way for writing high-level formulas that interacts with the outside world.

recalc tackles these problems by embedding a novel formula language into spreadsheets. The proposed formulas allow for:

  • A high-level formula language built for spreadsheets, making it easy to define reusable computations as sheet-defined functions and extending it to time-series data using stream-based effect semantics.
  • Statically typed spreadsheets that help you catch errors early and provide you with detailled error messages. It also provides an excellent basis for further features such as "compiling spreadsheets", or AI-enhanced capabilities.

Formulas

In recalc, writing formulas feels familiar to spreadsheet users: cell references are written in the usual form A1, and cell ranges separated by a colon (for example A1:B3).

Literals

Like any spreadsheet, you work with literal values. All of the following are available:

  • -1, 0, 1.2, etc. — numbers
  • FALSE, TRUE — booleans
  • "Hello, World!" — strings (with support for value interpolation via ${e} inside strings)

Syntax

Formulas (written as e, e') may refer to defined functions (f) or bound variables (x):

  • A1 — a simple reference to cell A1
  • A1:B3 — a reference to a block (which “spills” across the shape)
  • \x -> e — a lambda (anonymous) function that takes x and computes e
  • f(e, e', ...) — function calls
  • let x: t = e in e' — a let-binding with type annotation t
  • {l: e} — records (like small labeled dictionaries)
  • e.l — to project (access) a field l from record e
  • e: t — type annotation
  • literals

Events are syntactically distinct from regular expressions and prefixed with ~. For example, the formula @Temparature may refer to a discrete event source with temperature values.

Types

Types are checked and inferred. Syntactic restrictions make sure that types remain inferrable and make sure that there is no need for type annotations.

Implicit types (written as {t:Type} if its kind is of Type we may write {t}) are inferred by a unification and resolution procedure.

Formula Evaluation

Though under the hood recalc is powered by a complex type system, you don’t have to think about it that way. recalc provides syntactic restrictions such that programs do not grow too complex.

Formulas react to values they reference as usual. However, and this is unique to recalc, a spreadsheet is a function of time: values in recalc may change over time (see next section).

Spreadsheets that do not contain time-dependent values behave like regular spreadsheets would.

Reactive Programming

For example, the formula =LAST(@Temperature, 0) only makes sense when we specify a start and end time. Here @Temperature has the type @number (event type) and is a discrete sampling of an external signal. LAST evaluates to the last occurence of its event (or the provided default when no event occurred yet). Thus LAST(@Temperature, 0) is a continuously defined signal (type ~number).

Functional reactive programming is facilitated by the following primitives:

  • lift(v) — lifts a static value v to a time-varying signal. Its type is {t} -> t -> t~.
  • reduce(~Event, v, fn) — a generic stream reducer (an effectful fold), which accumulates using fn over ~Events using v as a starting value. Its type is {v} -> v -> {t} -> Event<t> -> (t -> v -> v) -> v~.

All interesting time-series functions can be implemented on top of the two. For example, the LAST combinator would be

\e -> \v -> reduce(e, v, \_ -> \last -> last)

UI Elements

The user interface for recalc is a regular spreadsheet editor. You can view shortcuts using Ctrl + \.

Time Controls

At the bottom right, you’ll find a time slider that sets the start and end of your current time window. Drag to adjust, or double-click to type precise dates.

This controls how your stream-based computations are evaluated, as described in the "Functional Reactive Programming" section.