Calcit uses tuples to simulate objects. Inherence not supported.

Core idea is inspired by JavaScript and also borrowed from a trick of Haskell since Haskell is simulating OOP with immutable data structures.


  • "Tuple", the data structure of 2 items, written like (:: a b). It's more "tagged union" in the case of Calcit.
  • "class", it's a concept between "JavaScript class" and "JavaScript prototype", it's using a record containing functions to represent the prototype of objects.
  • "objects", Calcit has no "OOP Objects", it's only tuples that simulating objects to support polymorphism.

which makes "tuple" a really special data type Calcit.


Define a class:

defrecord! MyNum
  :inc $ fn (self)
    update self 1 inc
  :show $ fn (self)
    str $ &tuple:nth self 1

notice that self in this context is (:: MyNum 1) rather than a bare liternal.

get an obejct and call method:

    a $ :: MyNum 1
  println $ .show a

Not to be confused with JavaScript native method function which uses .!method.

Use it with chaining:

-> (:: MyNum 1)

In the runtime, a method call will try to check first element in the passed tuple and use it as the prototype, looking up the method name, and then really call it. It's roughly same behavoirs running in JavaScript except that JavaScript need to polyfill this with partial functions.

Built-in classes

Many of core data types inside Calcit are treated like "tagged unions" inside the runtime, with some class being initialized at program start:


that's why you can call (.fract 1.1) to run (&number:fract 1.1) since 1 is treated like (:: &core-number-class 1) when passing to method syntax.

The cost of this syntax is the code related are always initialized when Calcit run, even all of the method syntaxes not actually called.

Some old materials

  • Dev log(中文) https://github.com/calcit-lang/calcit/discussions/44
  • Dev log in video(中文) https://www.bilibili.com/video/BV1Ky4y137cv