3

I have a few questions about scala generics and default parameter values.

Suppose, I have the following class definition (where Stack[E] is a trait)

class ImmutableStack[E](capacity: Int = 10, elems: Array[E] = new Array[E](capacity))(implicit ev: ClassTag[E]) extends Stack[E]

When I try to compile that code it gives two errors:

scala: cannot find class tag for element type E
class ImmutableStack[E <: Any](capacity: Int = 10, elems: Array[E] = new Array[E](capacity))(implicit ev: ClassTag[E]) extends SedgewickStack[E] {
                                                                 ^

And:

scala: not found: value capacity
class ImmutableStack[E <: Any](capacity: Int = 10, elems: Array[E] = new Array[E](capacity))(implicit ev: ClassTag[E]) extends SedgewickStack[E] {
                                                                                  ^

Could someone explain me:

  1. Why capacity parameter is not available for other parameters in constructor definition?
  2. Why ClassTag ev is not available for default parameter value i.e. new Array[E](capacity)?

When I remove default value for elem parameter - everything works fine.

Thanks in advance for any answer.

4
  • 2
    It might not be a full answer but: I don't think capacity is actually in scope inside the constructor declaration. For that matter, I don't know wether any language allows cross-referencing constructor or function parameters; you can only access them in the body. Commented Sep 17, 2013 at 8:08
  • 3
    @ViktorSeifert: reference to capacity is not a problem. You just should move it to additional parameters group. This works fine def test(a: Int)(b: Int = a) = a + b; test(1)(). But you can't access parameter from next group (ev). Commented Sep 17, 2013 at 8:15
  • @senia Does this work for constructors? Commented Sep 17, 2013 at 8:25
  • 2
    @ViktorSeifert: You can just try it: class Test(a: Int)(b: Int = a) { val c = a + b }; new Test(1)().c works fine. In other case you could use a factory method. Commented Sep 17, 2013 at 8:40

1 Answer 1

1

You can only use values from previous argument lists for default values in constructors and methods, not from the same one:

class ImmutableStack[E <: Any](capacity: Int = 10)(elems: Array[E] = new Array[E](capacity))(implicit ev: ClassTag[E])

To work around inability to use implicit class tag, the best I can offer is

class ImmutableStack[E <: Any : ClassTag](capacity: Int = 10)(elems: Array[E] = null) {
  val realElems = if (elems != null) elems else new Array[E](capacity)
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the tip. I have also used the same approach with default value for elems param. But am I right that inability to construct an array with generic type parameter as default parameter value is dictated by the fact that implicit ClassTag is supplied only as the last argument list and not available in the previous argument lists?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.