Introduce types for forward compiler compatiblity

After Crystal 0.15, compiler will require declare the types used
by instance variables on classes.

This require changes to the usage of `Radix::Tree` by introducing
the type of payload elements it will handle:

    # Will only support symbols as payload
    tree = Radix::Tree(Symbol).new
    tree.add "/", :root

    # Error: cannot add node with anything other than Symbol
    tree.add "/meaning-of-life", 42

The changes ensure future compatibility with Crystal and also
enforces a more declarative usage of `Radix::Tree`.

If necessary, you can combine multiple types to ensure a tree
can contain all the wide range of payloads you need:

    tree = Radix::Tree.new(Foo | Bar | Symbol).new
    tree.add "/", :root
    tree.add "/foo", foo_instance

This change includes:

- Tree, Node and Result has been updated to require types.
- Node is capable of have optional payload (from defined type).
- Documentation has been updated to reflect this change.
This commit is contained in:
Luis Lavena 2016-04-14 20:46:12 -03:00
parent 18bf9b132e
commit 9003075ec7
8 changed files with 190 additions and 109 deletions

View file

@ -4,7 +4,7 @@ module Radix
describe Node do
describe "#key=" do
it "accepts change of key after initialization" do
node = Node.new("abc")
node = Node(Nil).new("abc")
node.key.should eq("abc")
node.key = "xyz"
@ -23,39 +23,45 @@ module Radix
node.payload.should eq(1_000)
end
# This example focuses on the internal representation of `payload`
# as inferred from supplied types and default values.
#
# We cannot compare `typeof` against `property!` since it excludes `Nil`
# from the possible types.
it "makes optional to provide a payload" do
node = Node.new("abc")
node = Node(Int32).new("abc")
node.payload?.should be_falsey
typeof(node.@payload).should eq(Int32 | Nil)
end
end
describe "#priority" do
it "calculates it based on key size" do
node = Node.new("a")
node = Node(Nil).new("a")
node.priority.should eq(1)
node = Node.new("abc")
node = Node(Nil).new("abc")
node.priority.should eq(3)
end
it "returns zero for catch all (globbed) key" do
node = Node.new("*filepath")
node = Node(Nil).new("*filepath")
node.priority.should eq(0)
node = Node.new("/src/*filepath")
node = Node(Nil).new("/src/*filepath")
node.priority.should eq(0)
end
it "returns one for keys with named parameters" do
node = Node.new(":query")
node = Node(Nil).new(":query")
node.priority.should eq(1)
node = Node.new("/search/:query")
node = Node(Nil).new("/search/:query")
node.priority.should eq(1)
end
it "changes when key changes" do
node = Node.new("a")
node = Node(Nil).new("a")
node.priority.should eq(1)
node.key = "abc"
@ -71,10 +77,10 @@ module Radix
describe "#sort!" do
it "orders children by priority" do
root = Node.new("/")
node1 = Node.new("a")
node2 = Node.new("bc")
node3 = Node.new("def")
root = Node(Int32).new("/")
node1 = Node(Int32).new("a", 1)
node2 = Node(Int32).new("bc", 2)
node3 = Node(Int32).new("def", 3)
root.children.push(node1, node2, node3)
root.sort!
@ -85,10 +91,10 @@ module Radix
end
it "orders catch all and named parameters lower than others" do
root = Node.new("/")
node1 = Node.new("*filepath")
node2 = Node.new("abc")
node3 = Node.new(":query")
root = Node(Int32).new("/")
node1 = Node(Int32).new("*filepath", 1)
node2 = Node(Int32).new("abc", 2)
node3 = Node(Int32).new(":query", 3)
root.children.push(node1, node2, node3)
root.sort!