* [Caml-list] tree walking with... specular rec functions? what else?
@ 2003-05-09 9:56 Stalkern 2
2003-05-09 15:23 ` Brian Hurt
2003-05-11 16:02 ` Xavier Leroy
0 siblings, 2 replies; 9+ messages in thread
From: Stalkern 2 @ 2003-05-09 9:56 UTC (permalink / raw)
To: caml-list
Hello to everybody
I've a simple tree structure and I want to walk it. Since in such a simple
tree structure I can go AFAIK only sidewards or upwards/downwards, and I need
to do both, I guess what can be an efficent way to do so.
I've written a rec function containing a specular copy of itself, and have
each one call each other.
However, I find this clumsy.
More exactly:
1) I don't know what is generally used to walk trees. What's it?
2) I think that this approach isn't flexible. What if I had a tree where I
can move in other directions as well? Or if I were dealing with 5-generation
grandchildren only?
3) How comes it that I rewrite the code just to have the compiler accept the
first interlaced call? What Ocaml feature did I miss?
Code is pasted below; thank you for any hint or opinion on the matter
Ernesto
---------------------------------------------------------------------------------------------------------
type treeLeafType = TreeLeafTypeBuild of (string)
and treeNodeType = TreeNodeTypeBuild of (string * (treeLeafType list) *
(treeNodeType list));;
let harvest_nodeNames (aRootNode : treeNodeType) =
let TreeNodeTypeBuild
(aRootNodeName,aRootChildrenLeavesList,aRootChildrenNodesList) = aRootNode in
let rec extract_half_nn (aTreeNodesList : treeNodeType list)
aHalfAccumRList =
match aTreeNodesList with
[] -> aHalfAccumRList
| hd::tail ->
let TreeNodeTypeBuild
(aTreeNodeName,aHalfChildrenLeavesList,aHalfChildrenNodesList) = hd in
let rec extract_flah_nn (aFlahTreeNodesList : treeNodeType list)
aFlahAccumRList =
match aFlahTreeNodesList with
[] -> aFlahAccumRList
| dh::liat ->
let TreeNodeTypeBuild
(aFlahNodeName,aFlahChildrenLeavesList,aFlahChildrenNodesList) = dh in
let pawsChildrenNamesRL = extract_half_nn aFlahChildrenNodesList [] in
extract_flah_nn liat ((aFlahNodeName^" harvested By
Flah")::(pawsChildrenNamesRL@aFlahAccumRList))
in
let swapChildrenNamesRL = extract_flah_nn aHalfChildrenNodesList [] in
extract_half_nn tail ((aTreeNodeName^" harvested By
Half")::(swapChildrenNamesRL@aHalfAccumRList)) in
extract_half_nn [aRootNode] [] ;;
---------------------------------------------------------------------------------------------------------
In practice this gives:
---------------------------------------------------------------------------------------------------------
let aTestTree = TreeNodeTypeBuild
("testTree0",
[TreeLeafTypeBuild "leaf00";
TreeLeafTypeBuild "leaf01"],
[TreeNodeTypeBuild
("subtree03",
[TreeLeafTypeBuild "leaf030";
TreeLeafTypeBuild "leaf031"],
[TreeNodeTypeBuild
("subtree032",
[],
[])
]);
TreeNodeTypeBuild
("subtree04",
[],
[TreeNodeTypeBuild
("subtree040",
[TreeLeafTypeBuild "leaf0400";
TreeLeafTypeBuild "leaf0401"],
[TreeNodeTypeBuild
("subtree0402",
[],
[])
])
])]);;
# harvest_nodeNames aTestTree;;
- : string list =
["testTree0 harvested By Half"; "subtree04 harvested By Flah";
"subtree040 harvested By Half"; "subtree0402 harvested By Flah";
"subtree03 harvested By Flah"; "subtree032 harvested By Half"]
---------------------------------------------------------------------------------------------------------
-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Caml-list] tree walking with... specular rec functions? what else?
2003-05-09 9:56 [Caml-list] tree walking with... specular rec functions? what else? Stalkern 2
@ 2003-05-09 15:23 ` Brian Hurt
2003-05-12 12:57 ` John Carr
2003-05-11 16:02 ` Xavier Leroy
1 sibling, 1 reply; 9+ messages in thread
From: Brian Hurt @ 2003-05-09 15:23 UTC (permalink / raw)
To: Stalkern 2; +Cc: caml-list
On Fri, 9 May 2003, Stalkern 2 wrote:
> Hello to everybody
>
> I've a simple tree structure and I want to walk it. Since in such a simple
> tree structure I can go AFAIK only sidewards or upwards/downwards, and I need
> to do both, I guess what can be an efficent way to do so.
Recursion is your friend. Let's assume we have a type like:
type 'a tree = Leaf
| Node of 'a * 'a tree * 'a tree
This is the most basic of tree data structures. Data can be held in any
node, the bottom of the tree is marked by leafs. We want to define a walk
function, which calls a function f on all elements of the tree, in a
depth-first pattern. This is simple:
let rec walk f tree =
match tree with
Leaf -> ()
| Node(data, left, right) ->
walk f left;
f data;
walk f right
;;
Obvious variations include which order you evaluate the last three
statements as. Equally valid would be: f data; walk f left; walk f right;
and walk f left; walk f right; f data; .
Doing a breadth first is a little bit more tricky, as you have to keep a
list of the next nodes down:
let rec walk f tree =
let rec inner lst accum =
match lst with
[] -> List.rev accum
| Leaf :: t -> inner t accum
| Node(data, left, right) :: t ->
f data;
inner t (right :: left :: accum)
in
let rec outer lst =
if (List.length lst) == 0 then ()
else outer (inner lst [])
in
outer ( [ tree ] )
;;
Basically, I keep a list of the nodes at each level. As I walk the list,
calling f on all non-leaf nodes, I create the list of the nodes at the
next level down. Note the List.rev trick I pull, to keep the nodes in the
"expected" order.
> 2) I think that this approach isn't flexible. What if I had a
> tree where I can move in other directions as well? Or if I were
> dealing with 5-generation grandchildren only?
A variant of the breadth-first walking I did above could easily generate a
list of all nodes on level 5. Dealing with multiple children is easy.
Assume that instead of the binary tree structure we had above, we had an
n'ary tree structure, like:
type 'a tree = Leaf
| Node of 'a * 'a tree list
Each node holds data and a list of 0 or more children it has. Depth first
search would then become:
let rec walk f tree =
let rec loop lst =
match lst with
[] -> ()
| h :: t -> walk f h ; loop t
in
match tree with
Leaf -> ()
| Node(data, children) ->
f data;
loop children
;;
A similiar modification works to do breadth first walking. More general
data structures aren't really trees anymore, they're graphs. But graph
walking works more or less the same way.
Hope this helps.
Brian
-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Caml-list] tree walking with... specular rec functions? what else?
2003-05-09 15:23 ` Brian Hurt
@ 2003-05-12 12:57 ` John Carr
2003-05-12 13:35 ` Michal Moskal
0 siblings, 1 reply; 9+ messages in thread
From: John Carr @ 2003-05-12 12:57 UTC (permalink / raw)
To: Brian Hurt; +Cc: caml-list
I have a minor comment unrelated to the basic algorithm.
> ...
> let rec outer lst =
> if (List.length lst) == 0 then ()
> else outer (inner lst [])
> in
> ...
In general it is better to test for empty rather than compare the size
of a collection to 0. With some collections (including lists) testing
for empty takes constant time but computing size takes linear time.
Instead of
if (List.length lst) == 0 then empty-code else full-code
either of these will be faster:
if lst == [] then empty-code else full-code
(match lst with [] -> empty-code | _ -> full-code)
-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Caml-list] tree walking with... specular rec functions? what else?
2003-05-12 12:57 ` John Carr
@ 2003-05-12 13:35 ` Michal Moskal
2003-05-12 15:06 ` David Brown
0 siblings, 1 reply; 9+ messages in thread
From: Michal Moskal @ 2003-05-12 13:35 UTC (permalink / raw)
To: John Carr; +Cc: Brian Hurt, caml-list
On Mon, May 12, 2003 at 08:57:05AM -0400, John Carr wrote:
>
> I have a minor comment unrelated to the basic algorithm.
>
> > ...
> > let rec outer lst =
> > if (List.length lst) == 0 then ()
> > else outer (inner lst [])
> > in
> > ...
>
> In general it is better to test for empty rather than compare the size
> of a collection to 0. With some collections (including lists) testing
> for empty takes constant time but computing size takes linear time.
>
> Instead of
>
> if (List.length lst) == 0 then empty-code else full-code
>
> either of these will be faster:
>
> if lst == [] then empty-code else full-code
On non-mutable structures, the behavior of (==) is
implementation-dependent.
Which means that lst = [] does not imply lst == [].
In other words, one should use:
if lst = [] then empty-code else full-code
or pattern matching, as you said.
--
: Michal Moskal :: http://www.kernel.pl/~malekith : GCS {C,UL}++++$ a? !tv
: PLD Linux ::::::::: Wroclaw University, CS Dept : {E-,w}-- {b++,e}>+++ h
-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Caml-list] tree walking with... specular rec functions? what else?
2003-05-12 13:35 ` Michal Moskal
@ 2003-05-12 15:06 ` David Brown
2003-05-12 15:24 ` Xavier Leroy
0 siblings, 1 reply; 9+ messages in thread
From: David Brown @ 2003-05-12 15:06 UTC (permalink / raw)
To: Michal Moskal; +Cc: John Carr, Brian Hurt, caml-list
On Mon, May 12, 2003 at 03:35:42PM +0200, Michal Moskal wrote:
> On non-mutable structures, the behavior of (==) is
> implementation-dependent.
>
> Which means that lst = [] does not imply lst == [].
>
> In other words, one should use:
>
> if lst = [] then empty-code else full-code
>
> or pattern matching, as you said.
Is it really not defined by Ocaml? Ocaml implements the empty list as
the integer value zero. Although (==) won't tell you if two cons-cells
have the same contents, it will tell you if they are the same.
So is there any implementation of a caml language where [] == [] isn't
always true, for any way that [] is generated?
The (=) has more overhead, and in this case, I'm not sure it is
necessary.
Dave
-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Caml-list] tree walking with... specular rec functions? what else?
2003-05-12 15:06 ` David Brown
@ 2003-05-12 15:24 ` Xavier Leroy
0 siblings, 0 replies; 9+ messages in thread
From: Xavier Leroy @ 2003-05-12 15:24 UTC (permalink / raw)
To: David Brown; +Cc: caml-list
> > Which means that lst = [] does not imply lst == [].
> >
> > In other words, one should use:
> >
> > if lst = [] then empty-code else full-code
> >
> > or pattern matching, as you said.
>
> Is it really not defined by Ocaml? Ocaml implements the empty list as
> the integer value zero. Although (==) won't tell you if two cons-cells
> have the same contents, it will tell you if they are the same.
It happens to work in this case, but relies on features of the
implementation. It's better to use "==" only between mutable data
structures, where it has a well-defined meaning (two mutable
structures are == iff an in-place modification to one of them affects
the other one as well), and "=" otherwise.
> So is there any implementation of a caml language where [] == [] isn't
> always true, for any way that [] is generated?
Both Caml Light and OCaml ensure [] == [], but again it's better not
to rely on this fact.
> The (=) has more overhead
It doesn't: the OCaml compiler is clever enough to compile "lst = []"
as a direct comparison against the integer value zero.
- Xavier Leroy
-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Caml-list] tree walking with... specular rec functions? what else?
2003-05-09 9:56 [Caml-list] tree walking with... specular rec functions? what else? Stalkern 2
2003-05-09 15:23 ` Brian Hurt
@ 2003-05-11 16:02 ` Xavier Leroy
2003-05-12 6:55 ` Stalkern 2
1 sibling, 1 reply; 9+ messages in thread
From: Xavier Leroy @ 2003-05-11 16:02 UTC (permalink / raw)
To: Stalkern 2; +Cc: caml-list
> I've a simple tree structure and I want to walk it. Since in such a
> simple tree structure I can go AFAIK only sidewards or
> upwards/downwards, and I need to do both, I guess what can be an
> efficent way to do so.
That sounds like a job for Gérard Huet's "zippers":
G. Huet. The Zipper. Journal of Functional Programming, 7 (5), Sept
1997, pp. 549--554.
Apparently, the paper isn't freely available on-line, but see
http://www.informatik.uni-bonn.de/~ralf/publications/TheWeb.ps.gz
for a quick overview of the zipper, and more advanced stuff.
- Xavier Leroy
-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Caml-list] tree walking with... specular rec functions? what else?
2003-05-11 16:02 ` Xavier Leroy
@ 2003-05-12 6:55 ` Stalkern 2
2003-05-12 10:14 ` Gérard Huet
0 siblings, 1 reply; 9+ messages in thread
From: Stalkern 2 @ 2003-05-12 6:55 UTC (permalink / raw)
To: Xavier Leroy; +Cc: caml-list
Il Sunday 11 May 2003 18:02, Xavier Leroy ha scritto:
> > I've a simple tree structure and I want to walk it. Since in such a
> > simple tree structure I can go AFAIK only sidewards or
> > upwards/downwards, and I need to do both, I guess what can be an
> > efficent way to do so.
>
> That sounds like a job for Gérard Huet's "zippers":
>
> G. Huet. The Zipper. Journal of Functional Programming, 7 (5), Sept
> 1997, pp. 549--554.
>
> Apparently, the paper isn't freely available on-line, but see
>
> http://www.informatik.uni-bonn.de/~ralf/publications/TheWeb.ps.gz
>
> for a quick overview of the zipper, and more advanced stuff.
>
Thank you very much. I'm now using also a posting about zippers on this list
http://caml.inria.fr/archives/200304/msg00202.html and I was suggested to
take a look at http://pauillac.inria.fr/~remy/cours/appsem/ocaml-ml.html
Thank you
Ernesto Torresin
-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Caml-list] tree walking with... specular rec functions? what else?
2003-05-12 6:55 ` Stalkern 2
@ 2003-05-12 10:14 ` Gérard Huet
0 siblings, 0 replies; 9+ messages in thread
From: Gérard Huet @ 2003-05-12 10:14 UTC (permalink / raw)
To: stalkern2; +Cc: caml-list
Le lundi, 12 mai 2003, à 08:55 Europe/Paris, Stalkern 2 a écrit :
> Il Sunday 11 May 2003 18:02, Xavier Leroy ha scritto:
>>> I've a simple tree structure and I want to walk it. Since in such a
>>> simple tree structure I can go AFAIK only sidewards or
>>> upwards/downwards, and I need to do both, I guess what can be an
>>> efficent way to do so.
>>
>> That sounds like a job for Gérard Huet's "zippers":
>>
>> G. Huet. The Zipper. Journal of Functional Programming, 7 (5), Sept
>> 1997, pp. 549--554.
>>
>> Apparently, the paper isn't freely available on-line, but see
>>
>> http://www.informatik.uni-bonn.de/~ralf/publications/TheWeb.ps.gz
>>
>> for a quick overview of the zipper, and more advanced stuff.
>>
>
> Thank you very much. I'm now using also a posting about zippers on
> this list
> http://caml.inria.fr/archives/200304/msg00202.html and I was suggested
> to
> take a look at
> http://pauillac.inria.fr/~remy/cours/appsem/ocaml-ml.html
>
Hello
My original zipper paper is not on-line, but my latest thoughts on the
subject are given in
"Linear Contexts and the Sharing Functor: Techniques for Symbolic
Computation", available from
http://pauillac.inria.fr/~huet/PUBLIC/DB.pdf
Gerard
-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2003-05-12 15:24 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-05-09 9:56 [Caml-list] tree walking with... specular rec functions? what else? Stalkern 2
2003-05-09 15:23 ` Brian Hurt
2003-05-12 12:57 ` John Carr
2003-05-12 13:35 ` Michal Moskal
2003-05-12 15:06 ` David Brown
2003-05-12 15:24 ` Xavier Leroy
2003-05-11 16:02 ` Xavier Leroy
2003-05-12 6:55 ` Stalkern 2
2003-05-12 10:14 ` Gérard Huet
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox