caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: Mark Seaborn <mrs35@cam.ac.uk>
To: caml-list@inria.fr
Subject: Re: [Caml-list] two unrelated questions
Date: 26 Apr 2001 17:57:04 +0100	[thread overview]
Message-ID: <873davha5b.fsf@argbg34.argonet.co.uk> (raw)
In-Reply-To: Chris Hecker's message of "Wed, 25 Apr 2001 14:08:33 -0700"

Chris Hecker <checker@d6.com> writes:

> 1.  What is the right "functional pattern" for early-outing on success
>     while using an iter/map/fold type function?  Say I'm using iter to
>     search for something in an opaque datastructure.  Should I throw
>     an exception to get out, or is that bad style?  I guess this
>     question only makes sense for iter, since map/fold produce results
>     that you theoretically want to preserve.  So, the question is
>     really, given an iter-style interface to a datastructure (one that
>     takes an ('a -> unit)), how do you tell it to stop iterating?  I
>     guess if the function was ('a -> bool) you could do it that way,
>     but most iters aren't ((List|Array|Hashtbl).iter, for example).
>     Is throwing an exception the best bet?

Wrapping up the exception-throwing method with a function that
provides an escaping continuation function is something you might
prefer stylistically.

Another way of doing it is to CPS-convert the fold function to get
something like:

let rec foldc kons knil l = match l with
  | [] -> knil
  | x::xs -> kons x knil (fun rest -> foldc kons rest xs)

Then `reverse' and `map' can be defined by:

let reverse l = foldc (fun x xs c -> c (x::xs)) [] l
let map f l = foldc (fun x xs c -> (f x)::(c xs)) [] l

(Notice that `foldc' can be used to traverse the list from
right-to-left as well as left-to-right by calling the continuation
function at a different time.)

A function to return the first value satisfying a predicate in a list
and break out of the fold operation can be defined by:

let first_such pred l =
  foldc (fun x _ c -> if pred x then Some x else c None)
    None l

This is more powerful than fold, but also harder to understand, and
easier to use wrongly if you forget to call the continuation function.

Also, if you re-order the arguments of foldc and pass it a return
continuation you get something you can use to thread multiple values
through (which is possibly more efficient in OCaml?), instead of just
using one collector value (and putting a tuple in it):

let rec foldc' kons l c knil = match l with
  | [] -> c knil
  | x::xs -> kons x (fun rest -> foldc' kons xs c rest) knil

for example:
  foldc' (fun x c l1 l2 -> c (x::l1) (x::l2))
    [1;2;3;4] (fun a b -> (a,b)) [] []
gives
  ([4;3;2;1], [4;3;2;1])

You can use this to stop a fold operation and restart it later, and
for building lazy lists out of any collection that provides a `foldc'
operation.  However, it starts to get difficult to understand the
order of evaluation, so I'm not sure whether this is very useful in
practice (it probably gets to the point where you may as well use a
lazy language instead) or whether it's just a handy way of obfuscating
your programs.

-- 
         Mark Seaborn
   - mseaborn@bigfoot.com - http://www.srcf.ucam.org/~mrs35/ -

          ``Anyone foolish enough to predict the outcome of
               this match is a fool'' -- Fred Trueman
-------------------
To unsubscribe, mail caml-list-request@inria.fr.  Archives: http://caml.inria.fr


  parent reply	other threads:[~2001-04-26 16:53 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2001-04-25 21:08 Chris Hecker
2001-04-26  0:38 ` Patrick M Doane
2001-04-26  6:04   ` Judicaël Courant
2001-04-26 12:06     ` John Max Skaller
2001-04-27  9:12       ` Anton Moscal
2001-04-29 22:24         ` Brian Rogoff
2001-04-30 18:57           ` Fergus Henderson
2001-05-01  1:31           ` Jacques Garrigue
2001-05-01 12:45             ` [Caml-list] " Ken Friis Larsen
2001-04-27 15:09       ` [Caml-list] " Brian Rogoff
2001-04-27 17:49         ` John Max Skaller
2001-04-26  8:22   ` Andreas Rossberg
2001-04-26  1:13 ` Jacques Garrigue
2001-04-26 13:47 ` Xavier Leroy
2001-04-26 22:34   ` Chris Hecker
2001-04-26 16:57 ` Mark Seaborn [this message]
2001-04-26 22:20   ` John Max Skaller
2001-05-01 21:08     ` Brian Rogoff
2001-05-01 23:30       ` John Max Skaller
2001-05-02  0:03       ` John Max Skaller
2001-05-01 17:25 Dave Berry

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=873davha5b.fsf@argbg34.argonet.co.uk \
    --to=mrs35@cam.ac.uk \
    --cc=caml-list@inria.fr \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).