mirror of
https://github.com/c-cube/ocaml-containers.git
synced 2025-12-06 11:15:31 -05:00
updated roseTree (cosmetic; printer; to_seq) and test
This commit is contained in:
parent
b599e9941a
commit
8f66f0d7d8
3 changed files with 96 additions and 32 deletions
|
|
@ -1,11 +1,48 @@
|
||||||
|
|
||||||
|
(*
|
||||||
|
copyright (c) 2013-2014, Simon Cruanes, Emmanuel Surleau
|
||||||
|
all rights reserved.
|
||||||
|
|
||||||
|
redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer. redistributions in binary
|
||||||
|
form must reproduce the above copyright notice, this list of conditions and the
|
||||||
|
following disclaimer in the documentation and/or other materials provided with
|
||||||
|
the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*)
|
||||||
|
|
||||||
|
|
||||||
type +'a t = [`Node of 'a * 'a t list]
|
type +'a t = [`Node of 'a * 'a t list]
|
||||||
|
|
||||||
type 'a tree = 'a t
|
type 'a tree = 'a t
|
||||||
|
|
||||||
|
type 'a sequence = ('a -> unit) -> unit
|
||||||
|
type 'a printer = Format.formatter -> 'a -> unit
|
||||||
|
|
||||||
let rec fold ~f init_acc (`Node (value, children)) =
|
let rec fold ~f init_acc (`Node (value, children)) =
|
||||||
let acc = f value init_acc in
|
let acc = f value init_acc in
|
||||||
List.fold_left (fun acc' child_node -> fold ~f acc' child_node) acc children
|
List.fold_left (fun acc' child_node -> fold ~f acc' child_node) acc children
|
||||||
|
|
||||||
|
let to_seq t yield =
|
||||||
|
let rec iter (`Node (value, children)) =
|
||||||
|
yield value;
|
||||||
|
List.iter iter children
|
||||||
|
in
|
||||||
|
iter t
|
||||||
|
|
||||||
let split_at_length_minus_1 l =
|
let split_at_length_minus_1 l =
|
||||||
let rev_list = List.rev l in
|
let rev_list = List.rev l in
|
||||||
match rev_list with
|
match rev_list with
|
||||||
|
|
@ -13,7 +50,7 @@ let split_at_length_minus_1 l =
|
||||||
| [item] -> ([], Some item)
|
| [item] -> ([], Some item)
|
||||||
| item::items -> (List.rev items, Some item)
|
| item::items -> (List.rev items, Some item)
|
||||||
|
|
||||||
let print formatter string_of_value tree =
|
let print pp_val formatter tree =
|
||||||
let rec print_children children indent_string =
|
let rec print_children children indent_string =
|
||||||
let non_last_children, maybe_last_child =
|
let non_last_children, maybe_last_child =
|
||||||
split_at_length_minus_1 children
|
split_at_length_minus_1 children
|
||||||
|
|
@ -26,7 +63,7 @@ let print formatter string_of_value tree =
|
||||||
List.iter (fun (`Node (child_value, grandchildren)) ->
|
List.iter (fun (`Node (child_value, grandchildren)) ->
|
||||||
Format.pp_print_string formatter indent_string;
|
Format.pp_print_string formatter indent_string;
|
||||||
Format.pp_print_string formatter "|- ";
|
Format.pp_print_string formatter "|- ";
|
||||||
string_of_value child_value |> Format.pp_print_string formatter;
|
pp_val formatter child_value;
|
||||||
Format.pp_force_newline formatter ();
|
Format.pp_force_newline formatter ();
|
||||||
let indent_string' = indent_string ^ "| " in
|
let indent_string' = indent_string ^ "| " in
|
||||||
print_children grandchildren indent_string'
|
print_children grandchildren indent_string'
|
||||||
|
|
@ -34,13 +71,13 @@ let print formatter string_of_value tree =
|
||||||
and print_last_child (`Node (last_child_value, last_grandchildren)) indent_string =
|
and print_last_child (`Node (last_child_value, last_grandchildren)) indent_string =
|
||||||
Format.pp_print_string formatter indent_string;
|
Format.pp_print_string formatter indent_string;
|
||||||
Format.pp_print_string formatter "'- ";
|
Format.pp_print_string formatter "'- ";
|
||||||
string_of_value last_child_value |> Format.pp_print_string formatter;
|
pp_val formatter last_child_value;
|
||||||
Format.pp_force_newline formatter ();
|
Format.pp_force_newline formatter ();
|
||||||
let indent_string' = indent_string ^ " " in
|
let indent_string' = indent_string ^ " " in
|
||||||
print_children last_grandchildren indent_string'
|
print_children last_grandchildren indent_string'
|
||||||
in
|
in
|
||||||
let print_root (`Node (root_value, root_children)) =
|
let print_root (`Node (root_value, root_children)) =
|
||||||
string_of_value root_value |> Format.pp_print_string formatter;
|
pp_val formatter root_value;
|
||||||
Format.pp_force_newline formatter ();
|
Format.pp_force_newline formatter ();
|
||||||
print_children root_children ""
|
print_children root_children ""
|
||||||
in
|
in
|
||||||
|
|
|
||||||
|
|
@ -1,39 +1,67 @@
|
||||||
(**
|
|
||||||
{1 Rose Tree}
|
(*
|
||||||
|
copyright (c) 2013-2014, Simon Cruanes, Emmanuel Surleau
|
||||||
|
all rights reserved.
|
||||||
|
|
||||||
|
redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer. redistributions in binary
|
||||||
|
form must reproduce the above copyright notice, this list of conditions and the
|
||||||
|
following disclaimer in the documentation and/or other materials provided with
|
||||||
|
the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*)
|
||||||
|
|
||||||
|
(** {1 Rose Tree}
|
||||||
|
|
||||||
A persistent, non-lazy tree where each node may have an arbitrary number of
|
A persistent, non-lazy tree where each node may have an arbitrary number of
|
||||||
children.
|
children.
|
||||||
|
|
||||||
@since NEXT_RELEASE
|
@since NEXT_RELEASE *)
|
||||||
*)
|
|
||||||
|
|
||||||
(**
|
(** The type of a tree node - a (value, children) pair. *)
|
||||||
The type of a tree node - a (value, children) pair.
|
|
||||||
*)
|
|
||||||
type +'a t = [`Node of 'a * 'a t list]
|
type +'a t = [`Node of 'a * 'a t list]
|
||||||
|
|
||||||
type 'a tree = 'a t
|
type 'a tree = 'a t
|
||||||
|
|
||||||
|
type 'a sequence = ('a -> unit) -> unit
|
||||||
|
type 'a printer = Format.formatter -> 'a -> unit
|
||||||
|
|
||||||
(**
|
(**
|
||||||
Folds over the tree. Takes a function [f node accumulator], an initial value
|
Folds over the tree. Takes a function [f node accumulator], an initial value
|
||||||
for the accumulator, and the tree to operate on.
|
for the accumulator, and the tree to operate on.
|
||||||
*)
|
*)
|
||||||
val fold : f : ('a -> 'b -> 'b) -> 'b -> 'a t -> 'b
|
val fold : f : ('a -> 'b -> 'b) -> 'b -> 'a t -> 'b
|
||||||
|
|
||||||
|
(** Iterate over the tree *)
|
||||||
|
val to_seq : 'a t -> 'a sequence
|
||||||
|
|
||||||
(**
|
(**
|
||||||
Tree pretty-printer. Takes a [Formatter], a function turning a node into a
|
Tree pretty-printer. Takes a [Formatter], a function turning a node into a
|
||||||
string, and the tree itself as parameters. Appends the result to the
|
string, and the tree itself as parameters. Appends the result to the
|
||||||
formatter.
|
formatter.
|
||||||
*)
|
*)
|
||||||
val print : Format.formatter -> ('a -> string) -> 'a t -> unit
|
val print : 'a printer -> 'a t printer
|
||||||
|
|
||||||
|
(**
|
||||||
|
{2 Zipper}
|
||||||
|
|
||||||
|
A zipper to navigate and return modified versions of the tree.
|
||||||
|
*)
|
||||||
module Zipper : sig
|
module Zipper : sig
|
||||||
|
|
||||||
(**
|
|
||||||
{2 Zipper}
|
|
||||||
|
|
||||||
A zipper to navigate and return modified versions of the tree.
|
|
||||||
*)
|
|
||||||
type 'a t
|
type 'a t
|
||||||
|
|
||||||
(**
|
(**
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,10 @@
|
||||||
open Containers_misc
|
open Containers_misc
|
||||||
open OUnit
|
open OUnit
|
||||||
|
|
||||||
let format_node value = Printf.sprintf "%d" value
|
let format_node = Format.pp_print_int
|
||||||
|
|
||||||
let string_of_tree tree =
|
let string_of_tree tree =
|
||||||
CCFormat.sprintf "%a" (fun formatter value ->
|
CCFormat.sprintf "%a" (RoseTree.print format_node) tree
|
||||||
RoseTree.print formatter format_node tree) tree
|
|
||||||
|
|
||||||
let assert_equal_tree expected_tree_rep tree =
|
let assert_equal_tree expected_tree_rep tree =
|
||||||
let expected_tree_rep_string =
|
let expected_tree_rep_string =
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue