CodingNow
CodingNow

Reputation: 1028

Scala: why is a type used as a method call?

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

Answers (1)

Andrey Tyukin
Andrey Tyukin

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

Related Questions