5

I've already read that the if statement in scala always returns an expression

So I'm trying to do the following (pseudo code)

sql = "select * from xx" + iif(order.isDefined, "order by " order.get, "")

I'm trying with

val sql: String = "select * from xx" + if (order.isDefined) {" order by " + order.get} else {""} 

But I get this error:

illegal start of simple expression

order is an Option[String]

I just want to have an optional parameter to a method, and if that parameter (in this case order) is not passed then just skip it

what would be the most idiomatic way to achieve what I'm trying to do?

-- edit --

I guess I hurried up too much to ask

I found this way,

val orderBy = order.map( " order by " + _ ).getOrElse("")

Is this the right way to do it?

I thought map was meant for other purposes...

opensas
  • 60,462
  • 79
  • 252
  • 386
  • 2
    The reason your code isn't compiling is because you need parentheses around the `if` expression. But as Tomasz Nurkiewicz points out, there are better ways to write this anyway. – Tom Crockett Apr 01 '12 at 21:54
  • 1
    Anyone want to comment on *why* we need brackets around the if-expression (other than "because it compiles")? – Luigi Plinge Apr 01 '12 at 22:00
  • 1
    @LuigiPlinge this is just speculation, but it may be that they wanted to avoid programmer confusion as to how an expression like `1 + if (b) 2 else 3 + 4` would associate. Is it `1 + (if (b) 2 else 3) + 4` or `1 + (if (b) 2 else 3 + 4)`? Certainly you could have a grammar which resolves this ambiguity (Haskell does), but that doesn't mean people wouldn't make mistakes because they assumed a different behavior. – Tom Crockett Apr 01 '12 at 22:31

2 Answers2

11

First of all you are not using Option[T] idiomatically, try this:

"select * from xx" + order.map(" order by " + _).getOrElse("")

or with different syntax:

"select * from xx" + (order map {" order by " + _} getOrElse "")

Which is roughly equivalent to:

"select * from xx" + order match {
  case Some(o) => " order by " + o
  case None => ""
}

Have a look at scala.Option Cheat Sheet. But if you really want to go the ugly way of ifs (missing parentheses around if):

"select * from xx" + (if(order.isDefined) {" order by " + order.get} else {""})
Tomasz Nurkiewicz
  • 334,321
  • 69
  • 703
  • 674
  • Thanks a lot, Tomasz, I just found it on google... And yes, I'm trying to learn the most idiomatic way to work with Scala... – opensas Apr 01 '12 at 21:52
0

...or, if you really want to impress your friends:

order.foldLeft ("") ((_,b)=>"order by  " + b)

(I would still recommend Tomasz's answer, but I think this one is not included in the scala.Option cheat sheet, so i thought I'd mention it)

Paolo Falabella
  • 24,914
  • 3
  • 72
  • 86
  • 1
    If you're gonna fold, why not use the prefix as the initial value, and do the whole thing in one go? `val sql = order.foldLeft("select * from xx")((_,b)=>" order by " + b) ` – Andrzej Doyle Apr 23 '12 at 10:13
  • @AndrzejDoyle you're right, that's a way to do it... I was imagining this to be part of a larger dynamically constructed query where you have a function that builds only the "order by" part, another one that builds the "where" clauses and you put them all together at the end – Paolo Falabella Apr 23 '12 at 10:50