Janet 1.42.0-dev-7fd75f3 Documentation
(Other Versions: 1.42.0 1.41.2 1.41.1 1.40.1 1.40.0 1.39.1 1.38.0 1.37.1 1.36.0 1.35.0 1.34.0 1.31.0 1.29.1 1.28.0 1.27.0 1.26.0 1.25.1 1.24.0 1.23.0 1.22.0 1.21.0 1.20.0 1.19.0 1.18.1 1.17.1 1.16.1 1.15.0 1.13.1 1.12.2 1.11.1 1.10.1 1.9.1 1.8.1 1.7.0 1.6.0 1.5.1 1.5.0 1.4.0 1.3.1 )

Prototypes

To support basic generic programming, Janet tables support a prototype table. A prototype table contains default values for a table that are looked up if certain keys are not found in the original table. This allows many similar tables to share contents without duplicating memory.

# simple object oriented behavior
(def proto1
  @{:type :custom1
    :behave (fn [self x] (print "behaving " x))})
(def proto2
  @{:type :custom2
    :behave (fn [self x] (print "behaving 2 " x))})

(def thing1 (table/setproto @{} proto1))
(def thing2 (table/setproto @{} proto2))

(thing1 :type) # -> :custom1
(thing2 :type) # -> :custom2

# prints "behaving :a"
(:behave thing1 :a)
# prints "behaving 2 :b"
(:behave thing2 :b)

Looking up a value in a table with a prototype can be summed up with the following algorithm.

  1. (get my-table my-key) is called.
  2. my-table is checked for the key my-key. If there is a value for the key, it is returned.
  3. Otherwise, if there is a prototype table for my-table, set my-table = my-table's prototype and go to 2. Otherwise go to 4.
  4. Return nil (the key was not found).

Janet will check up to about a 1000 prototypes recursively by default before giving up and returning nil. This is to prevent an infinite loop. This limit can be changed by adjusting the JANET_RECURSION_GUARD value in janet.h.

If table/clone is used on a table, the resulting table will share the original's prototype.

(def proto1 @{:type :custom1})

(def tab1 @{})
(get tab1 :type) # -> nil
(table/setproto tab1 proto1)
(get tab1 :type) # -> :custom1

(def tab2 (table/clone tab1))
(get tab2 :type) # -> :custom1

(put proto1 :box :treasure)

(get tab1 :box) # -> :treasure
(get tab2 :box) # -> :treasure

# tab1 and tab2 have the same prototype
(= (table/getproto tab1) (table/getproto tab2)) # -> true

If using prototypes within nested data structures, see the Copying section of the Data Structures chapter.

Note that structs also support prototype structs in a manner similar to that for tables.

Janet prototypes are not as expressive as metatables in Lua and many other languages. This is by design, as adding Lua- or Python-like capabilities would not be technically difficult. Users should prefer plain data and functions that operate on them rather than mutable objects with methods. However, some object-oriented capabilities are useful in Janet for systems that require extra flexibility.