Showing posts with label F#. Show all posts
Showing posts with label F#. Show all posts

Thursday, March 6, 2014

Arrays and Indexers in F#



Today's post is about Arrays and Indexers in F#. Here below you will find a very easy to follow program, that demonstrate arrays and indexer, by implementing some simple tasks that will make you grasp the idea of those 2 features real quick. The main goal of this post, is not really teaching arrays because, come on, you probably already know "all" about them, in fact, it is more to show you how you do that in F#, in this case, compared to all other 22 languages on future posts, which essentially, is the real aim behind this blog.

By the way, if you missed my most recent post, "New Series - Arrays and Indexers", check it out. It has more details about the following program, and a bunch of definitions for the concepts used on this, and the following, posts. Or you can check my previous posts about arrays in C# and C++ just to compare.

I encourage you to copy the code below and try it yourself, normally, all programs you find in this blog are source code complete, just paste it on your IDE and run it.

There is room for improvement of the code, using generics is one example, but Generics, Collections, lambdas, etc. will have their own "series" of posts.

WARNING! I know that F# is intended to be use in a Functional way, however, my goal is to show its Imperative and OO language features, so it can be compared with other OO languages. Said that, if you know how to do something on the examples below on a Functional way, you are welcome to add them as a comment :)


open System
open System.Text

