Tour

patch = require 'patch'

The core verb of patch is patch.apply. As the name suggests, it applies a patch to an existing value, and spits out the result:

-- Replace the input (1) with the new value (2)
value = 1
value, undo = patch.apply(value, 2) -- replace value with 2

print(value) -- 2

Patches are normal Lua values. Here we used the number 2, but we can update a value to whatever we want.

value, undo2 = patch.apply(value, "magic")    --       2 -> "magic"
value, undo3 = patch.apply(value, {"carpet"}) -- "magic" -> {"carpet"}

Undo

Every time you call apply, in addition to the the result value, it will also spit out an "undo" patch. This will be an inverse of the input patch: if you give the current value and the undo back to apply it will give you the original value.

value, _ = patch.apply(value, undo3) -- {"carpet"} -> "magic"
value, _ = patch.apply(value, undo2) --    "magic" -> 2
value, _ = patch.apply(value, undo)  --          2 -> 1

Merges

Patch supports more complex operations than simple replacement, though. When the patch and the input are both tables, then each value in the patch table is recursively applied to the input, like so:

t = { a = 1, 'a', 'b', 'c'}
t2, _ = patch.apply(t,  {[2] = 2})           -- t2[2]    = 2
t3, _ = patch.apply(t2, {a = {age = "old"}}) -- t3.a     = {age = "old"}
t4, _ = patch.apply(t3, {a = {age = "new"}}) -- t4.a.age = "new"

Mutation

When working with stateful types like this, apply makes the guarantee that it won't modify the input table:

print(t == t4)   -- false
print(t.a)       -- b
print(t2.a)      -- 2
print(t3[2].age) -- old

But if you'd rather reuse a single instance of a datastructure, you can use patch.apply_inplace instead.

t5, _ = patch.apply_inplace(t4, {a = 3}) -- t4.a = 3

print(t4 == t5)     -- true
print(t4.a == t5.a) -- true

Updaters

These two primitive behaviors, replacing and merging, work for many of changes you might want to make to a table. However, this can't represent everything. For example, if you want to set a field in a table to nil, this won't work:

patch.apply({field = "set"}, {field = nil}) -- {field = "set"}, nil

That's because in Lua, nil is the same as undefined. instead of passing in a field set to nil, we've passed in nothing at all!

To fix this we use Updaters. An updater is a simple marker that suggests that patch should do something special when applying it. For this specific example, we can use the patch.Nil updater, which will always replace the input with nil:

patch.apply({field = "set"}, {field = patch.Nil} -- {}, {field = "set"}

Some other important updaters include patch.chain, which will "chain" patches together, left-to-right, and patch.insert_i and patch.remove_i which are shortcuts for using table.insert and table.remove respectively.

generated by LDoc 1.4.5 Last updated 2016-09-01 05:47:16