1
votes

I'm pretty new to programming in F#, and I am working on a project at the moment, with a function that takes an integer and returns a string value. My problem (se my code below) is that no matter what I do, I cant return the values of my str, calling my function.

let mulTable (n:int):string = string n
let mutable m = 1
let mutable str = ""

while m < 10 do
    str <- "m\t" + str
    m <- m + 1
printfn "%A" (mulTable str)

My idea here is that I want to store the value of m, in str, så that str in the end of my while loop contains the values of "1 2 3 4 5 6 7 8 9". But no matter what I try my printfn "%A" mulTable str, returns "this expressions was exspected to have type int, but here has type string". I have tried converting my str to a string in my mutable value like:

let mutable str = ""
let mutable str1 = str |> int

and then I try to call my str1 using function mulTable instead of calling str. But still it does not work.

What am I missing here? I've been trying every single possible solution I can think of, without being able to solve my problem.

3
mulTable takes an int, but you're passing str to it. str is a string, not an int. - Foole
Yeah I've figured so far :-) I have tried to solve this by using a new value str1, that takes the value of str and convert it to an int. But when I then try to use mulTable on str1 (that now contains str converted to a int) it still does not work. It returns: Unhandled Exception: System.FormatException: Input string was not in a correct format, even though the input I now use is actually an integer, and now satisfies my function mulTable. - NewDev90
You cannot convert an empty string into an integer. What value you would expect? Try initializing it with "0" if you have to. - s952163
It looks to me like your issue all along is that you are writing m inside the string and expecting it to produce an integer value inside str. I'm afraid it won't, you'll just get back the letter m. Try instead something like str <- (sprintf "%d\t" m) + str. Then you will have your concatenated string without the need for mulTable. Of course, the answers below have shown you some good other ways to achieve what you want. - Jarak

3 Answers

1
votes

A fix of your own algorithm could be:

let getSequenceAsString max =
    let concat s x = sprintf "%s\t%i" s x
    let mutable m = 1
    let mutable str = ""

    while m < max do
        str <- concat str m
        m <- m + 1
    str
printfn "%A" (getSequenceAsString 10)

But as others have shown it's a lot of work that can be done more easily:

open System
let getSequenceAsString max = 
    String.Join("\t", [1..max-1])

If you want each number reverted as you ask for in a comment it could be done this way:

let getSequenceAsString min max = 

    let revert x = 
        let rec rev y acc =
            match y with
            | 0 -> acc
            | _ -> rev (y / 10) (sprintf "%s%i" acc (y % 10))
        rev x ""

    String.Join("\t", ([min..max-1] |> List.map revert))

printfn "%A" (getSequenceAsString 95 105)

Gives: 
"59     69      79      89      99      001     101     201     301     401"
0
votes

You can easily join an array of strings into a string array, and then print it out if necessary.

open System

let xs = [1..9] |> List.map string 
//you should avoid using mutable variables, and instead generate your list of numbers with an list comprehension or something similar.
String.Join("\t", xs) 
//A little exploration of the List/Array/String classes will bring this method up: "concatenates the members of a collection using the separator string.

This gives me:

val it : string = "1 2 3 4 5 6 7 8 9"

0
votes

I've adjusted the code to make it produce results similar to what you wanted:

let mulTable (n:int):string = string n
let mutable m = 1
let mutable str = ""

while m < 10 do
    str <- mulTable m+ "\t" + str
    m <- m + 1
printfn "%A" (str)

I've used your mulTable to convert m to string, but for printfn you don't need to use that, because str is already a string. Still the result would be 9 8 7 6 5 4 3 2 1

There are more then one way to revert the string, one of them would be to split the string into an array of characthers and then revert the array. From resulting array we will build a new string again. It would look something like:

printf "%A" (new System.String(str.ToCharArray() |> Array.rev ))

Edit

To achieve the same result, I would suggest to use more functional style, using recursion and avoiding mutating variables.

let getNumbersString upperLimit = 
    let rec innerRecursion rem acc=
        match rem with
            | 0 -> acc
            | _ -> innerRecursion (rem-1) (sprintf "%i "rem::acc)
    innerRecursion upperLimit [] |> String.concat ""

getNumbersString 9

Will result in val it : string = "1 2 3 4 5 6 7 8 9 "