Browse Source

added depth/1 also clean up, dialyzer runs clean

pull/2/head
Sean Copenhaver 11 years ago
parent
commit
46ad37188d
  1. 46
      lib/rope.ex
  2. 11
      test/rope_test.exs

46
lib/rope.ex

@ -18,11 +18,13 @@ defmodule Rope do
defrecordp :rnode, Rope, defrecordp :rnode, Rope,
length: 0 :: non_neg_integer, length: 0 :: non_neg_integer,
depth: 1 :: non_neg_integer,
left: nil :: Rope, left: nil :: Rope,
right: nil :: Rope right: nil :: Rope
defrecordp :rleaf, Rope, defrecordp :rleaf, Rope,
length: 0 :: non_neg_integer, length: 0 :: non_neg_integer,
depth: 0 :: non_neg_integer,
value: nil :: binary value: nil :: binary
@ -31,12 +33,18 @@ defmodule Rope do
@type codepoint :: t @type codepoint :: t
@type grapheme :: t @type grapheme :: t
@type rope :: Rope.t | nil
@doc """ @doc """
Creates a new rope with the string provided Creates a new rope with the string provided
""" """
@spec new(t) :: Rope.t @spec new(t | nil) :: rope
def new(str) do def new(nil) do
nil
end
def new(str) when is_binary(str) do
rleaf(length: String.length(str), value: str) rleaf(length: String.length(str), value: str)
end end
@ -44,7 +52,7 @@ defmodule Rope do
@doc """ @doc """
Concatenates two ropes together producing a new single rope. Concatenates two ropes together producing a new single rope.
""" """
@spec concat(Rope.t | nil, Rope.t | nil) :: Rope.t | nil @spec concat(rope | t, rope | t) :: rope
def concat(nil, nil) do def concat(nil, nil) do
nil nil
end end
@ -61,7 +69,10 @@ defmodule Rope do
rope1 = ropeify rope1 rope1 = ropeify rope1
rope2 = ropeify rope2 rope2 = ropeify rope2
rnode(left: rope1, depth = Enum.max([rope1.depth, rope2.depth]) + 1
rnode(depth: depth,
left: rope1,
right: rope2, right: rope2,
length: rope1.length + rope2.length) length: rope1.length + rope2.length)
end end
@ -73,7 +84,7 @@ defmodule Rope do
Similar to String.slice/3 Similar to String.slice/3
""" """
@spec slice(Rope.t | nil, integer, integer) :: Rope.t | nil @spec slice(rope, integer, integer) :: rope
def slice(nil, _start, _len) do def slice(nil, _start, _len) do
nil nil
end end
@ -113,17 +124,26 @@ defmodule Rope do
@doc """ @doc """
Retrieve the length in ut8 characters in the rope. Retrieve the length in ut8 characters in the rope.
""" """
@spec length(Rope.t | t | nil) :: integer @spec length(rope) :: non_neg_integer
def length(rleaf(length: len)) do def length(rope) do
len case rope do
nil -> 0
rleaf(length: len) -> len
rnode(length: len) -> len
end end
def length(rnode(length: len)) do
len
end end
def length(rope) do
String.length rope @doc """
Returns the depth of the rope tree.
"""
@spec depth(rope) :: non_neg_integer
def depth(rope) do
case rope do
nil -> 0
rnode(depth: depth) -> depth
rleaf(depth: depth) -> depth
end
end end

11
test/rope_test.exs

@ -110,6 +110,15 @@ defmodule RopeTest do
assert Rope.length(rope) == String.length("") assert Rope.length(rope) == String.length("")
end end
test "get the depth of a rope" do
rope = build_rope @simple
assert Rope.depth(rope) == 1
rope = build_rope @longtext
assert Rope.depth(rope) == 185
end
defp build_rope(text) do defp build_rope(text) do
words = text words = text
|> String.split(" ") |> String.split(" ")
@ -118,7 +127,7 @@ defmodule RopeTest do
words words
|> Enum.drop(1) |> Enum.drop(1)
|> Enum.reduce(first, fn (word, rope) -> Rope.concat(rope, " " <> word) end) |> Enum.reduce(Rope.new(first), fn (word, rope) -> Rope.concat(rope, " " <> word) end)
end end
defp is_equal(rope, str) do defp is_equal(rope, str) do

Loading…
Cancel
Save