Module std.prototype.container

Container Prototype.

This module supplies the root prototype object from which every other object is descended. There are no classes as such, rather new objects are created by cloning an existing object, and then changing or adding to the clone. Further objects can then be made by cloning the changed object, and so on.

The functionality of a container based object is entirely defined by its metamethods. However, since we can store any object in a container, we cannot rely on the __index metamethod, because it is only a fallback for when that key is not already in the container itself. Of course that does not entirely preclude the use of __index with containers, so long as this limitation is observed.

When making your own prototypes, derive from prototype.container.prototype if you want to access the contents of your containers with the [] operator, otherwise from prototype.object.prototype if you want to access the functionality of your objects with named object methods.

Prototype Chain

table
 `-> Container

Objects

prototype Container prototype.

Metamethods

prototype:__call (...) Return a clone of this container and its metatable.
prototype:__pairs () Return an in-order iterator over public object fields.
prototype:__tostring () Return a compact string representation of this object.

Module Functions

mapfields (new, src[, map={}]) Return new with references to the fields of src merged in.


Objects

prototype
Container prototype.

Fields:

  • _init table or function object initialisation (optional)
  • _type string object name (default "Container")

Usage:

     local Container = require "prototype.container".prototype
     local Graph = Container { _type = "Graph" }
     local function nodes (graph)
       local n = 0
       for _ in pairs (graph) do n = n + 1 end
       return n
     end
     local g = Graph { "node1", "node2" }
     assert (nodes (g) == 2)

Metamethods

prototype:__call (...)
Return a clone of this container and its metatable.

Like any Lua table, a container is essentially a collection of field_n = value_n pairs, except that field names beginning with an underscore _ are usually kept in that container's metatable where they define the behaviour of a container object rather than being part of its actual contents. In general, cloned objects also clone the behaviour of the object they cloned, unless...

When calling prototype.container.prototype, you pass a single table argument with additional fields (and values) to be merged into the clone. Any field names beginning with an underscore _ are copied to the clone's metatable, and all other fields to the cloned container itself. For instance, you can change the name of the cloned object by setting the _type field in the argument table.

The _init private field is also special: When set to a sequence of field names, unnamed fields in the call argument table are assigned to those field names in subsequent clones, like the example below.

Alternatively, you can set the _init private field of a cloned container object to a function instead of a sequence, in which case all the arguments passed when it is called/cloned (including named and unnamed fields in the initial table argument, if there is one) are passed through to the _init function, following the nascent cloned object. See the mapfields usage example below.

Parameters:

  • ... arguments to prototype's _init, often a single table

Returns:

    prototype clone of this container, with shared or merged metatable as appropriate

Usage:

     local Cons = Container {_type="Cons", _init={"car", "cdr"}}
     local list = Cons {"head", Cons {"tail", nil}}
prototype:__pairs ()
Return an in-order iterator over public object fields.

Returns:

  1. function iterator function
  2. Object self

Usage:

    for k, v in pairs (anobject) do process (k, v) end
prototype:__tostring ()
Return a compact string representation of this object.

First the container name, and then between { and } an ordered list of the array elements of the contained values with numeric keys, followed by asciibetically sorted remaining public key-value pairs.

This metamethod doesn't recurse explicitly, but relies upon suitable __tostring metamethods for non-primitive content objects.

Returns:

    string stringified object representation

See also:

Usage:

    assert (tostring (list) == 'Cons {car="head", cdr=Cons {car="tail"}}')

Module Functions

mapfields (new, src[, map={}])
Return new with references to the fields of src merged in.

This is the function used to instantiate the contents of a newly cloned container, as called by __call above, to split the fields of a __call argument table into private "_" prefixed field namess, -- which are merged into the new metatable, and public (everything else) names, which are merged into new itself.

You might want to use this function from _init functions of your own derived containers.

Parameters:

  • new table partially instantiated clone container
  • src table __call argument table that triggered cloning
  • map table key renaming specification in the form {old_key=new_key, ...} (default {})

Returns:

    table merged public fields from new and src, with a metatable of private fields (if any), both renamed according to map

Usage:

     local Bag = Container {
       _type = "Bag",
       _init = function (new, ...)
         if type (...) == "table" then
           return container.mapfields (new, (...))
         end
         return functional.reduce (operator.set, new, ipairs, {...})
       end,
     }
     local groceries = Bag ("apple", "banana", "banana")
     local purse = Bag {_type = "Purse"} ("cards", "cash", "id")
generated by LDoc 1.4.3 Last updated 2016-02-08 00:31:49