Dennis V.
Dennis V.

Reputation: 120

Unexplainable Scala compiler error

I'm creating a OData query language in Scala. It's going pretty well, but there is one error I get which I can't explain.

First let me show you the Query class I created (omitted some code out for brevity):

case class Query(val name: String, val args: Seq[(String, String)] = Seq())
                (val parent: Option[Query] = None)
                (val options: Seq[QueryOption] = Seq()) {

  def /(newChild: Query): Query = new Query(newChild.name, newChild.args)(Some(this))(options)

  def $(newOptions: QueryOption*): Query = new Query(name, args)(parent)(options ++ newOptions)

  def |(newArgs: (String, String)*): Query = new Query(name, args ++ newArgs)(parent)(options)
}


object Query {

  private def emptyQueryWithName(name: String): Query = Query(name, Seq())(None)(Seq())

  def /(name: String): Query = emptyQueryWithName(name)

  implicit def createQuery(name: String): Query = emptyQueryWithName(name)
}

package object queries {

  implicit class QueryOps(name: String) {

    def ===(attr: Any): (String, String) = (name, attr.toString)
  }
}

I've written some tests for this DSL and they work mostly. For instance this code:

Query / "Pages" / "Component" | ("ItemId" === 123, "PublicationId" === 1) $ ("Title" ==| "Test Title") 

Gives me the expected query: /Pages/Component(ItemId=123,PublicationId=1)?$filter=Title eq 'Test Title'

But this one:

Query / "Pages" | ("ItemId" === 123) / "Title" $ jsonFormat $ ("Url" ==| "Bla")

Complains about the '/ "Title"' part. As if the compiler is not aware that the proceeding code results in a Query instance. It can't find the '/' method. To me this seems very strange as the '$' method is found, which has the same scope; the Query class.

I'm probably running into some kind of limitation I can't fathom, but I would like to understand. Thanks for any help!

Upvotes: 0

Views: 75

Answers (1)

Mario Camou
Mario Camou

Reputation: 2353

The fact that parentheses fix the problem usually means an operator precedence problem. Have a look at http://books.google.es/books?id=MFjNhTjeQKkC&pg=PA90&lpg=PA90&dq=scala+operator+precedence+reference&source=bl&ots=FMlkUEDSpq&sig=pf3szEM4GExN_UCsgaxcQNBegPQ&hl=en&sa=X&ei=ZezQU_-SDszY7Ab-pIDQDQ&redir_esc=y#v=onepage&q=scala%20operator%20precedence%20reference&f=false

| has a lower precedence than /, and $ has the highest precedence, so your expression is being interpreted as:

(Query / "Pages") | (("ItemId" === 123) / (("Title" $ jsonFormat) $ ("Url" ==| "Bla")))

Also, providing the exact error message is usually useful.

Upvotes: 2

Related Questions