Using Implicit Objects In Early Initializers, Impossible?

125 views
Skip to first unread message

Kevin Yancey

unread,
Aug 12, 2013, 9:36:12 PM8/12/13
to scala...@googlegroups.com
I have a class that has an early initializer and has a type bound implicit parameter passed into its constructor.  However, whenever I try to access the implicit object, I get compiler errors.  I've tried it two different ways, and I get different errors ecah time.

The first way:

class Summation[T : Summable](baseValue : Signal[T]) extends {

  private val _baseSignal = new Mutable[T, T](Val(implicitly[Summable[T]].zero), implicitly[Summable[T]].sum(_, _))

} with WrappedSignal[T](_baseSignal) {

  def +=(value : Signal[T]) = _baseSignal.applyMutator(value)

}


I get an error on line two that it "could not find the implicit value for argument e/not enough arguments for method implicitly".


On the second way:

class Summation[T](baseValue : Signal[T]) (implicit summable : Summable[T]) extends {

  private val _baseSignal = new Mutable[T, T](Val(summable.zero), summable.sum(_, _))

} with WrappedSignal[T](_baseSignal) {

  def +=(value : Signal[T]) = _baseSignal.applyMutator(value)

}


I get the compile error "implicit modifier cannot be used for top-level objects" on the first line.  If I remove the reference to summable in the early initializer, then the compile error goes away, although this makes it impossible to pass the signal into the base class constructor.


Is this a compile bug, or is it an intentional restriction that implicit parameters cannot be used inside early initializers?  I can't think of a logical reason this would be invalid, except for perhaps some practical limitation of the implementation of implicits by the compiler.

Kevin Yancey

unread,
Aug 12, 2013, 9:40:59 PM8/12/13
to scala...@googlegroups.com
Also, I'm using Scala 2.10.2 with the latest stable Scala IDE.

Jason Zaugg

unread,
Aug 13, 2013, 2:20:31 AM8/13/13
to Kevin Yancey, scala-user
This is a variation of SI-3439 [1].

I've added your examples to that ticket.

Here are workarounds:

class Summable[T]

// workaround 1: wrap in an object
object Wrapper {
  class Test()(implicit summable : Summable[Any]) extends {
    private val _baseSignal = new { val o = summable}
  } with Object
}

// workaround 2: make the parameter explicit and create an
//               factory method in the companion with it implicit
class Test1 private()(summable : Summable[Any]) extends {
  private val _baseSignal = new { val o = summable}
} with Object

object Test1 {
  def apply()(implicit summable: Summable[Any]) = new Test1()(summable)
}

-jason



On Tue, Aug 13, 2013 at 3:40 AM, Kevin Yancey <kpya...@gmail.com> wrote:
Also, I'm using Scala 2.10.2 with the latest stable Scala IDE.

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Kevin Yancey

unread,
Aug 13, 2013, 11:07:59 AM8/13/13
to scala...@googlegroups.com, Kevin Yancey
Thank you!

I also came up with another workaround using auxiliary constructors:

class Promotable[T] private(baseValue : Signal[T], ordering : Ordering[T]) extends {

  private val _baseSignal = new Mutable[T, T](baseValue, ordering.max(_, _))

} with WrappedSignal(_baseSignal) {

  //Workaround for SI-3439 - https://issues.scala-lang.org/browse/SI-3439

  def this(baseValue : Signal[T]) (implicit ordering : Ordering[T]) = this(baseValue, ordering)

  def promoteTo(value : Signal[T]) = _baseSignal.applyMutator(value)

}

Kevin Yancey

unread,
Aug 13, 2013, 11:23:15 AM8/13/13
to scala...@googlegroups.com, Kevin Yancey
Hmm...strangely, my workaround doesn't seem to work.  It seemed to compile initiallly, but now I'm getting an error that the signature of the two constructors are identical after erasure.

I guess I'll use one of the other workarounds, then.  Oh well.

Jason Zaugg

unread,
Aug 13, 2013, 11:26:15 AM8/13/13
to Kevin Yancey, scala-user
You could add a dummy parameter to the private constructor.


On Tue, Aug 13, 2013 at 5:23 PM, Kevin Yancey <kpya...@gmail.com> wrote:
Hmm...strangely, my workaround doesn't seem to work.  It seemed to compile initiallly, but now I'm getting an error that the signature of the two constructors are identical after erasure.

I guess I'll use one of the other workarounds, then.  Oh well.

--
Reply all
Reply to author
Forward
0 new messages