Reputation: 1028
Scala: why is a type used as a method call?
I'm new to Scala and I'm reading "Functional Programming in Scala" by PAUL CHIUSANO and RÚNAR BJARNASON.
I'm trying to understand the source code of parser combinator in Chapter 9, but I'm stuck by a
problem: in the source code, Parser[A]
is declared as a type, but I can see that instances of
Parser[A]
is used as a method call.
My question is: why instance of a type can be used as a method call?
def or[A](p: Parser[A], p2: => Parser[A]): Parser[A] =
s => p(s) match { // ========> p is used as a method call.
case Failure(e,false) => p2(s)
case r => r // committed failure or success skips running `p2`
}
Link to the source code:
https://github.com/fpinscala/fpinscala/blob/master/answers/src/main/scala/fpinscala/parsing
Code snippet:
trait Parsers[Parser[+_]] { self =>
.....
}
object ReferenceTypes {
/** A parser is a kind of state action that can fail. */
type Parser[+A] = ParseState => Result[A]
case class ParseState(loc: Location) {
......
}
sealed trait Result[+A] {
......
}
case class Success[+A](get: A, length: Int) extends Result[A]
case class Failure(get: ParseError, isCommitted: Boolean) extends Result[Nothing]
}
object Reference extends Parsers[Parser] {
......
def or[A](p: Parser[A], p2: => Parser[A]): Parser[A] =
s => p(s) match {
case Failure(e,false) => p2(s)
case r => r // committed failure or success skips running `p2`
}
.....
}
Upvotes: 2
Views: 94
Reputation: 44918
In the code you quoted, Parser[+A]
is explicitly declared as function type
type Parser[+A] = ParseState => Result[A]
Therefore, values of type Parser[+A]
can be applied to values of type ParseState
. The usual syntax for applying a function p
of type X => Y
to a value s
of type X
is
p(s)
So, it's just usual function application, it's not even some fancy overriden apply
method of some user-defined class.
A method call usually looks as follows:
obj.methodName(argument)
it requires an object on which the method is called. This can be omitted if the object is this
, or if you have previously imported
import obj._
so that all methods of this object are available in the current scope. In all other cases, you need a receiving object on which you invoke a method.
The function application
p(s)
actually desugars into a special method call
p.apply(s)
but that's an aside, it's not really relevant for the question.
Upvotes: 2