Scala/Processing Gotchas

Here’s a list of gotchas and ways to work around them related to Scala and/or Processing:

public void mousePressed() and boolean mousePressed are the same!

override def mousePressed() {
   //handle on mouse pressed event here
}

override def draw() {
   ...
   if(mousePressed) { //Won't compile! Scala thinks you're typing "if(mousePressed()) {"
      //mouse being held down
   }
}

Solution: Add a “:Boolean” when referring to the boolean

   if((mousePressed:Boolean)) { //Tell the compiler to treat mousePressed as a Boolean

As soon as you override mousePressed or keyPressed in your applet, the boolean variable mousePressed/keyPressed can’t be referred to anymore, since Scala thinks you’re talking about the method you just wrote. This isn’t a problem in Java since all method calls have a parentheses syntax. In general, you can ask the compiler to treat a value as a type T by putting “:T” after the value (e.g. var k = 12:AnyVal will create k as an AnyVal). You can even use this syntax to coerce things into implicit conversion types:

implicit def s2i(s:String) = s.length
val k = "abc":Int //k = 3
List(1,2,3) :+ List(4,5,6) creates List[Any]

scala> List(1,2,3) :+ List(4,5,6)
res5: List[Any] = List(1, 2, 3, List(4, 5, 6)) //Not what you were expecting, eh?

Solution: Use ++ instead of :+

scala> List(1,2,3) ++ List(4,5,6)
res6: List[Int] = List(1, 2, 3, 4, 5, 6)

List’s :+ method will accept ANY argument you give it and produce a new List whose type is the parent of both the argument and the type that the List is holding. In this case, we had a List[Int] and we were tying to append another List[Int] using :+, which treats the argument as a single item to append. So, List is holding type Int and we’re appending a List[Int] – their first shared parent is Any.

List(1,2,3) + List(4,5,6) gives error: type mismatch

scala> List(1,2,3) + List(4,5,6)
:8: error: type mismatch;
 found   : List[Int]
 required: String
       List(1,2,3) + List(4,5,6)

Solution: Use ++ instead of +

scala> List(1,2,3) ++ List(4,5,6)
res4: List[Int] = List(1, 2, 3, 4, 5, 6)

List doesn’t have a “+” method; instead, it has :+ for append and +: for prepend. But the error message talks as if there IS some method, and further that it wants a String, of all things? As it turns out, the Predef object (which is silently inserted in every Scala program) defines an implicit conversion any2StringAdd – this StringAdd object has a “+” method. This exists because Scala tries to provide the features Java has; in this case we are getting the + syntax with Strings that Java has, such as System.out.println(12345+” hello!”);. Since List doesn’t have a “+” method, the implicit takes place and assumes you’re trying to concatenate List(1,2,3)’s toString to another String. But it’s instead passed a List(4,5,6), creating the type mismatch error.

Stackable PApplet trait with abstract override def draw() stops the sketch

trait MyPAppletTrait extends PApplet { //I want a stackable PApplet trait 
   abstract override def draw() {
      super.draw(); //Call other trait's draws to keep stackability alive
      ...
   }
}

class MySketch extends MyPAppletTrait {
   override def draw() {
      super.draw(); //do the stuff that MyPAppletTrait does
   }
}

If this is your code, the sketch will one exactly once and then everything will stop.

Solution: Don’t call super.draw() in MyPAppletTrait, or MySketch, or create another trait T2 whose draw method doesn’t call super.draw() and have MySketch extend T with MyPAppletTrait as a mixin.

abstract override def draw() { //in MyPAppletTrait
   //just don't call super.draw(); unfortunately, this breaks stackability unless the trait is at the top of the mixin chain.
}

—or—

override def draw() { //In MySketch
   //don't call super.draw(), which sadly also means the code in MyPAppletTrait won't get run.
}

—or—

trait DrawBlocker extends PApplet { //can also be a class
    abstract override def draw() {} //Do nothing. Don't call super
}
class MySketch extends DrawBlocker with MyPAppletTrait { //this will work

PApplet’s default implementation of draw() is to turn the sketch off; this is discussed in this blog post.

Other Scala gotchas

More to come :)



Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s