module FsArrays =
    type Alphabet public (size: int) as this = class    
        // Array Field 
        [<DefaultValue>]
        val mutable private letters: char array 
        do this.letters <- Array.create size ' '
        // Indexer Get/Set Property  
        member public this.Item
            with get(index) = 
                this.letters.[index]
            and set index value = 
                this.letters.[index] <- value.ToString().ToUpper().[0]
        // Read-only Property
        member public this.Length
            with get() = this.letters.Length
        // Constructors  
        new() = new Alphabet(0)
        new(l: string) as this = new Alphabet(l.Length) then 
            this.letters <- l.ToUpper().ToCharArray()
        new(l: char[]) as this = new Alphabet(0) then 
            this.letters <- l
        // Overridden Method  
        override this.ToString() = 
            String.Join(",", [|for c in this.letters -> c.ToString()|])
        // Method
        member public this.Slice(start: int, length: int): char[] = 
            this.letters.[start .. start + length - 1]
    end

    let ReverseChar (arr: char array) : char array = 
        Array.rev arr

    let BubbleSortInt (arr: int array) = 
        let mutable swap = 0
        for i in Array.rev(arr) do
            for j in 0 .. arr.Length - 2 do
                if arr.[j] > arr.[j + 1] then
                    swap <- arr.[j]   
                    arr.[j] <- arr.[j + 1] 
                    arr.[j + 1] <- swap  
        arr  

    let BubbleSortString (arr: string array) = 
        let mutable swap = ""
        for i in Array.rev(arr) do
            for j in 0 .. arr.Length - 2 do
                if arr.[j].[0] > arr.[j + 1].[0] then
                    swap <- arr.[j]   
                    arr.[j] <- arr.[j + 1] 
                    arr.[j + 1] <- swap  
        arr  

    let TransposeMatrix(m: int[,]): int[,] =
        (* Transposing a Matrix 2,3  
            *  
            * A =  [6  4 24]T [ 6  1]  
            *      [1 -9  8]  [ 4 -9] 
            *                 [24  8] 
        *)  
        let transposed = Array2D.zeroCreate<int> (m.GetLength 1) (m.GetLength 0)  
        for i in 0 .. m.GetLength 0 - 1 do
            for j in 0 .. m.GetLength 1 - 1 do
                transposed.[j, i] <- m.[i, j]         
        transposed;  
  
    let UpperCaseRandomArray (arr: string[][]) =         
        let r = new System.Random()
        let i = r.Next (arr.Length - 1)
        for j in 0 .. arr.[i].Length - 1 do 
            arr.[i].[j] <- arr.[i].[j].ToUpper()

    let PrintArrayChar (arr: char array) =
        printfn "\nPrint Array Content %s" 
            (arr.GetType().Name.Replace("]", arr.Length.ToString() + "]"))
        for i in 0 .. arr.Length - 1 do
            printfn " array [%2i] = %2c" i arr.[i] 

    let PrintArrayInt (arr: int array) =
        printfn "\nPrint Array Content %s" 
            (arr.GetType().Name.Replace("]", arr.Length.ToString() + "]"))
        for i in 0 .. arr.Length - 1 do
            printfn " array [%2i] = %2i" i arr.[i] 

    let PrintArrayString (arr: string array) =
        printfn "\nPrint Array Content %s" 
            (arr.GetType().Name.Replace("]", arr.Length.ToString() + "]"))
        for i in 0 .. arr.Length - 1 do
            printfn " array [%2i] = %2s" i arr.[i] 

    let PrintMatrix (m: int[,]) = 
        printfn "\nPrint Matrix Content %s[%i,%i]" 
            (m.GetType().Name.Replace("[,]", "")) (m.GetLength 0) (m.GetLength 1)
        for i in 0 .. m.GetLength 0 - 1 do
            for j in 0 .. m.GetLength 1 - 1 do
                printfn " array [%2i,%2i] = %2i " i j m.[i, j]  

    let GraphJaggedArray (arr: string[][]) =  
        (* When using Arrays, we can use foreach instead of for + index:  
        *  
        * for i in 0 .. m.GetLength 0 - 1 do
        *   for j in 0 .. m.GetLength 1 - 1 do              
        *  
        *)  
        printfn "\nPrint Matrix Content %s" (arr.GetType().Name)
        let mutable lineCount = 1
        for s in arr do
            printf "Line%2i|" lineCount  
            for w in s do  
                printf "%3c" '*'  
            printfn " (%i)" (s.Length)
            lineCount <- lineCount + 1

    let PrintJaggedArray (arr: string[][]) = 
        printfn "\nPrint Jagged Array Content %s" (arr.GetType().Name)  
        for i in 0 .. arr.Length - 1 do
            let line = new StringBuilder()
            for j in 0 .. arr.[i].Length - 1 do
                line.Append (" " + arr.[i].[j]) |> ignore
            if line.ToString() = line.ToString().ToUpper() then
                line.Append " <-- [UPPERCASED]" |> ignore
            printfn "%s" (line.ToString())

    let PrintTitle (message: string) = 
        printfn "\n"
        printfn "%s" ([|for i in 0..54 -> "*"|] |> String.concat "")
        printfn "%s" message
        printfn "%s" ([|for i in 0..54 -> "*"|] |> String.concat "")

    let PrintCommonArrayExceptions (arr: string[][]) =
        try
            arr.[100].[100] <- "hola"
        with
            (*
            | :? IndexOutOfRangeException as ex -> 
            | _ as ex -> 
            *)
            | ex -> 
                printfn "\nException: \n%s\n%s" (ex.GetType().Name) (ex.Message)

    [<EntryPoint>]
    let main argv =       
        // Single-dimensional Array(s)   
        PrintTitle "Reverse Array Elements"

        // Declare and Initialize Array of Chars
        let letters: char array = Array.create 5 ' '
        letters.[0] <- 'A'  
        letters.[1] <- 'E'  
        letters.[2] <- 'I'  
        letters.[3] <- 'O'  
        letters.[4] <- 'U'  

        PrintArrayChar letters
        let inverse_letters = ReverseChar letters   
        PrintArrayChar inverse_letters

        PrintTitle "Sort Integer Array Elements"   
 
        // Declare and Initialize Array of Integers    
        let numbers = [| 10; 8; 3; 1; 5 |]

        PrintArrayInt numbers   
        let ordered_numbers = BubbleSortInt numbers    
        PrintArrayInt ordered_numbers    

        PrintTitle "Sort String Array Elements"
    
        // Declare and Initialize and Array of Strings    
        let names : string array = [|"Damian";    
                "Rogelio";    
                "Carlos";    
                "Luis";   
                "Daniel"|]   

        PrintArrayString names
        let ordered_names = BubbleSortString names
        PrintArrayString ordered_names   

        // Multi-dimensional Array (Matrix row,column)      
        PrintTitle "Transpose Matrix"
    
        // let matrix = Array2D.zeroCreate<int> 2 3
        let matrix = array2D [|[|6; 4; 24|];
                                [|1; -9; 8|]|]    

        PrintMatrix matrix
        let transposed_matrix = TransposeMatrix matrix
        PrintMatrix transposed_matrix 
  
        // Jagged Array (Array-of-Arrays)  
  
        PrintTitle "Upper Case Random Array & Graph Number of Elements"
    
        (*              
        * Creating an array of string arrays using the String.Split method 
        * instead of initializing it manually as follows: 
        *  
        * let text: string[][] = [|  
        *      [| "word1"; "word2"; "wordN" |];  
        *      [| "word1"; "word2"; "wordM" |];  
        *      ... 
        *      |]
        *  
        * Text extract from: "El ingenioso hidalgo don Quijote de la Mancha" 
        *  
        *)  
        let mutable text = [|
            "Hoy es el día más hermoso de nuestra vida, querido Sancho;".Split ' ';
            "los obstáculos más grandes, nuestras propias indecisiones;".Split ' ';
            "nuestro enemigo más fuerte, miedo al poderoso y nosotros mismos;".Split ' ';
            "la cosa más fácil, equivocarnos;".Split ' ';
            "la más destructiva, la mentira y el egoísmo;".Split ' ';
            "la peor derrota, el desaliento;".Split ' ';
            "los defectos más peligrosos, la soberbia y el rencor;".Split ' ';
            "las sensaciones más gratas, la buena conciencia...".Split ' ' 
        |]
        PrintJaggedArray text
        UpperCaseRandomArray text
        PrintJaggedArray text
        GraphJaggedArray text  

        // Array Exceptions  
  
        PrintTitle "Common Array Exceptions"

        PrintCommonArrayExceptions null
        PrintCommonArrayExceptions text  

        // Accessing Class Array Elements through Indexer  
  
        PrintTitle "Alphabets" 

        let vowels = new Alphabet(5)
        vowels.[0] <- 'a'
        vowels.[1] <- 'e'
        vowels.[2] <- 'i'
        vowels.[3] <- 'o'
        vowels.[4] <- 'u'

        printfn "\nVowels = {%s}" (String.Join(",", [|vowels.[0].ToString(); vowels.[1].ToString(); vowels.[2].ToString(); vowels.[3].ToString(); vowels.[4].ToString()|]))
  
        let en = new Alphabet("abcdefghijklmnopqrstuvwxyz")
        printfn "English Alphabet = {%s}" (en.ToString())  
  
        let x = new Alphabet(en.Slice(9, 10))
        printfn "Alphabet Extract en[9..19] = {%s}" (x.ToString())

        let word1 = String.Join("", [|en.[6].ToString(); en.[14].ToString(); en.[14].ToString(); en.[3].ToString()|])
        let word2 = String.Join("", [|en.[1].ToString(); en.[24].ToString(); en.[4].ToString()|])  
        let word3 = String.Join("", [|en.[4].ToString(); en.[21].ToString(); en.[4].ToString(); en.[17].ToString(); en.[24].ToString(); en.[14].ToString(); en.[13].ToString(); en.[4].ToString()|])  
  
        printfn "\n%s %s, %s!\n" word1 word2 word3

        Console.Read() |> ignore
        0 // Return


The output:






















































































Voilà, that's it. Next post in the following days.

Sunday, March 6, 2011

Factorial and Fibonacci in F#



WARNING! I know that F# is intended to be use in a very Functional way, however, my goal is to show its Imperative and OO language features, so it can be compared with other 19 OO languages. Said that, if you know how to do something on the examples below in a more Functional style you can add it in a comment :)

Here below a little program in F# that implements 2 classes (in fact, they are 3). There is the main class, called Fiborial (Fibo(nnacci)+(Facto)rial) that implements the Fibonacci and the Factorial algorithms in two ways, one Recursive (using recursion) and the other Imperative (using loops and states). The second class is just an instance class that does the same thing, but its there just to show the difference between static and instance classes, and finally the third one (which will not appear in other languages) is the Program class which has the static execution method "Main".

You can also find 3 more little examples at the bottom. One prints out the Factorial's Series and Fibonacci's Series, the second one just shows a class that mixes both: static and instance members, and finally the third one that uses different return types (including System.Numerics.BigInteger) for the Factorial method to compare the timing and result.

As with the previous posts, you can copy and paste the code below in your favorite IDE/Editor and start playing and learning with it. This little "working" program will teach you some more basics of the Programming Language.

There are some "comments" on the code added just to tell you what are or how are some features called. In case you want to review the theory, you can read my previous post, where I give a definition of each of the concepts mentioned on the code. You can find it here: http://carlosqt.blogspot.com/2011/01/new-series-factorial-and-fibonacci.html 

In F# like in VB.NET there is a type called Module. An F# module is a grouping of F# code constructs such as types, values, function values, and code in do bindings. It is implemented as a common language runtime (CLR) class that has only static members. Normally I would only use the Module type as the first example, however, here I included both, an instance class with only Static Members and a second example using Module. The syntax for the members declaration varies so I wanted to include both even if we see a second example in the Mixing Instance and Static members program.

The Fiborial Program (using Type = Instance Class)

// Factorial and Fibonacci in F#  
namespace FiborialFs  
open System    
open System.Collections.Generic  
open System.Diagnostics  
//open System.Numerics  
  
// Instance Class   
// with all static members   
type StaticFiborial() = class  
    // Static Field  
    static let mutable className:string = ""  
    // Static Constructor/Initializer(s)   
    static do className <- "Static Constructor"      
    static do printfn "%s" className      
    // Static Method - Factorial Recursive  
    // in F#: type bigint = BigInteger  
    static member public FactorialR(n:int) : bigint =  
        if n = 1 then   
            bigint(1)  
        else   
            bigint(n) * StaticFiborial.FactorialR(n-1)  
    // Static Method - Factorial Imperative  
    static member public FactorialI(n:int) : bigint =  
        let mutable res:bigint = bigint(1)  
        for i = n downto 1 do   
            res <- res * bigint(i)  
        res  
    // Static Method - Fibonacci Recursive  
    static member public FibonacciR(n:int) : int64 =  
        if (n < 2) then  
            int64(1)  
        else    
            StaticFiborial.FibonacciR (n - 1) + StaticFiborial.FibonacciR(n - 2)  
    // Static Method - Fibonacci Imperative  
    static member public FibonacciI(n:int) : int64 =  
        let mutable pre:int64 = int64(1)  
        let mutable cur:int64 = int64(1)  
        let mutable tmp:int64 = int64(0)  
        for i = 2 to n do  
            tmp <- cur + pre  
            pre <- cur  
            cur <- tmp  
        cur  
    // Static Method - Benchmarking Algorithms  
    static member public BenchmarkAlgorithm(algorithm:int, values:list<int>) =  
        let timer = new Stopwatch()  
        let mutable i:int = 0  
        let mutable testValue:int = 1  
        let mutable facTimeResult:bigint = bigint(0)  
        let mutable fibTimeResult:int64 = int64(0)  
  
        // "if-elif-else" Flow Control Statement  
        if algorithm = 1 then  
            printfn "\nFactorial Imperative:"   
            // "For to" Loop Statement  
            for i = 0 to values.Length - 1 do  
                testValue <- values.Item(i)  
                // Taking Time    
                timer.Start()  
                facTimeResult <- StaticFiborial.FactorialI testValue
                timer.Stop()  
                // Getting Time    
                printfn " (%A) = %A" testValue timer.Elapsed
  
        elif algorithm = 2 then  
            printfn "\nFactorial Recursive:"   
            // "While" Loop Statement  
            while i < values.Length do    
                testValue <- values.Item(i)  
                // Taking Time    
                timer.Start()  
                facTimeResult <- StaticFiborial.FactorialR testValue  
                timer.Stop()  
                // Getting Time    
                printfn " (%A) = %A" testValue timer.Elapsed
                i <- i + 1  
  
        elif algorithm = 3 then  
            printfn "\nFibonacci Imperative:"  
            // "For in" Loop Statement  
            for item in values do  
                testValue <- item  
                // Taking Time    
                timer.Start()    
                fibTimeResult <- StaticFiborial.FibonacciI(testValue)  
                timer.Stop()    
                // Getting Time    
                printfn " (%A) = %A" testValue timer.Elapsed
  
        elif algorithm = 4 then  
            printfn "\nFibonacci Recursive:"  
            // "For in" Loop Statement  
            for item in values do  
                testValue <- item  
                // Taking Time    
                timer.Start()
                fibTimeResult <- StaticFiborial.FibonacciR testValue
                timer.Stop()    
                // Getting Time    
                printfn " (%A) = %A" testValue timer.Elapsed
  
        else   
            printfn "DONG!"   
end   
  
// Instance Class    
type InstanceFiborial() = class     
        // Instance Field  
        let mutable className:string = ""  
        // Instance Constructor/Initializer(s)   
        do className <- "Instance Constructor"  
        do printfn "%s" className  
        // Instance Method - Factorial Recursive    
        member public self.FactorialR(n:int) : bigint =  
            // Calling Static Method    
            StaticFiborial.FactorialR n    
        // Instance Method - Factorial Imperative    
        member public self.FactorialI(n:int) : bigint =  
            // Calling Static Method    
            StaticFiborial.FactorialI n
        // Instance Method - Fibonacci Recursive    
        member public self.FibonacciR(n:int) : int64 =  
            // Calling Static Method    
            StaticFiborial.FibonacciR n
        // Instance Method - Factorial Imperative    
        member public self.FibonacciI(n:int) : int64 =  
            // Calling Static Method    
            StaticFiborial.FibonacciI n    
end  

 
module Program =   
    //printfn "%s" (Fiborial.FactorialR(40).ToString())  
    printfn "\nStatic Class"  
    // Calling Instance Class with Static Methods    
    // No instantiation needed. Calling method directly from the class        
    printfn "FacImp(5) = %A" (StaticFiborial.FactorialI 5)
    printfn "FacRec(5) = %A" (StaticFiborial.FactorialR 5)  
    printfn "FibImp(11)= %i" (StaticFiborial.FibonacciI 11)
    printfn "FibRec(11)= %i" (StaticFiborial.FibonacciR 11)
    
    printfn "\nInstance Class"  
    // Calling Instance Class and Methods     
    // Need to instantiate before using. Calling method from instantiated object    
    let ff = new InstanceFiborial()    
    printfn "FacImp(5) = %A" (ff.FactorialI 5)
    printfn "FacRec(5) = %A" (ff.FactorialR 5)  
    printfn "FibImp(11)= %i" (ff.FibonacciI 11)
    printfn "FibRec(11)= %i" (ff.FibonacciR 11)
    
    // Create a (generic) list of integer values to test    
    // From 5 to 50 by 5    
    let values = [5..5..50]  
      
    // Benchmarking Fibonacci  
    // 1 = Factorial Imperative  
    StaticFiborial.BenchmarkAlgorithm (1, values)
    // 2 = Factorial Recursive    
    StaticFiborial.BenchmarkAlgorithm (2, values)     
    
    // Benchmarking Factorial  
    // 3 = Fibonacci Imperative    
    StaticFiborial.BenchmarkAlgorithm (3, values)
    // 4 = Fibonacci Recursive    
    StaticFiborial.BenchmarkAlgorithm (4, values)
    
    // Stop and Exit    
    Console.Read() |> ignore

And the Output is:





































The Fiborial Program (using Module = Static Class)
// Factorial and Fibonacci in F#  
namespace FiborialFs  
open System    
open System.Collections.Generic  
open System.Diagnostics  
  
