This page is no longer maintained — Please continue to the home page at www.scala-lang.org

A Taste of 2.8: Named and Default Arguments

Scala 2.8 offers the possibility to call methods using "named arguments", which means specifying the arguments based on the parameter names (instead of the parameter positions). Named arguments help to avoid confusing parameters of the same type and improve code readability.

  

def resize(width: Int, height: Int) = { ... }
resize(width = 120, height = 42)

 

Furthermore, Scala 2.8 allows providing default arguments on method parameters. In current versions of Scala, default arguments have to be implemented manually using method overloading. This causes some level of code duplication which can be avoided using default arguments.

 

def f(elems: List[Int], x: Int = 0, cond: Boolean = true)
f(List(1))
f(Nil, cond = false)

The example also shows how named arguments allow to selectively use defaults of a method: the second application to f uses the default for x, but not the one for cond.

 

Compiler-generated copy methods

One very useful application of named and default arguments are the compiler-generated "copy" methods in case classes, which allow to create modified copies of an instance using a lightweight syntax. The copy method takes the same type and value parameters as the primary constructor of the case class, and every parameter defaults to the corresponding constructor parameter:

case class A[T](a: T, b: Int) {
// def copy[T'](a: T' = this.a, b: Int = this.b): A[T'] = new A[T'](a, b)
}
val a1: A[Int] = A(1, 2)
val a2: A[String] = a1.copy(a = "someString")

 

Download a recent nightly build (linux-mac / windows) to try out named and default arguments yourself! To read more about named and default arguments, have a look at the corresponding SID.

Re: A Taste of 2.8: Named and Default Arguments

It would be nice if there was some mentioning of nested-annotations in 2.8 as a result of this as I understand named argument is a prerequisite for it to work.

Re: A Taste of 2.8: Named and Default Arguments

Right, nested java annotations are supported in Scala 2.8:

@OuterAnnotation(value = 1,
                 nestedAnnot = new NestedAnnotation(2))

 

Compatibility/recompilations

I wonder how it is implemented behind the scenes.

 

Let's imagine I got third party library LIB and my application APP (3rd party library in scala! let's suspend disbelief for a moment ;)

1) Assuming I don't have sources for LIB, will I get benefits of default values ? Named parameters ?

2) Let's imagine one of the methods in LIB, compute(param: Something). I compile APP against this version of LIB. Now, new version of LIB appears, when they want to add optional parameter to the compute method, to add progress listener, compute(param:Something, listener:ProgressListener = MockListener) (with MockListener being a no-op singleton default). Obviously, if I recompile APP against new LIB sources, everything will work correctly (I don't want to use ProgressListener in APP). But what will happen if

  a) I will just run same APP jar with new LIB jar ? Will default parameter be added automatically ?

  b) if a) is not working, is it enough to recompile APP versus binary LIB (probably same answer as point 1 above)

 

3) If I have method add(x:Int, y:Int = 0) in LIB and compile APP against it, then have new version of LIB which changes definition to add(x:Int, y:Int = x+1), will I get it working by

  a) just dropping in new binary version of LIB ?

  b) recompiling APP versus binary version of LIB ?

 

 

Re: Compatibility/recompilations

  1. Yes, you will. The information required to use named parameters and default values are compiled into .class files. In fact, this is one major reason why Scala 2.8 .class files are incompatible with those of 2.7 (the other being the new collection library).
  2. You need to recompile APP against the new LIB. The rules are the same than those of source-compatible parameter type changes in APIs. You can think of parameter names becoming part of the public API of a class.
  3. That would be (a): a default parameter is provided by a magic static method in the LIB class. If you decompile a class (using scalap) that contains default parameters, you'll see the "default" methods.

Re: Compatibility/recompilations

Point 2 is bit disappointing - for me, one of the possible uses of default parameters was library evolution. It seems that in this case, for method parameter extension, it will be needed to fall back to normal java-like overloading of methods and have two methods implemented, one calling another with 'default' parameter.

 

Re: A Taste of 2.8: Named and Default Arguments

Do Scala autors consider adding some annotation (i'll name it here @GernerateWithDefaults) that would do following? It can be applied to a class C whose contructor contain N arguments, M of which has default values (M > 0). If applied compiler generates M additional contructors all with different number of arguments (N-M ... N-1). Each of these constructors can have following implementation: def apply(v1: T1, ... vk: Tk) = C(v1, ... vk).

 

The purpose is to make way to define a classes that would be friendly both to Scala codes and to Java frameworks. Because some frameworks need a class to have no-arguments constructor. This will also make Scala and Java code contructing instance of Scala class with default arguments look pritty the same. Example:

 

@GenerateWithDefaults

case class NamedObject(@BeanProperty var name: String = null);

 

generated class file would contain two contructors:

NamedObject(String name);

NamedObject();

Re: A Taste of 2.8: Named and Default Arguments

We don't have any plans to make default arguments interoperable with Java. The transfromation you describe could probably be implemented as a compiler plugin.

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland