Giter Site home page Giter Site logo

otom's Introduction

One-To-One Map

A One-To-One Map enforces a one-to-one relationship between keys and values.

Installation

Install using LuaRocks:

luarocks install otom

Alternatively, you could just grab otom.lua and use it directly in your project.

Testing

This module uses busted for testing. Once you have that installed, navigate to the repository root directory and run:

busted .

Basic Use

otom = require("otom")
t = otom.new()
t.x = "Hello"
t.y = "Hello"
assert(t.x == nil)
assert(t.y == "Hello")

Since there is a one-to-one relationship between keys and values, it becomes trivial to find a key for a given value. otom heavily supports this feature: otom.new() returns both a "forward table" which maps keys to values and a "reverse table" which maps values to keys. Every feature supported by the forward table is supported by the reverse table as well.

ft, rt = otom.new()
ft.x = "Hello"
ft.y = "World"
assert(rt.Hello == "x")
assert(rt.World == "y")

These tables are proxies. However, thanks to the __pairs metamethod in Lua 5.3 it is still possible to use pairs and ipairs as usual.

assert(rawget(ft, "x") == nil)
assert(rawget(rt, "Hello") == nil)
for k,v in pairs(ft) do
	assert(rt[v] == k)
end
for k,v in pairs(rt) do
	assert(ft[v] == k)
end

As of version 1.1 using one-to-one maps as arrays is supported.

ft = otom.new()
planets = { "Mercury", "Venus", "Earth", "Mars" }
for i,v in ipairs(planets) do
	table.insert(ft, v)
end
assert(#ft == 4)
for i,v in ipairs(planets) do
	assert(ft[i] == v)
end

Initial Tables and Iterator Factories

A one-to-one map can be created from a regular table.

planets = { "Mercury", "Venus", "Earth", "Mars" }
planet_ft, planet_rt = otom.new(planets)
for i,v in ipairs(planet_ft) do
	assert(planet_rt[v] == i)
end

otom.new takes up to three arguments related to handling this initial table.

otom.new([initial_table], [repeat_mode], [iter_factory])

repeat_mode

By default, if the initial table has a repeated value, otom.new throws an error.

res = pcall(function() t = otom.new({ "A", "A", "B" }) end)
assert(res == false)

However this behaviour can be changed by setting repeat_mode to one of the following values:

  • otom.ERR: when a repeated value is found, throw an error (default behaviour).
  • otom.FIRST: when a repeated value is found, only preserve the first key-value association encountered with that value.
  • otom.LAST: when a repeated value is found, only preserve the last key-value association encountered with that value.

The initial table is traversed in an order defined (or undefined, in the case of pairs) by the iter_factory argument.

iter_factory

By default, the initial table is traversed using pairs. However, that might not always be the optimal choice for traversal, especially since the order of keys accessed by pairs is not specified.

The iter_factory is an iterator factory function that will be called with the initial table as an argument. It will be used in a generic for loop to traverse that table. Among the functions in the Lua standard library, pairs and ipairs are the better choices of iterator factory.

Setting the iter_factory to ipairs allows you to use repeat_mode to predictably handle repeated values in the initial table.

t = otom.new({ "A", "A", "B" }, otom.FIRST, ipairs)
assert(t[1] == "A")
assert(t[2] == nil)
assert(t[3] == "B")

t = otom.new({ "A", "A", "B" }, otom.LAST, ipairs)
assert(t[1] == nil)
assert(t[2] == "A")
assert(t[3] == "B")

You can use other iterator factories if you wish. Iterators and iterator factories are explained extensively in this section of PIL.

It is possible to do away with having an initial table entirely if the iterator factory can produce all the necessary values.

t = otom.new(nil, nil, my_awesome_iter)

The above code will call my_awesome_iter(nil) to try extracting keys and values to be used in the forward table (which will become the value and keys, respectively, of the reverse table).

for k,v in my_awesome_iter(nil) do
	--Place k,v correctly
end

Hacking

This is outside the supported use of this module, but it is possible to bypass the one-to-one restriction like so:

t = otom.new({ "A", "B" })
_, rawt = pairs(t)
rawt[3] = "A"
for k,v in pairs(t) do
	print(k, v) --The value "A" is repeated.
end

The rawt variable is a table which actually stores the values retrieved through t. Doing this puts the forward and reverse tables "out-of-sync".

It may be useful to access rawt when writing iterators and iterator factories. However for most tasks it is probably best to avoid messing with rawt.

otom's People

Contributors

ratanvarghese avatar

Stargazers

Gábor Nagymajtényi avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.