// Static Class   
module StaticFiborial =   
    // Static Field  
    let mutable className:string = ""  
    // Static Constructor/Initializer(s)   
    do className <- "Static Constructor"      
    do printfn "%s" className      
    // Static Method - Factorial Recursive  
    // in F#: type bigint = BigInteger  
    let rec FactorialR(n:int) : bigint =  
        if n = 1 then   
            bigint(1)  
        else   
            bigint(n) * FactorialR(n-1)  
    // Static Method - Factorial Imperative  
    let public FactorialI(n:int) : bigint =  
        let mutable res:bigint = bigint(1)  
        for i = n downto 1 do   
            res <- res * bigint(i)  
        res  
    // Static Method - Fibonacci Recursive  
    let rec FibonacciR(n:int) : int64 =  
        if (n < 2) then  
            int64(1)  
        else    
            FibonacciR(n - 1) + FibonacciR(n - 2)  
    // Static Method - Fibonacci Imperative  
    let public FibonacciI(n:int) : int64 =  
        let mutable pre:int64 = int64(1)  
        let mutable cur:int64 = int64(1)  
        let mutable tmp:int64 = int64(0)  
        for i = 2 to n do  
            tmp <- cur + pre  
            pre <- cur  
            cur <- tmp  
        cur  
    // Static Method - Benchmarking Algorithms  
    let public BenchmarkAlgorithm(algorithm:int, values:list<int>) =  
        let timer = new Stopwatch()  
        let mutable i:int = 0 
        let mutable testValue:int = 1  
  
        // "if-elif-else" Flow Control Statement  
        if algorithm = 1 then  
            printfn "\nFactorial Imperative:"   
            // "For to" Loop Statement  
            for i = 0 to values.Length - 1 do  
                testValue <- values.Item(i)  
                // Taking Time    
                timer.Start()  
                FactorialI testValue |> ignore
                timer.Stop()  
                // Getting Time    
                printfn " (%A) = %A" testValue timer.Elapsed
  
        elif algorithm = 2 then  
            printfn "\nFactorial Recursive:"   
            // "While" Loop Statement  
            while i < values.Length - 1 do    
                testValue <- values.Item(i)  
                // Taking Time    
                timer.Start()  
                FactorialR testValue |> ignore
                timer.Stop()  
                // Getting Time    
                printfn " (%A) = %A" testValue timer.Elapsed
                i <- i + 1  
  
        elif algorithm = 3 then  
            printfn "\nFibonacci Imperative:"  
            // "For in" Loop Statement  
            for item in values do  
                testValue <- item  
                // Taking Time    
                timer.Start()    
                FibonacciI testValue |> ignore
                timer.Stop()    
                // Getting Time    
                printfn " (%A) = %A" testValue timer.Elapsed
  
        elif algorithm = 4 then  
            printfn "\nFibonacci Recursive:"  
            // "For in" Loop Statement  
            for item in values do  
                testValue <- item  
                // Taking Time    
                timer.Start()    
                FibonacciR testValue |> ignore
                timer.Stop()    
                // Getting Time    
                printfn " (%A) = %A" testValue timer.Elapsed
  
        else   
            printfn "DONG!"   
  
module Program =   
    printfn "\nStatic Class"  
    // Calling Instance Class with Static Methods    
    // No instantiation needed. Calling method directly from the class    
    printfn "FacImp(5) = %A" (StaticFiborial.FactorialI 5)
    printfn "FacRec(5) = %A" (StaticFiborial.FactorialR 5)  
    printfn "FibImp(11)= %i" (StaticFiborial.FibonacciI 11)
    printfn "FibRec(11)= %i" (StaticFiborial.FibonacciR 11)
  
    // Create a (generic) list of integer values to test    
    // From 5 to 50 by 5    
    let values = [5..5..50]  
      
    // Benchmarking Fibonacci  
    // 1 = Factorial Imperative  
    StaticFiborial.BenchmarkAlgorithm(1, values);    
    // 2 = Factorial Recursive    
    StaticFiborial.BenchmarkAlgorithm(2, values);     
    
    // Benchmarking Factorial  
    // 3 = Fibonacci Imperative    
    StaticFiborial.BenchmarkAlgorithm(3, values);    
    // 4 = Fibonacci Recursive    
    StaticFiborial.BenchmarkAlgorithm(4, values);     
    
    // Stop and Exit    
    Console.Read() |> ignore


And the Output is:




































Printing the Factorial and Fibonacci Series
// Factorial and Fibonacci in F#  
namespace FiborialSeries  
open System    
open System.Text  
open System.Numerics  
  
// Static Class   
module Fiborial =   
    // We first define the Factorial and Fibonacci methods  
    // so we can use them after in the Series methods  
  
    let rec Factorial(n:int) : bigint =  
        if n = 1 then   
            bigint(1)  
        else   
            bigint(n) * Factorial(n-1)  
  
    let rec Fibonacci(n:int) : int64 =  
        if (n < 2) then  
            int64(1)  
        else    
            Fibonacci(n - 1) + Fibonacci(n - 2)  
  
    // Using a StringBuilder as a list of string elements    
    let public GetFactorialSeries(n:int): string =  
        // Create the String that will hold the list    
        let mutable series:StringBuilder = StringBuilder()  
        // We begin by concatenating the number you want to calculate    
        // in the following format: "!# ="    
        ignore (series.Append "!")  
        ignore (series.Append n)  
        ignore (series.Append " = ")  
        // We iterate backwards through the elements of the series   
        for i = n downto 1 do   
            // and append it to the list    
            ignore (series.Append i)  
            if i > 1 then  
                ignore (series.Append " * ")  
            else  
                ignore (series.Append " = ")  
        // Get the result from the Factorial Method    
        // and append it to the end of the list    
        ignore (series.Append(Factorial n))    
        // return the list as a string    
        series.ToString()  
  
    // Using a StringBuilder as a list of string elements   
    let public GetFibonnaciSeries(n:int): string =  
        // Create the String that will hold the list   
        let mutable series:StringBuilder = StringBuilder()  
        // We begin by concatenating the first 3 values which    
        // are always constant    
        ignore (series.Append "0, 1, 1")  
        // Then we calculate the Fibonacci of each element    
        // and add append it to the list   
        for i = 2 to n do  
            if i < n then  
                ignore (series.Append ", ")  
            else  
                ignore (series.Append " = ")  
            ignore (series.Append(Fibonacci i))  
        // return the list as string  
        series.ToString()  
  
