Janet 1.16.1-87f8fe1 Documentation
(Other Versions: 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 )


To support basic generic programming, Janet tables support a prototype table. A prototype table contains default values for a table 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 in Janet
(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))

(print (thing1 :type)) # prints :custom1
(print (thing2 :type)) # prints :custom2

(:behave thing1 :a) # prints "behaving :a"
(:behave thing2 :b) # prints "behaving 2 :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. 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 as 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 value can be changed by adjusting the JANET_RECURSION_GUARD value in janet.h.

Note that 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.