2

I am new to Scala, and I hope this question is not too basic. I couldn't find the answer to this question on the web (which might be because I don't know the relevant keywords).

I am trying to understand the following definition:

def functionName[T <: AnyRef](name: Symbol)(range: String*)(f: T => String)(implicit tag: ClassTag[T]): DiscreteAttribute[T] = {
    val r = .... 
    new anotherFunctionName[T](name.toString, f, Some(r))
  }
  • First , why is it defined as def functionName[...](...)(...)(...)(...)? Can't we define it as def functionName[...](..., ..., ..., ...)?
  • Second, how does range: String* from range: String?
  • Third, would it be a problem if implicit tag: ClassTag[T] did not exist?
Daniel
  • 5,839
  • 9
  • 46
  • 85
  • 1
    Please, if you have three questions, ask three questions, not one. That way, each question gets its own answer and the answers can be up- and downvoted independently. How would you judge the quality of an answer that gives an outstanding answer to one question but crappy ones for the other two? In your case, however, at least the first two questions would be immediately closed as duplicates because they have already been asked and answered many times before on StackOverflow (which the automatic duplicate detection algorithm might have told you if you hadn't mixed them up with other questions.) – Jörg W Mittag Aug 16 '15 at 07:40

3 Answers3

4

First , why is it defined as def functionName...(...)(...)(...)? Can't we define it as def functionName[...](..., ..., ..., ...)?

One good reason to use currying is to support type inference. Consider these two functions:

def pred1[A](x: A, f: A => Boolean): Boolean = f(x)
def pred2[A](x: A)(f: A => Boolean): Boolean = f(x)

Since type information flows from left to right if you try to call pred1 like this:

pred1(1, x => x > 0)

type of the x => x > 0 cannot be determined yet and you'll get an error:

<console>:22: error: missing parameter type
              pred1(1, x => x > 0)
                       ^

To make it work you have to specify argument type of the anonymous function:

pred1(1, (x: Int) => x > 0)

pred2 from the other hand can be used without specifying argument type:

pred2(1)(x => x > 0)

or simply:

pred2(1)(_ > 0)

Second, how does range: String* from range: String?

It is a syntax for defining Repeated Parameters a.k.a varargs. Ignoring other differences it can be used only on the last position and is available as a scala.Seq (here scala.Seq[String]). Typical usage is apply method of the collections types which allows for syntax like SomeDummyCollection(1, 2, 3). For more see:

Third, would it be a problem if implicit tag: ClassTag[T] did not exist?

As already stated by Aivean it shouldn't be the case here. ClassTags are automatically generated by the compiler and should be accessible as long as the class exists. In general case if implicit argument cannot be accessed you'll get an error:

scala> import scala.concurrent._
import scala.concurrent._

scala> val answer: Future[Int] = Future(42)
<console>:13: error: Cannot find an implicit ExecutionContext. You might     pass
an (implicit ec: ExecutionContext) parameter to your method
or import scala.concurrent.ExecutionContext.Implicits.global.
       val answer: Future[Int] = Future(42)
Community
  • 1
  • 1
zero323
  • 322,348
  • 103
  • 959
  • 935
2
  • Multiple argument lists: this is called "currying", and enables you to call a function with only some of the arguments, yielding a function that takes the rest of the arguments and produces the result type (partial function application). Here is a link to Scala documentation that gives an example of using this. Further, any implicit arguments to a function must be specified together in one argument list, coming after any other argument lists. While defining functions this way is not necessary (apart from any implicit arguments), this style of function definition can sometimes make it clearer how the function is expected to be used, and/or make the syntax for partial application look more natural (f(x) rather than f(x, _)).

  • Arguments with an asterisk: "varargs". This syntax denotes that rather than a single argument being expected, a variable number of arguments can be passed in, which will be handled as (in this case) a Seq[String]. It is the equivalent of specifying (String... range) in Java.

  • the implicit ClassTag: this is often needed to ensure proper typing of the function result, where the type (T here) cannot be determined at compile time. Since Scala runs on the JVM, which does not retain type information beyond compile time, this is a work-around used in Scala to ensure information about the type(s) involved is still available at runtime.

Shadowlands
  • 14,994
  • 4
  • 45
  • 43
2
  1. Check currying:
    Methods may define multiple parameter lists. When a method is called with a fewer number of parameter lists, then this will yield a function taking the missing parameter lists as its arguments.
  2. range:String* is the syntax for varargs
  3. implicit TypeTag parameter in Scala is the alternative for Class<T> clazzparameter in Java. It will be always available if your class is defined in scope. Read more about type tags.
Aivean
  • 10,692
  • 25
  • 39
  • Two problems with (1). First, currying is defined for a single argument, so I wouldn't call it currying if we stick with currying definition. Second, no, when you call it with a fewer number of parameter lists you will get a compiler error (unless eta-expansion is in effect). Just to be accurate. – Victor Moroz Aug 16 '15 at 00:38
  • `varagra` is the blue pill that makes us feel young. – som-snytt Aug 16 '15 at 01:07