module Program =  
    // Printing Factorial Series    
    printfn ""    
    printfn "%s" (Fiborial.GetFactorialSeries 5)  
    printfn "%s" (Fiborial.GetFactorialSeries 7)    
    printfn "%s" (Fiborial.GetFactorialSeries 9)  
    printfn "%s" (Fiborial.GetFactorialSeries 11)    
    printfn "%s" (Fiborial.GetFactorialSeries 40)    
    // Printing Fibonacci Series    
    printfn ""    
    printfn "%s" (Fiborial.GetFibonnaciSeries 5)  
    printfn "%s" (Fiborial.GetFibonnaciSeries 7)  
    printfn "%s" (Fiborial.GetFibonnaciSeries 9)  
    printfn "%s" (Fiborial.GetFibonnaciSeries 11)  
    printfn "%s" (Fiborial.GetFibonnaciSeries 40)

And the Output is:

















Mixing Instance and Static Members in the same Class

We can also define instance classes that have both, instance and static members such as: fields, properties, constructors, methods, etc. However, we cannot do that if the type is a Module because Module = Static Class and remember the features mentioned in the previous post:
The main features of a static class are:
  • They only contain static members.
  • They cannot be instantiated.
  • They are sealed.
  • They cannot contain Instance Constructors

namespace FiborialExtrasFs2  
open System  
  
// Instance Classes can have both: static and instance members.     
// However, Modules (Static Classes) only allow static members to be defined.    
  
// Instance Class    
type Fiborial() = class  
    // Instance Field  
    let mutable instanceCount:int = 0  
    // Instance Constructor/Initializer(s)   
    do instanceCount <- 0  
    do printfn "\nInstance Constructor %i" instanceCount
    // Static Field  
    static let mutable staticCount:int = 0  
    // Static Constructor/Initializer(s)   
    static do staticCount <- 0  
    static do printfn "\nStatic Constructor %i" Fiborial.StaticCount    
    // Instance Read-Only Property  
    member public this.InstanceCount   
        with get() = instanceCount  
    // Static Read-Only Property    
    // Remeber that Properties are Methods to the CLR, so, you can also    
    // define static properties for static fields.     
    static member public StaticCount  
        with get() = staticCount  
    // Instance Method  
    member public this.Factorial(n:int) =  
        instanceCount <- instanceCount + 1  
        printfn "\nFactorial(%i)" instanceCount
    // Static Method  
    static member public Fibonacci(n:int) =  
        staticCount <- staticCount + 1  
        printfn "\nFibonacci(%i)" Fiborial.StaticCount
end  
  
module Program =  
    // Calling Static Constructor and Methods    
    // No need to instantiate    
    Fiborial.Fibonacci 5
    
    // Calling Instance Constructor and Methods    
    // Instance required    
    let fib:Fiborial = new Fiborial()  
    fib.Factorial 5
    
    Fiborial.Fibonacci 15
    fib.Factorial 5
    
    // Calling Instance Constructor and Methods    
    // for a second object    
    let fib2:Fiborial = new Fiborial()  
    fib2.Factorial 5    
                
    printfn ""  
    // Calling Static Property    
    printfn "Static Count = %i" Fiborial.StaticCount  
    // Calling Instance Property of object 1 and 2    
    printfn "Instance 1 Count = %i" fib.InstanceCount
    printfn "Instance 2 Count = %i" fib2.InstanceCount

And the Output is:





















Factorial using System.Int64, System.Double, System.Numerics.BigInteger (bigint)

The Factorial of numbers over 20 are massive!
For instance: !40 = 815915283247897734345611269596115894272000000000!
Because of this, the previous version of this program was giving the "wrong" result
!40 = -70609262346240000 when using "long" (System.Int64) type, but it was not until I did the Fiborial version in VB.NET that I realized about this faulty code, because instead of giving me a wrong value, VB.NET execution thrown an Overflow Exception when using the "Long" (System.Int64) type.

My first idea was to use ulong and ULong, but both failed for "big" numbers. I then used Double (double floating point) type and got no more exception/wrong result. The result of the factorial was now correct !40 = 1.1962222086548E+56, but still I wanted to show the Integer value of it, so I did some research and found that there is a new System.Numerics.BigInteger class in the .NET Framework 4.0. Adding the reference to the project and using this new class as the return type of the Factorial methods, I was able to get the result I was expecting.
!40 = 815915283247897734345611269596115894272000000000

What I also found was that using different types change the time the algorithm takes to finish:
System.Int64 < System.Double < System.Numerics.BigInteger
Almost by double!

To illustrate what I just said, lets have a look at the following code and the output we get.

open System  
open System.Diagnostics  
  
// Long Factorial  
let rec FactorialInt64(n:int): int64 =  
    match n with  
    | 1 -> int64(1)  
    | n -> int64(n) * FactorialInt64(n - 1)  
  
// Double Factorial  
let rec FactorialDouble(n:int): double =  
    match n with  
    | 1 -> double(1)  
    | n -> double(n) * FactorialDouble(n - 1)  
  
