8

I'm learning f# and I've got a pretty trivial problem that doesn't seem to make sense. I'm working on Project Euler problem 2 and I've got this:

let fib (x : BigInteger) (y : BigInteger) (max : BigInteger) = 
    let added = x + y
    if added > max then y
    else fib y (x + y) max

I've got the error at the recursive fib call:

Value or constructor 'fib' is not defined

And I'm not sure why. Any help?

Zero Piraeus
  • 56,143
  • 27
  • 150
  • 160
Steven Evers
  • 16,649
  • 19
  • 79
  • 126
  • System.Int32.MaxValue >> 4000000, and "even-valued terms" – BLUEPIXY Mar 10 '12 at 11:49
  • @BLUEPIXY: Yea, I know it's not a correct or efficient solution to the problem at the moment. It's an iterative attempt. I'm just trying to fully get all of the syntax. – Steven Evers Mar 10 '12 at 16:45

3 Answers3

14

Because fib is recursive function, it has to start with let rec.

pad
  • 41,040
  • 7
  • 92
  • 166
7

In F#, if you want to write a recursive function, you have to use the rec keyword:

let rec fib (x : BigInteger) (y : BigInteger) (max : BigInteger) = 
    let added = x + y
    if added > max then y
    else fib y (x + y) max

That's because in F# under normal circumstances, you can only use identifiers declared before the current code, unlike in C#.

svick
  • 236,525
  • 50
  • 385
  • 514
3

Talking of Project Euler Problem 2, you may consider instead of recursion going with Seq.unfold, which is very idiomatic and gives you all Fibonacci numbers at once:

let fibs = Seq.unfold (fun (current, next) ->
    Some(current, (next, current + next))) (1,2)

Now fibs represents lazy sequence of Fibonacci numbers :

>fibs;;
val it : seq<int> = seq[1; 2; 3; 5; ...]

And to make it of BigInteger just substitute (1,2) by (1I,2I), although the solution allows you to stay within ordinary integers.

Gene Belitski
  • 10,270
  • 1
  • 34
  • 54
  • Even more idiomatic would be let fibs = (1,2) |> Seq.unfold (fun (current, next) -> Some(current, (next, current + next))) – Onorio Catenacci Mar 10 '12 at 06:32
  • Interesting. I have just started reading about foldl/foldr but am still having trouble fully grasping their applications. I'll give this a shot. Thanks. – Steven Evers Mar 10 '12 at 16:34
  • @SnOrfus: To see how this piece fits into the full solution context you may want to peek [here](http://infsharpmajor.wordpress.com/2011/09/28/project-euler-problem-2/) – Gene Belitski Mar 10 '12 at 17:18
  • @GeneBelitski: Thanks. I will look at that once I write a working solution myself first :) I generally solve it on my own first, and then look for/at better solutions. I find I can really grasp it better that way. – Steven Evers Mar 10 '12 at 19:27
  • fold and unfold are shortcuts for recursion with accumulators, I think that for learning is better to not use them, and do it manually instead – Omu Apr 28 '12 at 14:23