44

I just wonder why there is no i++ to increase a number. As what I know, languages like Ruby or Python doesn't support it because they are dynamically typed. So it's obviously we cannot write code like i++ because maybe i is a string or something else. But Scala is statically typed - the compiler absolutely can infer that if it is legal or not to put ++ behind a variable.

So, why doesn't i++ exist in Scala?

kiritsuku
  • 52,967
  • 18
  • 114
  • 136
xiaowl
  • 5,177
  • 3
  • 27
  • 28
  • 14
    PHP is dynamically typed but supports pre and post incrementation. Just a counterexample ;) – Mchl Dec 23 '10 at 16:13
  • What do you need it for? – Viktor Klang Dec 23 '10 at 16:15
  • 2
    Duplicate of http://stackoverflow.com/questions/3992399/operator-in-scala/3993646#3993646 – Craig P. Motlin Dec 23 '10 at 16:57
  • 6
    Just to make it explicit what Mchl has already alluded to: *you are dead wrong* about the reasons why Ruby doesn’t have `++`, and why Scala should have it. – Konrad Rudolph Dec 23 '10 at 18:36
  • 3
    By this argument you can't do anything in Ruby or Python or Scheme or Prolog or... where do people come up with this stuff? – James Iry Dec 23 '10 at 21:08
  • @Mchl Yes, that's true.What I said is not strict. – xiaowl Dec 24 '10 at 03:29
  • 1
    @Konrad I think I didn't make it clear that why Ruby or Python doesn't have `++`. It's not because they are dynamic, but there are ambiguous ways to implement `++`. Take JavaScript as example, `var i=1 i++` we get `2`, but `var i='1' i++` we get `1`. That makes things more confused. Some other dynamic language support `++`, and there are different ways to do `++` on different types. So it's not so good to do `++` in Ruby. – xiaowl Dec 24 '10 at 03:36
  • KevinX: the Ruby equivalent of "var i='1' i++" could simply give a runtime error. There are already many functions which work just for some types, ++ would be no different. JavaScript is an exception, because there is almost no way to get a runtime error. – Blaisorblade Mar 30 '11 at 23:47
  • 2
    @KevinX Wow. Dynamic typing has ***nothing*** to do with that. `++` isn't allowed in Ruby simply because it's not among the operators that you can overload. `++` won't get parsed as a single operator, so you can't have a method with that name. – Jonathan Sterling May 11 '11 at 05:23

11 Answers11

72

Scala doesn't have i++ because it's a functional language, and in functional languages, operations with side effects are avoided (in a purely functional language, no side effects are permitted at all). The side effect of i++ is that i is now 1 larger than it was before. Instead, you should try to use immutable objects (e.g. val not var).