// BigInteger Factorial  
let rec FactorialBigInteger(n:int): bigint =  
    match n with  
    | 1 -> bigint(1)  
    | n -> bigint(n) * FactorialBigInteger(n - 1)  
  
let timer:Stopwatch = new Stopwatch()  
let mutable facIntResult:int64 = int64(0)  
let mutable facDblResult:double = double(0)  
let mutable facBigResult:bigint = bigint(0)  
  
let values:list<int> = [5..5..50]  
  
printfn "\nFactorial using Int64"  
// Benchmark Factorial using Int64  
for i in values do  
    timer.Start()    
    facIntResult <- FactorialInt64(i)  
    timer.Stop()   
    printfn "(%i) = %A : %i" i timer.Elapsed facIntResult
  
printfn "\nFactorial using Double"  
// Benchmark Factorial using Double  
for i in values do  
    timer.Start()    
    facDblResult <- FactorialDouble(i)  
    timer.Stop()   
    printfn "(%i) = %A : %E" i timer.Elapsed facDblResult
  
printfn "\nFactorial using BigInteger"  
// Benchmark Factorial using Double  
for i in values do  
    timer.Start()  
    facBigResult <- FactorialBigInteger(i)  
    timer.Stop()   
    printfn "(%i) = %A : %A" i timer.Elapsed facBigResult

NOTE: you DONT need to manually add a reference to the System.Numerics.dll assembly to your project because F# already adds it for you. In fact you don't need to use BigInteger, but bigint which is a type bigint = BigInteger.

And the Output is:

Saturday, October 16, 2010

F# - Basics by Example



Continue with the Basics by Example; today's version of the post written in F# Enjoy!

I was thinking in changing the name of this post to "F# - OO Basics by Example" because I guess its confusing the fact that F# is more a Functional Programming language than an Imperative one, even if both paradigms are well supported by the language. At the end I decided to leave it like that, I just want to make clear that you will not find any "Functional Basics" on this post ;) ... I will probably do the same in my next Scala post.

You can copy and paste the code below in your favorite IDE/Editor and start playing and learning with it. This little "working" program will teach you the basics of the Programming Language.

There are some "comments" on the code added just to tell you what are or how are some features called. In case you want to review the theory, you can read my previous post, where I give a definition of each of the concepts mentioned on the code. You can find it here: http://carlosqt.blogspot.com/2010/08/new-series-languages-basics-by-example.html 



Greetings Program - Verbose
// F# Basics
namespace GreetProgram  
open System  
  
// Constructor
type public Greet(message:string, name:string, loopMessage:int) = class  
    // Attributes or Fields
    let mutable message:string = message
    let mutable name:string = name
    let mutable loopMessage:int = loopMessage
    // Properties
    member public this.Name 
        with get() = name 
        and set(value:string) = name <- this.Capitalize(value)
    member public this.Message 
        with get() = message 
        and set(value:string) = message <- this.Capitalize(value)
    member public this.LoopMessage 
        with get() = loopMessage
        and set(value:int) = loopMessage <- value
    // Overloaded Constructor
    new() = Greet("", "", 0)
    // Method 1
    member private self.Capitalize(value:string) = (
        // "if-then-else" statement 
        if value.Length >= 1 then 
            value.[0].ToString().ToUpper() + value.[1..]            
        else
            ""
    )
    // Method 2  
    member public self.Salute() = (
        // "for" statement
        for i = 1 to self.LoopMessage do            
            printfn "%s %s!" self.Message self.Name            
    )
    // Overloaded Method 2.1
    member public self.Salute(message:string, name:string, loopMessage:int) = (
        // "while" statement
        let mutable i:int = 0
        while i < loopMessage do
            printfn "%s %s!" (self.Capitalize message) (self.Capitalize name)
            i <- i + 1
    )
    // Overloaded Method 2.2
    member public self.Salute(name:string) = (
        // "switch/case" statement is not supported  
        // using match statement instead
        let dtNow:DateTime = DateTime.Now   
        let t:int = dtNow.Hour
        let timeMessage =
            match t with
            |6|7|8|9|10|11 -> self.Message <- "good morning,"  
            |12|13|14|15|16|17 -> self.Message <- "good afternoon,"  
            |18|19|20|21|22 -> self.Message <- "good evening,"  
            |23|0|1|2|3|4|5 -> self.Message <- "good night,"  
            | _ -> self.Message <- "huh?"
        printfn "%s %s!" (self.Capitalize self.Message) (self.Capitalize name)
    )
end  
  
// Console Program
module public GreetProgram = 
    // Define object of type Greet  
    let g:Greet = new Greet()
    // Instantiate Greet. Call Constructor 
    // Call Set Properties  
    g.Message <- "hello"
    g.Name <- "world"
    g.LoopMessage <- 5
    // Call Method 2  
    g.Salute()
    // Call Overloaded Method 2.1 and Get Properties
    g.Salute(g.Message, "f#", g.LoopMessage)
    // Call Overloaded Method 2.2 
    g.Salute("carlos")

    // Stop and Exit
    printfn "Press any key to exit..."
    Console.Read() |> ignore

Greetings Program - Minimal
// F# Basics
open System  
  
