If you explicitly make fibFaster a function by providing it with an argument, then you won't get this message (as the warning itself suggests):

1
let rec fibFaster i = memoize (fun n -> if n > 2 then fibFaster (n - 1) + fibFaster (n - 2) else n) i

With a function, the right hand side of the definition isn’t immediately evaluated, so recursive references don’t present a problem. However, with values, if the right hand side refers to the left hand side, the definition itself might be unsafe. For instance, if you had written:

1
2
let rec fibFaster2 =
  memoize fibFaster2

When F# tries to evaluate what it should assign to fibFaster2, the expression on the right refers to fibFaster2 itself. What should be passed to memoize when trying to evaluate this expression?

In your case, your use of fibFaster is safely hidden inside a function which won't be evaluated immediately, so the warning is overly conservative. In these cases you can either ignore the warning, or define fibFaster as a "syntactic function" by giving it an argument as I've done above.

By on 6/10/2009 2:08 PM ()

Hmm... that doesn't quite work.

With fibFaster converted to a function, memoize() gets evalutaed each time -- which causes a new Dictionary to be generated each iteration.

The idea is that fibFaster is evaluated only once, and only the function that it returns is evaluated per iteration. That way you can use the values precomputed in previous iterations.

Which seems to work with the code in the book (which is the code I pasted) -- except I get that warning message.

I guess I'll just have to turn off the warning and live with it for now :)

Thanks again,

Rei

By on 6/10/2009 7:12 PM ()

If you want to get rid of the warning you could always do something like this for recursive functions:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
open System.Collections.Generic

let memo_rec f =

   let cache = Dictionary≺_,_> ()

   let rec g x =

      let ok, res = cache.TryGetValue x

      if ok then res

      else let res = f g x

           cache.[x] ≺- res

           res

   g

let fib = memo_rec ≺| fun fib n -> if n ≺ 2 then n else fib (n-1) + fib (n-2)

{0..20} |> Seq.iter (fib >> printfn "%d")

BTW: How do you write less-thans in code in this forum? I had to use the "precedes" symbol instead.

By on 6/11/2009 10:51 AM ()

Oy that seems to work but it's totally confusing for my imperative-wired brain.

Looks like I should review the let keyword even more...

Thanks!

By on 6/11/2009 5:38 PM ()

Hah, of course you're right. Sorry for not catching that...

By on 6/10/2009 8:39 PM ()
IntelliFactory Offices Copyright (c) 2011-2012 IntelliFactory. All rights reserved.
Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy
Built with WebSharper