REVISED: Friday, September 12, 2025
1. OCAML FIBONACCI SEQUENCE
(*
File: fibonacci_sequence.ml
Author: Ron Tinnel
Description: This script provides an interactive command-line interface
for calculating and displaying a user-defined segment of the Fibonacci sequence.
It demonstrates core OCaml concepts such as recursion, function definition,
pattern matching, exception handling, and I/O operations.
To run this script:
1. Make sure you have OCaml installed.
2. Save the code as `fibonacci_sequence.ml`.
3. Compile it using: `ocamlc -o fib_seq fibonacci_sequence.ml`
4. Execute the compiled program: `./fib_seq`
*)
(**
* == Objective 2: Fibonacci Method ==
* Computes the nth Fibonacci number.
*
* OCaml Usage Explained:
* `let rec fib n`: This defines a recursive function named `fib` that takes one
* argument, `n`. The `rec` keyword is essential for functions that call themselves.
* `match n with`: This is OCaml's powerful pattern matching construct. It checks
* the value of `n` against a series of patterns.
* `| 0 -> 0`: The first pattern. If `n` is 0, the function returns 0.
* `| 1 -> 1`: The second pattern. If `n` is 1, the function returns 1. These are
* the base cases for the recursion, which prevent an infinite loop.
* `| _ -> fib (n - 1) + fib (n - 2)`: The underscore `_` is a wildcard pattern
* that matches any other value. If `n` is not 0 or 1, the function calls
* itself with `n-1` and `n-2` and returns their sum. This is the recursive step.
*
* Note: This is a classic, simple implementation. For very large values of `n`,
* it becomes inefficient due to re-calculating the same Fibonacci numbers
* multiple times. A more optimized version would use memoization or an
* iterative approach.
*
* @param n The index in the Fibonacci sequence (integer, should be non-negative).
* @return The nth Fibonacci number.
*)
let rec fib n =
match n with
| 0 -> 0
| 1 -> 1
| _ -> fib (n - 1) + fib (n - 2)
(**
* == Objective 3: Printing the Sequence ==
* Iterates from a starting number to an ending number, printing the
* Fibonacci value for each index in the range.
*
* OCaml Usage Explained:
* `let print_fib_sequence start_num end_num =`: Defines a function that takes two arguments.
* `if start_num < 0 || end_num < 0 then ...`: A simple guard clause to handle invalid
* negative input, as the Fibonacci sequence is typically defined for non-negative integers.
* `else if start_num > end_num then ...`: Handles the case where the user mixes up
* the start and end numbers.
* `for i = start_num to end_num do ... done`: OCaml provides imperative-style
* constructs like `for` loops, which are very useful for simple iterations
* where a side-effect (like printing to the console) is the main goal.
* `let result = fib i in`: Calls our `fib` function for the current loop index `i`
* and binds the returned value to the name `result`.
* `print_endline (...)`: A standard library function that prints a string to the
* console, followed by a newline character.
* `string_of_int i`: Converts an integer `i` to its string representation.
* `^`: The string concatenation operator in OCaml.
*
* @param start_num The starting index for the sequence.
* @param end_num The ending index for the sequence.
*)
let print_fib_sequence start_num end_num =
if start_num < 0 || end_num < 0 then
print_endline "Error: Fibonacci numbers must be non-negative."
else if start_num > end_num then
print_endline "Error: The starting number cannot be greater than the ending number."
else
(* Loop from the start to the end number, inclusive *)
for i = start_num to end_num do
let result = fib i in
(* Print the result in a formatted string *)
print_endline ("Fib(" ^ (string_of_int i) ^ ") = " ^ (string_of_int result))
done
(**
* == Objective 1: Recursive Main Loop ==
* This function creates a persistent loop that prompts the user for input,
* processes it, and then calls itself to repeat the process.
*
* OCaml Usage Explained:
* `let rec main_loop () =`: Defines a recursive function that takes `()` (pronounced "unit")
* as its argument. Unit is used for functions that don't need a meaningful input,
* often because they deal with side-effects like I/O.
* `print_string "> ";`: Prints a prompt without a newline.
* `flush stdout;`: This is important in interactive programs. It forces the program
* to immediately print any text that is buffered. Without it, the "> " prompt
* might not appear until after the user has already entered their input.
* `let input = read_line () in`: Reads a line of text from the user's input
* and binds it to the name `input`.
* `match input with | "exit" -> ...`: We use pattern matching again. If the user
* types exactly "exit", we print a goodbye message and the function simply returns,
* ending the chain of recursive calls and thus exiting the program.
* `| _ -> ...`: If the input is anything other than "exit", we proceed.
* `try ... with ...`: This is OCaml's exception handling mechanism. We `try` to
* execute a block of code that might fail (like converting a non-number string to an integer).
* If an exception occurs, the `with` block catches it.
* `Scanf.sscanf input "%d %d" print_fib_sequence`: This is a powerful function from the
* `Scanf` module. It scans the `input` string, looks for a pattern of two integers
* ("%d %d"), and if it finds them, it passes them as arguments to the `print_fib_sequence`
* function. It's a very clean way to parse formatted input.
* `with _ -> ...`: If `Scanf.sscanf` fails (e.g., the user typed "hello world"), it
* raises an exception. We catch it with a wildcard `_` and print a helpful error message.
* `main_loop ()`: The crucial final line. After handling the input (either successfully or
* by catching an error), the function calls itself to start the loop over again.
* This is how recursion is used to create loops in functional programming.
*)
let rec main_loop () =
print_string "Enter a start and end number (e.g., '5 10') or type 'exit': ";
flush stdout; (* Ensure the prompt is displayed before waiting for input *)
let input = read_line () in
match input with
| "exit" ->
(* Base case for the recursion: user wants to exit, so we don't recurse. *)
print_endline "Goodbye!"
| _ ->
(* Recursive step: process input, then call main_loop again. *)
(try
(* Attempt to parse two integers from the user's input string. *)
(* If successful, call print_fib_sequence with the parsed numbers. *)
Scanf.sscanf input "%d %d" print_fib_sequence
with
(* If Scanf.sscanf fails, it raises an exception. We catch it here. *)
| _ -> print_endline "\nInvalid input. Please enter two integers separated by a space.\n");
main_loop () (* The recursive call that continues the loop *)
(*
* The entry point of the script.
* OCaml scripts execute code at the top level from top to bottom.
* This is the first code that will actually run.
*)
let () =
print_endline "--- OCaml Fibonacci Sequence Generator ---";
main_loop ()
2. CONCLUSION
This script provides an interactive command-line interface for calculating and displaying a user-defined segment of the Fibonacci sequence. It demonstrates core OCaml concepts such as recursion, function definition, pattern matching, exception handling, and I/O operations.
3. REFERENCES
Bird, R. (2015). Thinking Functionally with Haskell. Cambridge, England: Cambridge University Press.
Davie, A. (1992). Introduction to Functional Programming Systems Using Haskell. Cambridge, England: Cambridge University Press.
Goerzen, J. & O'Sullivan, B. & Stewart, D. (2008). Real World Haskell. Sebastopol, CA: O'Reilly Media, Inc.
Hutton, G. (2007). Programming in Haskell. New York: Cambridge University Press.
Lipovača, M. (2011). Learn You a Haskell for Great Good!: A Beginner's Guide. San Francisco, CA: No Starch Press, Inc.
Pierce, Benjamin C., et al., editors. Logical Foundations. Vol. 1 of Software Foundations. Electronic Textbook, 2024. Version 6.7, http://softwarefoundations.cis.upenn.edu.
Thompson, S. (2011). The Craft of Functional Programming. Edinburgh Gate, Harlow, England: Pearson Education Limited.