Also, Scala doesn't really need i++ because of the control flow constructs it provides. In Java and others, you need i++ often to construct while and for loops that iterate over arrays. However, in Scala, you can just say what you mean: for(x <- someArray) or someArray.foreach or something along those lines. i++ is useful in imperative programming, but when you get to a higher level, it's rarely necessary (in Python, I've never found myself needing it once).

You're spot on that ++ could be in Scala, but it's not because it's not necessary and would just clog up the syntax. If you really need it, say i += 1, but because Scala calls for programming with immutables and rich control flow more often, you should rarely need to. You certainly could define it yourself, as operators are indeed just methods in Scala.

Rafe Kettler
  • 75,757
  • 21
  • 156
  • 151
  • @Cedric You can't write that if you declared `i` as a `val`. You can declare something as `var` and do that, but that's not considered a functional style. So in most cases (Ints are usually vals if you're doing it right), you're wrong. Most values in well written Scala code are immutable. – Rafe Kettler Dec 23 '10 at 20:46
  • 8
    Well, `++` could _not_ be in Scala without some big changes, since it assigns a new value to an identifier. This identifier is not visible from inside a method, and Scala doesn't have a pass-by-reference to handle it anyway (nor does the JVM). – Daniel C. Sobral Dec 24 '10 at 01:49
  • 2
    Fine, let me refine my answer, then: if this was true, then Scala wouldn't allow you to declare vars. The bottom line is that Scala supports both functional and OO, it's a design goal. So saying that i++ is not supported because Scala is functional doesn't make sense. – Cedric Beust Dec 24 '10 at 17:06
  • 2
    And Daniel nails my point: i++ doesn't exist in Scala for a completely different reason. – Cedric Beust Dec 24 '10 at 17:06
  • @DanielC.Sobral Pardon me, but can you try to elaborate it (bit more in simpler terms) To be very frank, I read Rafe Kettler and it sounded right and then I read yours and gone above my head. – manocha_ak Feb 13 '13 at 12:14
  • @manocha_ak Ok, I've written [an answer](http://stackoverflow.com/a/14859565/53013) elaborating upon the ideas I raised in that comment. – Daniel C. Sobral Feb 13 '13 at 17:40
  • To say that Scala is a functional programming language is wrong. Scala is a multi-paradigm language. Quoting Odersky book “Programming in Scala” “Scala is a blend of object-oriented and functional programming concepts in a statically typed language”. I agree that immutability is greatly encouraged in Scala and is a core concept in functional programming, but it would be wrong to say that it is only a functional language. – Onema Nov 24 '18 at 05:51
35

Of course you can have that in Scala, if you really want:

import scalaz._, Scalaz._

case class IncLens[S,N](lens: Lens[S,N], num: Numeric[N]) { 
  def ++ = lens.mods(num.plus(_, num.one))
}

implicit def incLens[S,N: Numeric](lens: Lens[S,N]) =
  IncLens[S,N](lens, implicitly[Numeric[N]])

val i = Lens.lensu[Int,Int]((x, y) => y, identity)

val imperativeProgram = for {
  _ <- i++;
  _ <- i++;
  x <- i++
} yield x

def runProgram = imperativeProgram exec 0

And here you go:

scala> runProgram
res26: scalaz.Id.Id[Int] = 3

No need to resort to violence against variables.

kiritsuku
  • 52,967
  • 18
  • 114
  • 136
Apocalisp
  • 34,834
  • 8
  • 106
  • 155
14

Scala is perfectly capable of parsing i++ and, with a small modification to the language, could be made to modify a variable. But there are a variety of reasons not to.

First, it saves only one character, i++ vs. i+=1, which is not very much savings for adding a new language feature.

Second, the ++ operator is widely used in the collections library, where xs ++ ys takes collection xs and ys and produces a new collection that contains both.

Third, Scala tries to encourage you, without forcing you, to write code in a functional way. i++ is a mutable operation, so it's inconsistent with the idea of Scala to make it especially easy. (Likewise with a language feature that would allow ++ to mutate a variable.)

Rex Kerr
  • 166,841
  • 26
  • 322
  • 407
  • 4
    `i+=1` evaluates `()`, so it's not a direct substitute. `{i+=1;i}` would be. But I agree with the rest of your answer. – retronym Dec 23 '10 at 22:29
  • @retronym - Fair enough. Most of the time the return value of `i++` isn't used. If it is used, then `++i` is probably wanted also. – Rex Kerr Dec 24 '10 at 06:24
  • It depends on programming style really, and on the details of what is being done. Some of us know the difference and use it. :-) – Donal Fellows Dec 24 '10 at 08:27
12

Scala doesn't have a ++ operator because it is not possible to implement one in it.

EDIT: As just pointed out in response to this answer, Scala 2.10.0 can implement an increment operator through use of macros. See this answer for details, and take everything below as being pre-Scala 2.10.0.

Let me elaborate on this, and I'll rely heavily on Java, since it actually suffers from the same problem, but it might be easier for people to understand it if I use a Java example.

To start, it is important to note that one of the goals of Scala is that the "built-in" classes must not have any capability that could not be duplicated by a library. And, of course, in Scala an Int is a class, whereas in Java an int is a primitive -- a type entirely distinct from a class.

So, for Scala to support i++ for i of type Int, I should be able to create my own class MyInt also supporting the same method. This is one of the driving design goals of Scala.

Now, naturally, Java does not support symbols as method names, so let's just call it incr(). Our intent then is to try to create a method incr() such that y.incr() works just like i++.

Here's a first pass at it:

public class Incrementable {
    private int n;

    public Incrementable(int n) {
        this.n = n;
    }

    public void incr() {
        n++;
    }

    @Override
    public String toString() {
        return "Incrementable("+n+")";
    }
}

We can test it with this:

public class DemoIncrementable {
    static public void main(String[] args) {
        Incrementable i = new Incrementable(0);
        System.out.println(i);
        i.incr();
        System.out.println(i);
    }
}

Everything seems to work, too:

Incrementable(0)
Incrementable(1)

And, now, I'll show what the problem is. Let's change our demo program, and make it compare Incrementable to int:

public class DemoIncrementable {
    static public void main(String[] args) {
        Incrementable i = new Incrementable(0);
        Incrementable j = i;
        int k = 0;
        int l = 0;
        System.out.println("i\t\tj\t\tk\tl");
        System.out.println(i+"\t"+j+"\t"+k+"\t"+l);
        i.incr();
        k++;
        System.out.println(i+"\t"+j+"\t"+k+"\t"+l);
    }
}

As we can see in the output, Incrementable and int are behaving differently:

i                   j                       k       l
Incrementable(0)    Incrementable(0)        0       0
Incrementable(1)    Incrementable(1)        1       0

The problem is that we implemented incr() by mutating Incrementable, which is not how primitives work. Incrementable needs to be immutable, which means that incr() must produce a new object. Let's do a naive change:

public Incrementable incr() {
    return new Incrementable(n + 1);
}

However, this doesn't work:

i                   j                       k       l
Incrementable(0)    Incrementable(0)        0       0
Incrementable(0)    Incrementable(0)        1       0

The problem is that, while, incr() created a new object, that new object hasn't been assigned to i. There's no existing mechanism in Java -- or Scala -- that would allow us to implement this method with the exact same semantics as ++.

Now, that doesn't mean it would be impossible for Scala to make such a thing possible. If Scala supported parameter passing by reference (see "call by reference" in this wikipedia article), like C++ does, then we could implement it!

Here's a fictitious implementation, assuming the same by-reference notation as in C++.

implicit def toIncr(Int &n) = {
  def ++ = { val tmp = n; n += 1; tmp }
  def prefix_++ = { n += 1; n }
}

This would either require JVM support or some serious mechanics on the Scala compiler.

In fact, Scala does something similar to what would be needed that when it create closures -- and one of the consequences is that the original Int becomes boxed, with possibly serious performance impact.

For example, consider this method:

  def f(l: List[Int]): Int = {
    var sum = 0
    l foreach { n => sum += n }
    sum
  }

The code being passed to foreach, { n => sum += n }, is not part of this method. The method foreach takes an object of the type Function1 whose apply method implements that little code. That means { n => sum += n } is not only on a different method, it is on a different class altogether! And yet, it can change the value of sum just like a ++ operator would need to.

If we use javap to look at it, we'll see this:

public int f(scala.collection.immutable.List);
  Code:
   0:   new     #7; //class scala/runtime/IntRef
   3:   dup
   4:   iconst_0
   5:   invokespecial   #12; //Method scala/runtime/IntRef."<init>":(I)V
   8:   astore_2
   9:   aload_1
   10:  new     #14; //class tst$$anonfun$f$1
   13:  dup
   14:  aload_0
   15:  aload_2
   16:  invokespecial   #17; //Method tst$$anonfun$f$1."<init>":(Ltst;Lscala/runtime/IntRef;)V
   19:  invokeinterface #23,  2; //InterfaceMethod scala/collection/LinearSeqOptimized.foreach:(Lscala/Function1;)V
   24:  aload_2
   25:  getfield        #27; //Field scala/runtime/IntRef.elem:I
   28:  ireturn

Note that instead of creating an int local variable, it creates an IntRef on the heap (at 0), which is boxing the int. The real int is inside IntRef.elem, as we see on 25. Let's see this same thing implemented with a while loop to make clear the difference:

  def f(l: List[Int]): Int = {
    var sum = 0
    var next = l
    while (next.nonEmpty) {
      sum += next.head
      next = next.tail
    }
    sum
  }

That becomes:

public int f(scala.collection.immutable.List);
  Code:
   0:   iconst_0
   1:   istore_2
   2:   aload_1
   3:   astore_3
   4:   aload_3
   5:   invokeinterface #12,  1; //InterfaceMethod scala/collection/TraversableOnce.nonEmpty:()Z
   10:  ifeq    38
   13:  iload_2
   14:  aload_3
   15:  invokeinterface #18,  1; //InterfaceMethod scala/collection/IterableLike.head:()Ljava/lang/Object;
   20:  invokestatic    #24; //Method scala/runtime/BoxesRunTime.unboxToInt:(Ljava/lang/Object;)I
   23:  iadd
   24:  istore_2
   25:  aload_3
   26:  invokeinterface #29,  1; //InterfaceMethod scala/collection/TraversableLike.tail:()Ljava/lang/Object;
   31:  checkcast       #31; //class scala/collection/immutable/List
   34:  astore_3
   35:  goto    4
   38:  iload_2
   39:  ireturn

No object creation above, no need to get something from the heap.

So, to conclude, Scala would need additional capabilities to support an increment operator that could be defined by the user, as it avoids giving its own built-in classes capabilities not available to external libraries. One such capability is passing parameters by-reference, but JVM does not provide support for it. Scala does something similar to call by-reference, and to do so it uses boxing, which would seriously impact performance (something that would most likely come up with an increment operator!). In the absence of JVM support, therefore, that isn't much likely.

As an additional note, Scala has a distinct functional slant, privileging immutability and referential transparency over mutability and side effects. The sole purpose of call by-reference is to cause side effects on the caller! While doing so can bring performance advantages in a number of situations, it goes very much against the grain of Scala, so I doubt call by-reference will ever be part of it.

Community
  • 1
  • 1
Daniel C. Sobral
  • 295,120
  • 86
  • 501
  • 681
  • As my answers shows, it is in fact possible have a `++` operator in Scala. One can even add it to the existing `Int` type. – Kim Stebel Feb 13 '13 at 20:08
  • Even with call-by-reference as described in the example, "def toIncr(Int &n)...", does it still need the primitive type ? when assign n to tmp, tmp would capture the value then. – Keith Mar 06 '18 at 10:00
9

Other answers have already correctly pointed out that a ++ operator is neither particularly useful nor desirable in a functional programming language. I would like to add that since Scala 2.10, you can add a ++ operator, if you want to. Here is how:

You need an implicit macro that converts ints to instances of something that has a ++ method. The ++ method is "written" by the macro, which has access to the variable (as opposed to its value) on which the ++ method is called. Here is the macro implementation:

trait Incrementer {
  def ++ : Int
}

implicit def withPp(i:Int):Incrementer = macro withPpImpl

def withPpImpl(c:Context)(i:c.Expr[Int]):c.Expr[Incrementer] = {
  import c.universe._
  val id = i.tree
  val f = c.Expr[()=>Unit](Function(
      List(),
      Assign(
          id,
          Apply(
              Select(
                  id,
                  newTermName("$plus")
              ),
              List(
                  Literal(Constant(1))
              )
          )
      )
  ))
  reify(new Incrementer {
    def ++ = {
      val res = i.splice 
      f.splice.apply
      res
    }
  })
}

Now, as long as the implicit conversion macro is in scope, you can write

var i = 0
println(i++) //prints 0
println(i) //prints 1
Kim Stebel
  • 41,826
  • 12
  • 125
  • 142
  • Clever. Although, `def ++` ought to return an Int, specifically the original value of i. – Leif Wickland Feb 13 '13 at 20:42
  • 1
    Nice. It'd suggest updating the sample to do var i = 0; println(i++); /\* Prints 0 \*/ println(i); /\* Prints 1 \*/ To demonstrate that it really is incrementing after evaluating i. – Leif Wickland Feb 13 '13 at 23:18
  • I'm not sure I'd bother with implementing a trait for it. Just replace `i.++` with `{val freshName = i; i += 1; freshName}`. – Daniel C. Sobral Feb 14 '13 at 01:00
  • @DanielC.Sobral: That's really not the point. The point is it can be done. And if you have a better implementation, show it to us! – Kim Stebel Feb 14 '13 at 05:16
  • 1
    @LeifWickland: Changed the example as well, but it should be clear from the lines `val res = i.splice; f.splice.apply; res`, that it saves the old value, increments the `var` and returns the old value. – Kim Stebel Feb 14 '13 at 05:19
  • @KimStebel My idea is using the implicit conversion to actually _replace_ `i++` with an equivalent block. I've dabbled at it yesterday, but I wasn't feeling particularly well so I gave up. :-) – Daniel C. Sobral Feb 14 '13 at 15:01
  • @DanielC.Sobral: I'm not sure how that would work. What would be the signature of the conversion function? – Kim Stebel Feb 14 '13 at 17:11
  • 1
    @KimStebel I *so* wish I could come up with the time for it... :-( The signature for the conversion signature is the same. The trick here is that the macro implementation can return something completely different than the return type declared for the function that calls the macro, so you can declare to return an `Incrementer`, thereby getting the implicit conversion to be called, and then go ahead and do no such thing and, instead, replace it with a block doing the right thing. – Daniel C. Sobral Feb 22 '13 at 05:32
  • @DanielC.Sobral: "go ahead and do no such thing"? Do you have any example of that? I don't think this is possible, at least not with Scala 2.10.0. – Kim Stebel Feb 22 '13 at 11:03
7

Rafe's answer is true about the rationale for why something like i++ doesn't belong in Scala. However I have one nitpick. It's actually not possible to implement i++ in Scala without changing the language.

In Scala, ++ is a valid method, and no method implies assignment. Only = can do that.

Languages like C++ and Java treat ++ specially to mean both increment and assign. Scala treats = specially, and in an inconsistent way.

In Scala when you write i += 1 the compiler first looks for a method called += on the Int. It's not there so next it does it's magic on = and tries to compile the line as if it read i = i + 1. If you write i++ then Scala will call the method ++ on i and assign the result to... nothing. Because only = means assignment. You could write i ++= 1 but that kind of defeats the purpose.

The fact that Scala supports method names like += is already controversial and some people think it's operator overloading. They could have added special behavior for ++ but then it would no longer be a valid method name (like =) and it would be one more thing to remember.

Craig P. Motlin
  • 26,452
  • 17
  • 99
  • 126
  • In which way is it inconsistent and what would be a better alternative? Imho the current solution is better than allowing two separate method implementations for `+=` and `+`. Would you consider the `update` and `apply` methods "inconsistent too? – soc Dec 23 '10 at 18:09
  • apply(), unapply(), update(), etc. are certainly exceptional in that they have dedicated syntax. However, I'm just talking about the consistency of language rules around assignment. In Scala, the = operator does assignment and any operators that end in = might do assignment. In other languages =, ++, and -- do assignment. – Craig P. Motlin Dec 23 '10 at 18:37
  • Also, I'm not suggesting any alternative. I think these language design choices are all fine. If Scala allowed assignment through more operators, it would be more confusing. – Craig P. Motlin Dec 23 '10 at 18:38
2

Quite a few languages do not support the ++ notation, such as Lua. In languages in which it is supported, it is frequently a source of confusion and bugs, so it's quality as a language feature is dubious, and compared to the alternative of i += 1 or even just i = i + 1, the saving of such minor characters is fairly pointless.

This is not at all relevant to the type system of the language. While it's true that most static type languages do offer and most dynamic types don't, that's a correlation and definitely not a cause.

Puppy
  • 144,682
  • 38
  • 256
  • 465
  • 1
    Post-increment is an expression giving lvalue. So that `i++` will return a current value of `i` and then increment it. It is not equivalent of `i = i + 1` or `i += 1` at all. There are lots of things that programmers may misuse if they don't know what it is. But this is not a good reason to remove these things from the language. –  Dec 23 '10 at 16:20
  • @Vlad: If you can't substitute with `i+=1` or `i=i+1`, then you are almost certainly misusing it. I mean, programmers in the know don't make this kind of mistake (didn't mean you personally, but in general), but it's very easy to trip up and fundamentally provides no real benefits. – Puppy Dec 23 '10 at 16:24
  • Yeah, you right. One can live without post increment. Also, I hate when people abusing it, i.e. in for loops like `for (int i = 0; i < 100; i++)`. –  Dec 23 '10 at 16:26
  • @Vlad: Which is perfectly substitutable with `i+=1` or `i=i+1` – Puppy Dec 23 '10 at 17:03
  • DeadMG: True, except if your identifier is over 30 chars! (OK, extreme, but not all variables are one char either). += is a good middle measure (not in Lua either). @Vlad: increment wasn't "removed" from Scala, it was just not added... And I don't see how i++ in for loops is abusing the notation. At least, it is a firmly ingrained idiom... – PhiLho Jan 02 '12 at 11:20
2

Scala encourages using of FP style, which i++ certainly is not.

fehu
  • 457
  • 2
  • 8
1

The question to ask is why there should be such an operator, not why there shouldn't be. Would Scala be improved by it?

The ++ operator is single-purpose, and having an operator that can change the value of a variable can cause problems. It's easy to write confusing expressions, and even if the language defines what i = i + i++ means, for example, that's a lot of detailed rules to remember.

Your reasoning on Python and Ruby is wrong, by the way. In Perl, you can write $i++ or ++$i just fine. If $i turns out to be something that can't be incremented, you get a run-time error. It isn't in Python or Ruby because the language designers didn't think it was a good idea, not because they're dynamically typed like Perl.

David Thornley
  • 56,304
  • 9
  • 91
  • 158
0

You could simulate it, though. As a trivial example:

scala> case class IncInt(var self: Int = 0) { def ++ { self += 1 } }
defined class IncInt

scala> val i = IncInt()
i: IncInt = IncInt(0)

scala> i++

scala> i++

scala> i
res28: IncInt = IncInt(2)

Add some implicit conversions and you're good to go. However, this sort of changes the question into: why isn't there a mutable RichInt with this functionality?

Knut Arne Vedaa
  • 15,372
  • 11
  • 48
  • 59
0

As another answer suggests, the increment operator, as found in i++, was—

supposedly ... added to the B language [a predecessor of the C language] by Ken Thompson specifically because [it was] capable of translating directly to a single opcode once compiled

and not necessarily because such an operator is as useful to have as, say, general addition and subtraction. Although certain object-oriented languages (such as Java and C#) also have an increment operator (often borrowed from C), not all do (such as Ruby).

Peter O.
  • 32,158
  • 14
  • 82
  • 96