<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE message PUBLIC
  "-//MLarc//DTD MLarc output files//EN"
  "../../mlarc.dtd"[
  <!ATTLIST message
    listname CDATA #REQUIRED
    title CDATA #REQUIRED
  >
]>

  <?xml-stylesheet href="../../mlarc.xsl" type="text/xsl"?>


<message 
  url="2003/01/ca1dffd1660ca65a4b05e25358542cd4"
  from="Diego Olivier Fernandez Pons &lt;Diego-Olivier.FERNANDEZ-PONS@c...&gt;"
  author="Diego Olivier Fernandez Pons"
  date="2003-01-31T17:33:52"
  subject="Re: [Caml-list] @, List.append, and tail recursion"
  prev="2003/01/1c9ca4f143a0ace6056cb77ebfb173e0"
  next="2003/01/43d4021b732340168a7aa2d608ef4e32"
  prev-thread="2003/01/5ef42def11e5adc1e52c1ccc74ec1d0b"
  next-thread="2003/01/335005727844e8eb6d467d43be0988a3"
  root="../../"
  period="month"
  listname="caml-list"
  title="Archives of the Caml mailing list">

<thread subject="Re: [Caml-list] @, List.append, and tail recursion">
<msg 
  url="2003/01/ca1dffd1660ca65a4b05e25358542cd4"
  from="Diego Olivier Fernandez Pons &lt;Diego-Olivier.FERNANDEZ-PONS@c...&gt;"
  author="Diego Olivier Fernandez Pons"
  date="2003-01-31T17:33:52"
  subject="Re: [Caml-list] @, List.append, and tail recursion">
</msg>
</thread>

<contents>
    Bonjour,

Brian Hurt wrote :

&gt; Here's an example I have run across.  I'm working with sparse vectors, and
&gt; basically storing them as (int * float) lists.  Now, let's write the
&gt; vector add function.  The naive implementation would be:

let rec add_rec result = fun a b -&gt;
  match (a, b) with
    | ([], _) -&gt; a @ result
    | (_, []) -&gt; b @ result
    | ((n, x) :: a_tail, (m, y) :: b_tail) -&gt;
       match compare m n with
         | k when k &lt; 0 -&gt; add_rec ((n, x) :: result) a_tail b
         | k when k &gt; 0 -&gt; add_rec ((m, y) :: result) a b_tail
         | _ -&gt; add_rec ((n, x +. y) :: result) a_tail b_tail


This is a tail recursive version of your function. The main problem is
that it reverses the list every time it is called.

Your first idea is to define

let add = fun a b -&gt; List.rev (add_rec a b)

and you are right when you say that you are allocating a lot of
memory. But you can do much better : add_rec only needs the two lists
to be sorted, not to be increasing.

Why don't you try

type vector =
  | Increasing of (int * float) list
  | Decreasing of (int * float) list

then you just have to write the 4 corresponding add functions

Here is a second idea : is there a way to implement add in such a way
that it does not need the two arguments to be sorted ? If you were
working with arrays this would not be difficult.

Then, just try functional random acces lists. They give you a O(1)
access to the head element (in case both list are sorted in the same
way) or O(log n) acces to any element.


        Diego Olivier


-------------------
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

</contents>

</message>

