Search code examples
stringscalacharpattern-matchingstring-iteration

Scala: iterate through every character of a String and use pattern matching


I think what I'm trying to do is pretty obvious. For every character in a string1, print something using patter matching. (I have string2 there because I will use pattern matching of string1 to do something to string 2 and return String 2)

For some reason my code only prints out "()".

Also how do I make sure that my code returns a String. When I put the code in terminal it says: (string1: String)String => Unit , how do I make it say (string1: String)String => String

def stringPipeline(string1: String) = (string2: String) => {

  for(c <- string1) {
    c match {
      case 'u' => "Upper Case"
      case 'r' => "reverse"
      case _ => "do something"
    }
  }
}

EDIT:

I would just like to point out what I wanted to do with string2:

def stringPipeline(string1: String) = (string2: String) => { 
    for(c <- string1) yield { 
        c match { 
            case 'U' => string2.toUpperCase 
            case 'r' => string2.reverse } } } 

But it's return a vector/list of strings. I want all those cases to work on the same string2 object. So if I test the method on "hello", it should return "OLLEH".

Thanks


Solution

  • If you paste your definition in the Scala REPL you will see that the type of the function you have defined is

    stringPipeline: (string1: String)String => Unit
    

    i.e. a function that takes a string string1 as input and returns a closure taking a second string string2 as input, and returning Unit, which is like void in Java and has only the value ().

    So why does the returned closure have Unit as return type? Its body contains only one expression:

    for(c <- string1) {
        c match {
          case 'u' => "Upper Case"
          case 'r' => "reverse"
          case _ => "do something"
        }
    }
    

    for evaluates its internal expression

    c match {
        case 'u' => "Upper Case"
        case 'r' => "reverse"
        case _ => "do something"
    }
    

    for each possible c in string1 and then returns (). In other words, for is not letting the values produced inside it through.

    If you want to print the strings "Upper Case" you need to write

        case 'u' => println("Upper Case")
    

    Then the return value of the closure will still be (), but its evaluation will print the strings in the match expression as a side effect.

    On a side note, why did you introduce the parameter string2 if you do not use it?

    EDIT

    Since the output of the function inside the loop is used as input for the next cycle of the loop, you need a fold function, i.e. something like this:

    def stringPipeline(string1: String) = (string2: String) => {
        string1.foldLeft(string2)((s: String, c: Char) =>
            c match {
                case 'u' => s.toUpperCase
                case 'r' => s.reverse
                case _   => s
            }
        )
    }