caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: skaller <skaller@users.sourceforge.net>
To: Julien Moutinho <julien.moutinho@gmail.com>
Cc: caml-list@yquem.inria.fr
Subject: Re: [Caml-list] Preferred Way to Split a List
Date: Tue, 30 Oct 2007 16:46:22 +1100	[thread overview]
Message-ID: <1193723182.6129.66.camel@rosella.wigram> (raw)
In-Reply-To: <20071030012012.GA29836@localhost>


On Tue, 2007-10-30 at 02:20 +0100, Julien Moutinho wrote:
> On Mon, Oct 29, 2007 at 06:33:11PM -0500, Robert Fischer wrote:
> > What is the preferred way to split a list into two, at an arbitrary point?  
> > There's lots of ways you could do it, but I'm not sure if there's a 
> > standard best practice for this.
> 
> Two answers for what they're worth:

Ouch. A simpler way is:

	let split ls n = let rec aux inp out n =
		if n = 0 then unsafe_rev_cat out inp
		else match inp with
		| [] -> unsafe_rev_cat out []
		| h :: t -> aux t (h::out) (n-1)
	in aux ls [] n

Here 'unsafe_rev_cat' uses magic to reverse a list in place
and tack the tail onto the end. 

However this isn't the fastest way. The fastest way is:

	let split ls n = 
		let out = magic_list() in
		let rec aux inp n =
			if n = 0 then magic_cat out inp
			else match inp with
			| [] -> ()
			| h :: t -> magic_append h out; aux t (n-1)
	in 
		aux ls n;
		list_of out

Here the magic list is the usual list data structure PLUS a pointer
to the last element allowing O(1) append. This is of course a mutable
data structure. All the operations here can be implemented without
Obj.magic, however it's much faster WITH Obj.magic: by using a 
magic list structure identical to an actual list, the 'list_of'
function becomes a typecast.

A similar code uses a reversed ordinary list for the temporary,
and then reverses it inplace (safe because it is a temporary)
and tacks the tail on. Felix uses that algorithm in its standard
library, however the one actually coded above is optimal (it isn't
possible to do it any faster).

Note the function above is purely functional (mutations are
isolated to the implementation) and does not itself use any
unsafe features (but the magic implementation is unsafe,
so it should be put in a library to limit bugs and 
implementation dependencies).

-- 
John Skaller <skaller at users dot sf dot net>
Felix, successor to C++: http://felix.sf.net


  parent reply	other threads:[~2007-10-30  5:47 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-10-29 23:33 Robert Fischer
2007-10-30  0:45 ` [Caml-list] " Matthew William Cox
2007-10-30 13:18   ` Robert Fischer
2007-11-03  3:06     ` Nathaniel Gray
2007-10-30  1:20 ` Julien Moutinho
2007-10-30  1:38   ` Karl Zilles
2007-10-30  5:46   ` skaller [this message]
2007-10-30  7:58     ` Alain Frisch
2007-10-29  9:34       ` Christophe Raffalli
2007-10-30 11:31         ` skaller
2007-10-30 12:30         ` David Allsopp
2007-10-30 15:03           ` Christophe Raffalli
2007-10-30 11:15       ` skaller
2007-10-30 13:05         ` Brian Hurt
2007-10-30  7:50 ` Jon Harrop
2007-10-30 13:20   ` Robert Fischer

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=1193723182.6129.66.camel@rosella.wigram \
    --to=skaller@users.sourceforge.net \
    --cc=caml-list@yquem.inria.fr \
    --cc=julien.moutinho@gmail.com \
    /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).