0

I am new to Scala and try to use it in a functional way. Here are my questions:

  1. Why can't I create a new binding for 'cnt' variable with function return value using '<-' operator?

  2. How can increment immutable variable in a functional way (similar to Haskell <-) ? For the sake of experiment I don't want to use mutable vars.

    import scala.io.Source
    object MyProgram {
    
      def main(args: Array[String]): Unit = {
        if (args.length > 0) {
          val lines = Source.fromFile(args(0)).getLines()
          val cnt = 0
          for (line <- lines) {
            cnt <- readLines(line, cnt)
          }
          Console.err.println("cnt = "+cnt)
        }
      }
    
      def readLines(line: String, cnt:Int):Int = {
        println(line.length + " " + line)
        val newCnt = cnt + 1
        return (newCnt)
      }
    }   
    

As for side effects, I could never expect that (line <- lines) is so devastating! It completely unwinds lines iterator. So running the following snippet will make size = 0 :

val lines = Source.fromFile(args(0)).getLines()
var cnt = 0
for (line <- lines) {
  cnt = readLines(line, cnt)
}
val size = lines.size

Is it a normal Scala practice to have well-hidden side-effects like this?

Chris Martin
  • 30,334
  • 10
  • 78
  • 137
Anton Ashanin
  • 1,817
  • 5
  • 30
  • 43
  • tip: in scala last statement of the function interpreted as result to return, thus `readLines` can be written as `def readLines(line: String, cnt:Int):Int = { println(line.length + " " + line); cnt + 1}` – om-nom-nom Mar 19 '13 at 14:10
  • Scala encourages use of immutability, you have the option of using mutable data structures in situations like the one you have. You can idiomaticaly fold/reduce/recurse to eliminate var's but they are the underlying mechanisms used! – korefn Mar 19 '13 at 14:17

3 Answers3

2

You could fold on lines like so:

val lines = Source.fromFile(args(0)).getLines()
val cnt = lines.foldLeft(0) { case (count, line) => readLines(line, count) }
Console.err.println("cnt = "+cnt)

Your readLines method does side-effect with the call to println, but using foldLeft guarantees left-to-right processing of the list, so the output should be the same.

1

Why can't I reassign immutable 'cnt' variable with function return value using '<-' operator?

Why would you? If you has java experience, <- has the simular meaning as : in for(Item x: someCollection). It is just a syntactic sugar for taking current item from collection and naming it, it is not a bind operator in general.

Moreover, isn't reassign immutable oxymoron?

How can increment immutable variable in a functional way (similar to Haskell <-)?

Scala people usually use .zipWithIndex but this will work only if you're going to use counter inside for comprehension:

for((x, i) <- lines.zipWithIndex) { println("the counter value is" + i) } 

So I think you need to stick with lines.count or use fold/reduce or = to assign new value to variable.

Community
  • 1
  • 1
om-nom-nom
  • 62,329
  • 13
  • 183
  • 228
  • You right, I should not use "reassign" so I have changed my question to: "Why can't I create a new binding for 'cnt' variable with function return value using '<-' operator?" And from answers here I now understand that Scala does not provide programmer explicit binding mechanism for immutables like Haskell monads do. – Anton Ashanin Mar 19 '13 at 14:18
0

<- is not an operator, just a syntax used in for expressions. You have to use =. If you want to use <- it must be within the for-iteration-expression. And you cannot increment a val. If you want to modify that variable, make it a var.

bluenote10
  • 23,414
  • 14
  • 122
  • 178