// Constructor
type Greet(message:string, name:string, loopMessage:int) = 
    // Attributes or Fields 
    let mutable message:string = message
    let mutable name:string = name
    let mutable loopMessage:int = loopMessage
    // Properties
    member this.Name 
        with get() = name 
        and set(value:string) = name <- this.Capitalize(value)
    member this.Message 
        with get() = message 
        and set(value:string) = message <- this.Capitalize(value)
    member this.LoopMessage 
        with get() = loopMessage 
        and set(value:int) = loopMessage <- value
    // Overloaded Constructor
    new() = Greet("", "", 0)
    // Method 1
    member private self.Capitalize(value:string) = 
        // "if-then-else" statement 
        if value.Length >= 1 then 
            value.[0].ToString().ToUpper() + value.[1..]
        else
            ""
    // Method 2  
    member self.Salute() =
        // "for" statement
        for i = 1 to self.LoopMessage do            
            printfn "%s %s!" self.Message self.Name
    // Overloaded Method 2.1
    member self.Salute(message:string, name:string, loopMessage:int) = 
        // "while" statement
        let mutable i:int = 0
        while i < loopMessage do
            printfn "%s %s!" (self.Capitalize message) (self.Capitalize name)
            i <- i + 1
    // Overloaded Method 2.2
    member self.Salute(name:string) = 
        // "switch/case" statement is not supported  
        // using match statement instead
        let dtNow = DateTime.Now        
        let t = dtNow.Hour
        let timeMessage =
            match t with
            |6|7|8|9|10|11 -> self.Message <- "good morning,"  
            |12|13|14|15|16|17 -> self.Message <- "good afternoon,"  
            |18|19|20|21|22 -> self.Message <- "good evening,"  
            |23|0|1|2|3|4|5 -> self.Message <- "good night,"  
            | _ -> self.Message <- "huh?"        
        printfn "%s %s!" (self.Capitalize self.Message) (self.Capitalize name)
  
// Console Program
// Define object of type Greet  
let g = Greet()
// Instantiate Greet. Call Constructor 
// Call Set Properties  
g.Message <- "hello"
g.Name <- "world"
g.LoopMessage <- 5
// Call Method 2  
g.Salute()
// Call Overloaded Method 2.1 and Get Properties
g.Salute(g.Message, "f#", g.LoopMessage)
// Call Overloaded Method 2.2 
g.Salute("carlos")

// Stop and Exit
printfn "Press any key to exit..."
Console.Read() |> ignore


And the Output is:


Saturday, June 19, 2010

OO Hello World - F#



Hello world in F# is here.
F# is a great addition to the .NET set of languages because of its functional paradigm support.
You can go directly to the F# Info section to get some extra info about the language.


By the way, you can see my previous post here: http://carlosqt.blogspot.com/2010/06/oo-hello-world.html
where I give some details on WHY these "OO Hello World series" samples.

Version 1 (Minimal):
The minimum you need to type to get your program compiled and running.
type Greet(name:string) = 
    member private self.name = name.[0].ToString().ToUpper() + name.[1..]
    member self.Salute() = printfn "Hello %s!" name

// Greet the world!
 let g = Greet("world")
 g.Salute()


Version 2 (Verbose):
Explicitly adding instructions and keywords that are optional to the compiler.
namespace GreetProgram
open System

type Greet(name:string) = class
    member private self.name = name.[0].ToString().ToUpper() + name.[1..]
    member public self.Salute() = printfn "Hello %s!" self.name
end

// Greet the world!
module GreetModule =
    let g:Greet = new Greet("world")
    g.Salute()



The Program Output:










F# Info:

F# (pronounced “F Sharp”) is the latest addition to the Microsoft programming languages.
“F# is a succinct, expressive and efficient functional and object-oriented language for .NET which helps you write simple code to solve complex problems.” “F# brings you type safe, succinct, efficient and expressive functional programming language on the .NET platform. It is a simple and pragmatic language, and has particular strengths in data-oriented programming, parallel I/O programming, parallel CPU programming, scripting and algorithmic development. It lets you access a huge .NET library and tools base and comes with a strong set of Visual Studio development tools. F# combines the advantages of typed functional programming with a high-quality, well-supported modern runtime system.” Taken from (http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/default.aspx)

“F# is a programming language that provides support for functional programming in addition to traditional object-oriented and imperative (procedural) programming. The Visual F# product provides support for developing F# applications and extending other .NET Framework applications by using F# code. F# is a first-class member of the .NET Framework languages and retains a strong resemblance to the ML family of functional languages.” Taken from: (http://msdn.microsoft.com/en-us/library/dd233154.aspx)

Appeared:
2005
Current Version:
Developed by:
Microsoft
Creator:
Don Syme
Influenced by:
OCaml (Xavier Leroy)
Predecessor Language
Predecessor Appeared
Predecessor Creator
Runtime Target:
CLR
Latest Framework Target:
4.0
Mono Target:
Yes
Allows Unmanaged Code:
No
Source Code Extension:
“.fs”, “.fsx”
Keywords:
97
Case Sensitive:
Yes
Free Version Available:
Yes
Open Source:
No
Standard:
No
Latest IDE Support:
Visual Studio 2010 (std, pro, etc) or Visual Studio 2008 (std, pro, shell)
SharpDevelop 3.2/4.0 (beta)
MonoDevelop 2.2
Language Reference:
Extra Info: