Question

Given the following Scala code:

val buffer = new scala.collection.mutable.ArrayBuffer[Function0[Boolean]]
def foo(): Boolean = { println("foo"); false }
def bar(): Boolean = { println("bar"); true }

buffer += foo
buffer += bar

I've added two functions to my buffer. Now, how do I remove one?

buffer -= foo doesn't work because foo is evaluated to a boolean before any comparisons.

Was it helpful?

Solution

You misunderstand the reason why your current code is not working. Removing objects in this way relies on the == operator, which for functions is defined using the object identity only. This means that you must ensure that you have a stable value for the function that you are adding if you want to remove it again. You are currently using anonymous function literals ('boxed' from the method references), which cannot be recreated.

In other words, buffer += foo is equivalent to buffer += (foo _), and foo _ will give you a different function object each time. Try this:

buffer += foo
buffer += foo
buffer.map(System.identityHashCode(_))
res4: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(944601779, 1722981029)

Oops, two different objects, we were expecting to have two references to the same one.

Now try

val fooRef:Function0[Boolean] = foo // or val fooRef = foo _
buffer += fooRef
buffer += fooRef
buffer.map(System.identityHashCode(_))
res8: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1732011089, 1732011089)

Ah, that's better! buffer -= fooRef will now work as expected.

OTHER TIPS

You can define foo and bar as function literals:

scala>  val buffer = collection.mutable.ArrayBuffer.empty[Function0[Boolean]]
buffer: scala.collection.mutable.ArrayBuffer[() => Boolean] = ArrayBuffer()

scala>  val foo = () => { println("foo"); false }
foo: () => Boolean = <function0>

scala>  val bar = () => { println("bar"); true }
bar: () => Boolean = <function0>

scala>  buffer += foo
res0: buffer.type = ArrayBuffer(<function0>)

scala>  buffer += bar
res1: buffer.type = ArrayBuffer(<function0>, <function0>)

scala>  buffer -= foo
res2: buffer.type = ArrayBuffer(<function0>)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top