Semantics of records as first class data

note: The semantics illustrated above should not be taken as implementation detail. at the moment <validation> is undefined and should be considered a no-op.

The <initialization value> refers to the same default default values for Java primitive types (as defined by type hinting on the record fields) or nil for instances. For record reader forms, the keys and values must remain as constants as their semantics require that the readable form coincide with the evalable form.

Record and Type reader forms

There would be two additional reader forms added to Clojure.

Labelled record reader form

No Format

#myns.MyRecord{:a 1, :b 2}

Positional record and type reader forms

No Format

#myns.MyRecord[1 2]

and

No Format

#myns.MyType[1 2]

This syntax satisfies the need for a general-purpose Java class construction reader form. However, not all Java classes are considered fully constructed after the use of their constructors. Therefore, serialization support is not provided for any Java classes by default. For instances such as these, Clojure will continue to provide facilities via print-dup in the known ways.

Generated factory functions

When defining a new defrecord, two functions will also be defined in the same namespace as the record itself. For new deftypes, only the positional constructor outlined below is generated.

Factory function taking a map (defrecord only)

A factory function named map->MyRecord taking a map is defined by defrecord.

No Format

(myns/map->MyRecord {:a 1, :b 2})
;=> #myns.MyRecord{:a 1, :b 2}

Factory function taking positional values (defrecord and deftype)

A factory function named ->MyRecord taking positional values (as defined by the record ctor) is also defined by defrecord.

No Format

(myns/->MyRecord 1 2)
;=> #myns.MyRecord{:a 1, :b 2}

and

No Format

(myns/->MyType 1 2)
;=> #<MyType myns.MyType@2ed277f2>

Writing records

When writing record data for the purposes of serialization, the positional reader form is used by default:

Tool support

Defining Clojure defrecords will also expose static class methods useable at the Java API level. These methods are not documented with the intention of public consumption and are considered implementation details.

Static factory for defrecords

The static factory exposed will mirror the map->MyRecord function:

No Format

(MyRecord/create aMap)

Basis access

A static factory allowing access to the basis keys will also be provided:

No Format

(MyRecord/getBasis)
;=> [a b]

and

No Format

(MyType/getBasis)
;=> [a b]

The getBasis method will return a PersistentVector of Symbols with (potentially) attached metadata for each field.

Tentative Proposal 2:

people can build their own defaults, validation, etc. easily with macros, given this

Some history:

The record multimethod was almost ready to go when Rich raised the GC issue. What happens when somebody creates a ton of record classes over time? GC can collect records that are not longer in use, but doesn't clean up the old multimethod functions.