Re: Sys.time( ) and Unix.gettimeofday( ) ;;
"Douglas Lewit [email protected] [ocaml_beginners]" <[email protected]> Mon, 7 Mar 2016 11:40:58 -0600
| Newsgroups | gmane.comp.lang.ocaml.beginners |
|---|---|
| Message-ID | <CAM0XMJRLkznFnpT6xv8fp3P6gJZjQudzL0ae+Caf9NyRa0ygTw@mail.gmail.com> |
Hi Gabriel,
I may have figured it out, although utop/Ocaml is responding with *Warning
26: unused variable myList*
Here's what I did:
I want to find the "infinite" sum of the sequence { a[n] } = { 1/ ( n *
sqrt n ) }
So here's what I did: ( assuming that these functions are loaded in
memory )
*let calculusList = sequence 1. 40e3 1. (* Because I want 40,000 terms in
my sequence or my list. *)*
*let calculusList = List.map ( fun x -> 1. /. ( x *. sqrt x ) )
calculusList ;;*
*utop** # **let** timeIt1 **=* *let** beginning **=* *Unix**.**gettimeofday*
*(* *)* *in*
*let** myList **=** partialsums calculusList **in*
*let** ending **=* *Unix**.**gettimeofday**(* *)* *in*
*ending **-.** beginning **;;*
*Characters 59-65:
Warning 26: unused variable myList.
**val**
timeIt1 **:** float **=* *0.00942301750183105469*
*utop** # **let** timeIt2 **=* *let** beginning **=* *Unix**.**gettimeofday*
*(* *)* *in*
*let** myList **=** partialSums calculusList **in*
*let** ending **=* *Unix**.**gettimeofday**(* *)* *in*
*ending **-.** beginning **;;*
*Characters 59-65:
Warning 26: unused variable myList.
**val**
timeIt2 **:** float **=* *118.222778081893921*
I think my original issue was that I had the "ending" variable immediately
after the "beginning" variable, so of course the elapsed time was going to
be negligible. My mistake!
But this leads to some really interesting questions.
First off, EXACTLY WHAT IS TAIL RECURSION. I'm assuming that any recursive
function that uses an "accumulator" is tail-recursive, but that seems like
a pretty poor definition of tail-recursion. So exactly what is the key
difference between normal recursion ( or forward recursion ) and
tail-recursion? Is it true that tail-recursion is always faster and more
efficient than forward recursion? Are there any notable exceptions to that
rule?
Also, how on earth do I tell Ocaml to ignore Warning 26? I mean.... I know
I don't need the "myList" variable per se, but I had to create it for the
sake of scoping, right? So how can I tell the interpreter/compiler "Hey,
it's okay. I'm just creating a dummy variable and I plan to just throw it
away. I'm not going to really use it". What would happen if I used
ocamlopt or ocamlc on such a function? Would it compile? Would I still
see the error message? Would the program execute in spite of that error
message?
It's also really interesting to notice that my less efficient function
required almost 2 minutes to execute, but the function that used the
accumulator ran in far less than a second! Wow! That's pretty amazing to
me.
This last question may seem a little dumb, but here it goes. Why do
functional programmers have this prejudice against for, do-while, while
loops, and other looping structures? I'm not sure I really understand
that. ( But I will admit that it's extremely interesting to see just how
much can really be done with recursive functions. )
Thanks for the feedback.
Best,
Douglas Lewit
On Mon, Mar 7, 2016 at 11:17 AM, Gabriel Scherer [email protected]
[ocaml_beginners] <[email protected]> wrote:
>
>
> You should also show us the code that does the actual calls to your timing
> functions. It's possible that you may have assumed too much of evaluation
> order, for example, and that these calls are made at a time you do not
> expect.
>
> On Mon, Mar 7, 2016 at 12:15 PM, Douglas Lewit [email protected]
> [ocaml_beginners] <[email protected]> wrote:
>
>>
>>
>> Hi everyone,
>>
>> I wrote two different functions to generate a list of partial sums if
>> given a list of floats.
>>
>> Here are my functions:
>>
>> *(* Recursively compute the partial sums of a list of floats. Not
>> tail-recursive and might be too slow for very long lists. *)*
>>
>> *let partialSums lst = let rec take n l = match n with *
>>
>> *|0 -> [ ]*
>>
>> *|_ -> match l with*
>>
>> *|[ ] -> [ ]*
>>
>> *|head :: tail -> head :: ( take ( n - 1 ) tail ) in *
>>
>> *let rec sum l = match l with *
>>
>> *|[ ] -> 0.*
>>
>> *|head :: tail -> head +. sum tail in *
>>
>> *let rec pSum l k m = if k > m then [ ] else sum ( take k lst ) :: ( pSum
>> l ( k + 1 ) m ) in *
>>
>> *pSum lst 1 ( List.length lst ) ;;*
>>
>>
>> *(* Recursively compute the partial sums of a list of floats.
>> Tail-recursive and therefore more efficient and faster than *
>>
>> *the preceding function. *)*
>>
>> *let partialsums lst = let rec psums l accumulator = match l with *
>>
>> *|[ ] -> [ ]*
>>
>> *|head :: tail -> ( head +. accumulator ) :: begin psums tail ( head +.
>> accumulator ) end in *
>>
>> *psums lst 0. ;;*
>>
>>
>> *(* Recursively generate a sequence of floats. *)*
>>
>> *let rec sequence lower upper step = if lower > upper then [ ] else lower
>> :: ( sequence ( lower +. step ) upper step ) ;;*
>>
>>
>> The functions work just fine, but I'm having trouble using *Sys.time( )*
>> and *Unix.gettimeofday( )* in the utop environment. They are not
>> returning any error messages, but the values seem very unreliable. For
>> *partialSums* for example, the answer should be at least 60 seconds ( if
>> not more ) and what I'm getting back as an answer is something like
>> 0.000001 seconds, which makes more sense for *partialsums*, which is by
>> far the more efficient of the two functions. Any suggestions? Thank you!
>>
>>
>> Best,
>>
>>
>> Douglas Lewit
>>
>>
>>
>>
>>
>
>