1

I need to finish a method in F#. All-day I was searching for some methods to change a letter in a string and did not found anything. I have done the (a) and now I need to use the method from (a) in (b).

The task

let rec vowelToUpper x : char = 
    match x with 
    | 'a' -> 'A'
    | 'e' -> 'E'
    | 'i' -> 'I'
    | 'o' -> 'O'
    | 'u' -> 'U'
    | _ -> x
let rec converter (str ) length =  
    if length=0 then 
        str
    else
        str.[length-1] <- vowelToUpper str.[length-1]
        converter str (length-1)
  

Neither <- nor = works, in this case, the error says to consider using some constraints. I think I need to use the list of chars constraint on the str. Also, maybe it is because it's not mutable? And since this is a basic thing to do in any programming language, why is it that hard to find the solution on internet?)

kakakakakakakk
  • 467
  • 10
  • 31
  • 1
    The compiler doesn't know if `str` has an indexer because it doesn't know the type of `str`. Tell it what the type is - `converter (str : string) length =` – Fyodor Soikin Feb 25 '21 at 18:07
  • 1
    But that won't help you anyway, because strings are immutable. – Fyodor Soikin Feb 25 '21 at 18:08
  • so there is no way to change the string? – kakakakakakakk Feb 25 '21 at 18:08
  • ``` let workingString = "aeioufffaa" let array = workingString.ToCharArray() array.[0] <- vowelToUpper array.[0] ``` this works, but I dont know how to integrate it in my assignment – kakakakakakakk Feb 25 '21 at 18:09
  • Strings are immutable in all .NET languages, so instead of thinking about modifying a string, you should think about generating a **new** string that contains the correct answer. – Brian Berns Feb 25 '21 at 19:01

3 Answers3

2

As mentioned in the comments, strings in .NET are immutable and cannot be changed. The only way in which your converter function can work is by returning a new string.

There are several ways of doing that. As is usual with answers about assignments, I won't give you a complete solution, but some hints that you should be able to put together.

First, the most obvious approach is to use the String.map function which takes a function char -> char (you have one of those already!) together with an input string and produces a new output string.

Second, if you wanted to do your own functional processing of strings, then the best way to do this is to turn a string into a list of characters and then back. You could then use pattern matching and recursion to transform your string as a list of characters:

let sin = "hello"
let l1 = sin |> List.ofSeq
let l2 = (* ... do some transformation here ... *)
let sout = System.String(Array.ofSeq l2)

Finally, if you really wanted to use something based on mutating an array, you could get the array of characters, mutate that and then construct a new string:

let sin = "hello"
let arr = sin.ToCharArray()
arr.[0] <- 'H' (* Mutate the array *)
let sout = System.String(arr)
Tomas Petricek
  • 240,744
  • 19
  • 378
  • 553
2
let to_upper =
    function
    | 'a' -> 'A'
    | 'e' -> 'E'
    | 'i' -> 'I'
    | 'o' -> 'O'
    | 'u' -> 'U'
    | x -> x

"hello world"
|> Seq.map to_upper
|> Seq.toArray
|> System.String

So I did not read conditions :(

This will work as stated

let vowelToUpper c = 
    match c with
    | 'a' -> 'A'
    | 'e' -> 'E'
    | 'i' -> 'I'
    | 'o' -> 'O'
    | 'u' -> 'U'
    | _ -> c
    |> (string)

let rec convert input =
    match Seq.tryHead input with
    | None -> ""
    | Some c -> (vowelToUpper c) + (convert (Seq.tail input))

convert "hello world"

But I would say it's bad code.

Huusom
  • 5,654
  • 1
  • 17
  • 15
1

This worked out for me by generating a new string.


let rec converter (str : string) (finalStr : string) length =  
    if length=0 then 
        finalStr
    else
        converter str (finalStr + (vowelToUpper str.[length-1]).ToString()) (length-1)
    

kakakakakakakk
  • 467
  • 10
  • 31