ReflectionΒΆ

Note: the features shown here can change as the language internals evolve

Every value in Closet can hold metadata. When set, the metadata is a dictionary, which can contain entries for things like documentation.

If you come from a language which supports docstrings, the idea is similar.

However, in Closet, the metadata can hold more than a docstring. For instance, functions, macros or classes expose their own source code in their metadata, as well as the name they were defined with. Macros also use their metadata to tell the interpreter how to show the result of macro expansion in stacktraces, although this part is not fully implemented yet. In addition, any value can be annotated. This can be useful when documenting global constants, for example.

Documentation and metadata can be accessed with:

(def (f)
  "This is a docstring"
  (print "hello world"))
(print (get-doc f))
(print (repr (get-metadata f)))
; result:
;This is a docstring
;(dict
;      name "f"
;      source (def (f) "This is a docstring" (print "hello world")))

Note: In the source code entry of the metadata generated by (def), the value stored is the code itself, not a string representation

The type of a value can be inspected with (get-type):

(= (get-type 1) integer) ; true

The (get-closure) function can be used to get the environment in which a function was defined:

(let name "value"
  (def (f) name))
(get-closure f)  # (env name "value" ...)

With (repr), the source code metadata generated by (def), (defclass) and (defmacro), the embedded documentation, and the ability to explore the language internals, it is very easy to do exploratory programming and experiment interactively with Antilisp.