* Re: [Caml-list] recursion/iterator question
2006-04-16 21:11 recursion/iterator question Tato Thetza
@ 2006-04-16 22:00 ` David Powers
2006-04-16 22:27 ` Martin Jambon
` (3 subsequent siblings)
4 siblings, 0 replies; 13+ messages in thread
From: David Powers @ 2006-04-16 22:00 UTC (permalink / raw)
To: Tato Thetza; +Cc: caml-list
The best way would probably be to write a permutation function that
returns a list of triplets given a list, and then to use List.iter and a
local function to split out each triplet to work on the component
parts... something like:
let for_each_trip lst =
let real_work (a, b, c) =
(* do some stuff with a b and c in here *)
in
List.iter real_work (permute_triples lst)
(loose code - forgive my laziness)
This could be made more general by improving the permute code to take a
number option and to return triplets of that number (permute 3 lst).
In addition you could make the internal function (real_work) be a
parameter of the for_each... which would reduce all of this to the more
general
List.iter any_function_I_want (permute 3 lst)
Finally, you might want to consider using lazy evaluation in your
permute function to avoid calculating every permutation up front. See
http://caml.inria.fr/pub/docs/manual-ocaml/libref/Lazy.html for more on
that.
-David
Tato Thetza wrote:
> Hi caml-list
> Given a list, I would like to iterate over all triplets in the list. For
> example, in mathematcs, its not uncommon to have expressions such as
> "for all i,j,k in set X, do f(i,j,k)"
>
> The only way I can think of is to create a list with all triplets of the
> list, so:
> triplets([1,2,3,4]) = [(1,2,3),(1,2,4),(1,3,4),(2,3,4)]
> and take this list and map a function f to it.
>
> questions:
> 1) what would be the best way to write triplets?
> 2) is there a cleaner way to iterate over all triplets in a list?
>
> please excuse my english
> Tato T.
>
> _______________________________________________
> Caml-list mailing list. Subscription management:
> http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
> Archives: http://caml.inria.fr
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs
>
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Caml-list] recursion/iterator question
2006-04-16 21:11 recursion/iterator question Tato Thetza
2006-04-16 22:00 ` [Caml-list] " David Powers
@ 2006-04-16 22:27 ` Martin Jambon
2006-04-17 0:06 ` Jon Harrop
` (2 subsequent siblings)
4 siblings, 0 replies; 13+ messages in thread
From: Martin Jambon @ 2006-04-16 22:27 UTC (permalink / raw)
To: Tato Thetza; +Cc: caml-list
On Sun, 16 Apr 2006, Tato Thetza wrote:
> Hi caml-list
> Given a list, I would like to iterate over all triplets in the list. For
> example, in mathematcs, its not uncommon to have expressions such as
> "for all i,j,k in set X, do f(i,j,k)"
>
> The only way I can think of is to create a list with all triplets of the
> list, so:
> triplets([1,2,3,4]) = [(1,2,3),(1,2,4),(1,3,4),(2,3,4)]
> and take this list and map a function f to it.
>
> questions:
> 1) what would be the best way to write triplets?
You can use list comprehensions.
See http://oandrieu.nerim.net/ocaml/#pa_compr
let triplets l = [+ (x, y, z)
| x <- l
| y <- l
| z <- l
| when x < y && y < z ];;
That's not optimal, but it's pretty clear.
> 2) is there a cleaner way to iterate over all triplets in a list?
You can do that, it should perform better:
let rec iter_full f = function
[] -> ()
| x :: l -> f x l; iter_full f l
let iter_tail iter f l = iter_full (fun x l -> iter (f x) l) l
let iter_full3 f l = iter_tail (iter_tail iter_full) f l
let iter3 f l = iter_full3 (fun x y z _ -> f x y z) l
Martin
--
Martin Jambon, PhD
http://martin.jambon.free.fr
Edit http://wikiomics.org, bioinformatics wiki
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Caml-list] recursion/iterator question
2006-04-16 21:11 recursion/iterator question Tato Thetza
2006-04-16 22:00 ` [Caml-list] " David Powers
2006-04-16 22:27 ` Martin Jambon
@ 2006-04-17 0:06 ` Jon Harrop
2006-04-17 9:36 ` Christian Stork
2006-04-17 6:50 ` Li-Thiao-Té Sébastien
2006-04-17 13:09 ` Xavier Leroy
4 siblings, 1 reply; 13+ messages in thread
From: Jon Harrop @ 2006-04-17 0:06 UTC (permalink / raw)
To: caml-list
On Sunday 16 April 2006 22:11, Tato Thetza wrote:
> Hi caml-list
> Given a list, I would like to iterate over all triplets in the list. For
> example, in mathematcs, its not uncommon to have expressions such as
> "for all i,j,k in set X, do f(i,j,k)"
>
> The only way I can think of is to create a list with all triplets of the
> list, so:
> triplets([1,2,3,4]) = [(1,2,3),(1,2,4),(1,3,4),(2,3,4)]
> and take this list and map a function f to it.
>
> questions:
> 1) what would be the best way to write triplets?
As 3-tuples, as you have done.
> 2) is there a cleaner way to iterate over all triplets in a list?
I think you mean _tabulate_ all triplets _from_ a list. You can write a
function to tabulate all pairs like this:
# let rec f2 = function
[] -> []
| a::t -> List.map (fun b -> a, b) t @ f2 t;;
val f2 : 'a list -> ('a * 'a) list = <fun>
and then another to tabulate all triplets like this:
# let rec f3 = function
[] -> []
| a::t -> List.map (fun (b, c) -> a, b, c) (f2 t) @ f3 t;;
val f3 : 'a list -> ('a * 'a * 'a) list = <fun>
On the example you gave:
# f3 [1;2;3;4];;
- : (int * int * int) list = [(1, 2, 3); (1, 2, 4); (1, 3, 4); (2, 3, 4)]
--
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
Objective CAML for Scientists
http://www.ffconsultancy.com/products/ocaml_for_scientists
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Caml-list] recursion/iterator question
2006-04-17 0:06 ` Jon Harrop
@ 2006-04-17 9:36 ` Christian Stork
2006-04-17 17:07 ` Jon Harrop
2006-04-20 11:53 ` Damien Doligez
0 siblings, 2 replies; 13+ messages in thread
From: Christian Stork @ 2006-04-17 9:36 UTC (permalink / raw)
To: caml-list
On Mon, Apr 17, 2006 at 01:06:22AM +0100, Jon Harrop wrote:
> On Sunday 16 April 2006 22:11, Tato Thetza wrote:
> > Hi caml-list
> > Given a list, I would like to iterate over all triplets in the list. For
> > example, in mathematcs, its not uncommon to have expressions such as
> > "for all i,j,k in set X, do f(i,j,k)"
Just in case you didn't know, you're looking for an enumeration of all
"3-sets" or "combinations" out of the set X. See for example
http://mathworld.wolfram.com/Combination.html .
> > The only way I can think of is to create a list with all triplets of the
> > list, so:
> > triplets([1,2,3,4]) = [(1,2,3),(1,2,4),(1,3,4),(2,3,4)]
> > and take this list and map a function f to it.
> > questions:
> > 1) what would be the best way to write triplets?
> As 3-tuples, as you have done.
Or, if you choose to represent triplets as lists of three elements, you can
generalize Jon's solution to
let rec combs = function
| (0, _) -> [[]]
| (n, es) when n > List.length es -> []
| (n, e::es) -> List.map (fun l -> e::l) (combs (n-1, es)) @ combs (n, es)
let triplets es = combs (3, es)
Question to the rest of the list: The ocaml compiler complains with
...
Warning P: this pattern-matching is not exhaustive.
Here is an example of a value that is not matched:
(1, [])
(However, some guarded clause may match this value.)
...
Am I right to assume there's no way to get rid of this warning short of
disabling P-warnings on the command line? (I can't list all the lacking
patterns since they depend on n, right?)
--
Chris Stork <> Support eff.org! <> http://www.ics.uci.edu/~cstork/
OpenPGP fingerprint: B08B 602C C806 C492 D069 021E 41F3 8C8D 50F9 CA2F
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Caml-list] recursion/iterator question
2006-04-17 9:36 ` Christian Stork
@ 2006-04-17 17:07 ` Jon Harrop
2006-04-18 3:25 ` Jonathan Roewen
2006-04-18 8:58 ` Christian Stork
2006-04-20 11:53 ` Damien Doligez
1 sibling, 2 replies; 13+ messages in thread
From: Jon Harrop @ 2006-04-17 17:07 UTC (permalink / raw)
To: caml-list
On Monday 17 April 2006 10:36, Christian Stork wrote:
> Or, if you choose to represent triplets as lists of three elements, you can
> generalize Jon's solution to
>
> let rec combs = function
>
> | (0, _) -> [[]]
> | (n, es) when n > List.length es -> []
> | (n, e::es) -> List.map (fun l -> e::l) (combs (n-1, es)) @ combs
> | (n, es)
>
> let triplets es = combs (3, es)
>
> Question to the rest of the list: The ocaml compiler complains with
> ...
> Warning P: this pattern-matching is not exhaustive.
> Here is an example of a value that is not matched:
> (1, [])
> (However, some guarded clause may match this value.)
> ...
>
> Am I right to assume there's no way to get rid of this warning short of
> disabling P-warnings on the command line? (I can't list all the lacking
> patterns since they depend on n, right?)
The lacking patterns are covered by (_, []), so you probably want:
| 0, _ | _, [] -> [[]]
--
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
Objective CAML for Scientists
http://www.ffconsultancy.com/products/ocaml_for_scientists
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Caml-list] recursion/iterator question
2006-04-17 17:07 ` Jon Harrop
@ 2006-04-18 3:25 ` Jonathan Roewen
2006-04-18 8:58 ` Christian Stork
1 sibling, 0 replies; 13+ messages in thread
From: Jonathan Roewen @ 2006-04-18 3:25 UTC (permalink / raw)
To: Jon Harrop; +Cc: caml-list
> > let rec combs = function
> >
> > | (0, _) -> [[]]
> > | (n, es) when n > List.length es -> []
> > | (n, e::es) -> List.map (fun l -> e::l) (combs (n-1, es)) @ combs
> > | (n, es)
> >
> > let triplets es = combs (3, es)
> >
> > Question to the rest of the list: The ocaml compiler complains with
> > ...
> > Warning P: this pattern-matching is not exhaustive.
> > Here is an example of a value that is not matched:
> > (1, [])
> > (However, some guarded clause may match this value.)
Personally, if you know it can never be reached, then an assertion is
probably better.
| otherwise -> assert false (* I prefer using a name like otherwise
rather than _ for pure readability value *)
Jonathan
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Caml-list] recursion/iterator question
2006-04-17 17:07 ` Jon Harrop
2006-04-18 3:25 ` Jonathan Roewen
@ 2006-04-18 8:58 ` Christian Stork
2006-04-18 16:15 ` Christian Stork
1 sibling, 1 reply; 13+ messages in thread
From: Christian Stork @ 2006-04-18 8:58 UTC (permalink / raw)
To: Jon Harrop, caml-list
On Mon, Apr 17, 2006 at 06:07:47PM +0100, Jon Harrop wrote:
> On Monday 17 April 2006 10:36, Christian Stork wrote:
> > Or, if you choose to represent triplets as lists of three elements, you can
> > generalize Jon's solution to
> > let rec combs = function
> > | (0, _) -> [[]]
> > | (n, es) when n > List.length es -> []
> > | (n, e::es) -> List.map (fun l -> e::l) (combs (n-1, es)) @ combs
> > | (n, es)
> > let triplets es = combs (3, es)
> > Question to the rest of the list: The ocaml compiler complains with
> > ...
> > Warning P: this pattern-matching is not exhaustive.
> > Here is an example of a value that is not matched:
> > (1, [])
> > (However, some guarded clause may match this value.)
> > ...
> > Am I right to assume there's no way to get rid of this warning short of
> > disabling P-warnings on the command line? (I can't list all the lacking
> > patterns since they depend on n, right?)
> The lacking patterns are covered by (_, []), so you probably want:
> | 0, _ | _, [] -> [[]]
No, that would generate solutions shorter than the requested n elements.
What we want is something like
| 1, []
| 2, [] | 2, [_]
| 3, [] | 3, [_] | 3, [_;_]
...
| n, [] | n, [_] | n, [_;_] | ... | n, [_;...;_] (* n-1 times '_' *)
-> []
Anyway, I think it's better not to use pattern matching but to use a
simple if-then-else to circumvent the warning.
--
Chris Stork <> Support eff.org! <> http://www.ics.uci.edu/~cstork/
OpenPGP fingerprint: B08B 602C C806 C492 D069 021E 41F3 8C8D 50F9 CA2F
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Caml-list] recursion/iterator question
2006-04-18 8:58 ` Christian Stork
@ 2006-04-18 16:15 ` Christian Stork
0 siblings, 0 replies; 13+ messages in thread
From: Christian Stork @ 2006-04-18 16:15 UTC (permalink / raw)
To: Jon Harrop, caml-list
On Tue, Apr 18, 2006 at 01:58:25AM -0700, Christian Stork wrote:
> On Mon, Apr 17, 2006 at 06:07:47PM +0100, Jon Harrop wrote:
> > On Monday 17 April 2006 10:36, Christian Stork wrote:
> > > Or, if you choose to represent triplets as lists of three elements, you can
> > > generalize Jon's solution to
> > > let rec combs = function
> > > | (0, _) -> [[]]
> > > | (n, es) when n > List.length es -> []
> > > | (n, e::es) -> List.map (fun l -> e::l) (combs (n-1, es)) @ combs
> > > | (n, es)
> > > let triplets es = combs (3, es)
> > > Question to the rest of the list: The ocaml compiler complains with
> > > ...
> > > Warning P: this pattern-matching is not exhaustive.
> > > Here is an example of a value that is not matched:
> > > (1, [])
> > > (However, some guarded clause may match this value.)
> > > ...
> > > Am I right to assume there's no way to get rid of this warning short of
> > > disabling P-warnings on the command line? (I can't list all the lacking
> > > patterns since they depend on n, right?)
> > The lacking patterns are covered by (_, []), so you probably want:
> > | 0, _ | _, [] -> [[]]
Oh, I think you meant
| 0, _ -> [[]]
| _, [] -> []
and that does indeed work (tho it's less efficient).
--
Chris Stork <> Support eff.org! <> http://www.ics.uci.edu/~cstork/
OpenPGP fingerprint: B08B 602C C806 C492 D069 021E 41F3 8C8D 50F9 CA2F
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Caml-list] recursion/iterator question
2006-04-17 9:36 ` Christian Stork
2006-04-17 17:07 ` Jon Harrop
@ 2006-04-20 11:53 ` Damien Doligez
1 sibling, 0 replies; 13+ messages in thread
From: Damien Doligez @ 2006-04-20 11:53 UTC (permalink / raw)
To: caml-list
On 2006-04-17, at 11:36, Christian Stork wrote:
> Question to the rest of the list: The ocaml compiler complains with
> ...
> Warning P: this pattern-matching is not exhaustive.
> Here is an example of a value that is not matched:
> (1, [])
> (However, some guarded clause may match this value.)
> ...
>
> Am I right to assume there's no way to get rid of this warning
> short of
> disabling P-warnings on the command line? (I can't list all the
> lacking
> patterns since they depend on n, right?)
Since nobody has pointed out the obvious, I'll do it:
You can always disable this warning for a particular pattern-matching
by adding the following as the last clause:
| _ -> assert false
-- Damien
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Caml-list] recursion/iterator question
2006-04-16 21:11 recursion/iterator question Tato Thetza
` (2 preceding siblings ...)
2006-04-17 0:06 ` Jon Harrop
@ 2006-04-17 6:50 ` Li-Thiao-Té Sébastien
2006-04-17 11:26 ` Nils Gesbert
2006-04-17 13:09 ` Xavier Leroy
4 siblings, 1 reply; 13+ messages in thread
From: Li-Thiao-Té Sébastien @ 2006-04-17 6:50 UTC (permalink / raw)
To: Tato Thetza; +Cc: caml-list
Tato Thetza wrote:
> Given a list, I would like to iterate over all triplets in the list. For
> example, in mathematcs, its not uncommon to have expressions such as
> "for all i,j,k in set X, do f(i,j,k)"
>
> The only way I can think of is to create a list with all triplets of the
> list, so:
> triplets([1,2,3,4]) = [(1,2,3),(1,2,4),(1,3,4),(2,3,4)]
> and take this list and map a function f to it.
>
> questions:
> 1) what would be the best way to write triplets?
> 2) is there a cleaner way to iterate over all triplets in a list?
>
Hi,
I suggest turning the list into an array, then using for-loops instead
of trying to explicitly generate the list of all possible triplets. If
you need to accumulate the results, you can use a list ref. This amounts
to implementing a set using an array instead of a list; unfortunately it
is not functional :(
let iterate f l =
let t = Array.of_list l in
let n = Array.length t in
let results = ref [] in
for i = 0 to n-1 do
for j = 0 to n-1 do
for k = 0 to n-1 do
results := f (t.(i),t.(j),t.(k)) :: results
done done done
;;
--
Li-Thiao-Té Sébastien
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Caml-list] recursion/iterator question
2006-04-17 6:50 ` Li-Thiao-Té Sébastien
@ 2006-04-17 11:26 ` Nils Gesbert
0 siblings, 0 replies; 13+ messages in thread
From: Nils Gesbert @ 2006-04-17 11:26 UTC (permalink / raw)
To: caml-list
Li-Thiao-Té Sébastien <sayan@crans.org> a écrit :
» let iterate f l =
» let t = Array.of_list l in
» let n = Array.length t in
» let results = ref [] in
» for i = 0 to n-1 do
» for j = 0 to n-1 do
» for k = 0 to n-1 do
» results := f (t.(i),t.(j),t.(k)) :: results
» done done done
» ;;
Hi,
A functional version of this could be (assuming f is curryed, and without keeping results) :
let iter3 f l =
let rec it2 iter g = function
h::t -> iter (g h) l; it2 iter g t
| _ -> ()
in it2 (it2 List.iter) f l
But I think the goal was to iterate over triplets (a,b,c) with a < b < c, not over all triplets. If I am not mistaken, it suffices to replace the l on line 3 by t to get this behaviour.
--
Nils Gesbert
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Caml-list] recursion/iterator question
2006-04-16 21:11 recursion/iterator question Tato Thetza
` (3 preceding siblings ...)
2006-04-17 6:50 ` Li-Thiao-Té Sébastien
@ 2006-04-17 13:09 ` Xavier Leroy
4 siblings, 0 replies; 13+ messages in thread
From: Xavier Leroy @ 2006-04-17 13:09 UTC (permalink / raw)
To: Tato Thetza; +Cc: caml-list
> Given a list, I would like to iterate over all triplets in the list. For
> example, in mathematcs, its not uncommon to have expressions such as
> "for all i,j,k in set X, do f(i,j,k)"
>
> The only way I can think of is to create a list with all triplets of the
> list, so:
> triplets([1,2,3,4]) = [(1,2,3),(1,2,4),(1,3,4),(2,3,4)]
> and take this list and map a function f to it.
Folds are more general than maps and tend to compose better.
Consider:
let list_fold_right_3 f l1 l2 l3 =
List.fold_right
(fun x1 -> List.fold_right (fun x2 -> List.fold_right (f x1 x2) l3) l2)
l1
Examples:
# list_fold_right_3 (fun x y z a -> (x,y,z)::a) [1;2] [3;4] [5;6] [];;
- : (int * int * int) list =
[(1, 3, 5); (1, 3, 6); (1, 4, 5); (1, 4, 6); (2, 3, 5); (2, 3, 6); (2,
4, 5);
(2, 4, 6)]
# list_fold_right_3 (fun x y z a -> (x+y+z)::a) [1;2] [3;4] [5;6] [];;
- : int list = [9; 10; 10; 11; 10; 11; 11; 12]
# list_fold_right_3 (fun x y z a -> x*y*z + a) [1;2] [3;4] [5;6] 0;;
- : int = 231
But, yes, if you find yourself doing this often, it's a good idea to
use the syntax extension for list comprehensions.
- Xavier Leroy
^ permalink raw reply [flat|nested] 13+ messages in thread