# A safer way to cut a string

I want to get just the first line of a big string. Currently, here's how I do it:

def getFirstParagraph(txt: String) = {
val newLineIdx = txt.indexOf("\n") match {
case i: Int if i > 0 => i
case _               => txt.length
}

txt.substring(0, newLineIdx)
}


But my friend sees some downfall: if txt is null, there will be an exception. His suggestion involved using var:

def getFirstParagraph(txt: String) = {
var result = txt
scala.util.control.Exception.ignoring(classOf[Exception]) {
result = result.substring(0, result.indexOf("\n"))
}
result
}


Which will handle the null value fine. Thing is, I'm quite uncomfortable using var. How can I handle this case without using var (aka the Scala / functional way)?

-

## 3 Answers

scala> def getFirstParagraph(txt: String) = {
Option(txt).map(_.takeWhile(c => c != '\n')).orNull
}
getFirstParagraph: (txt: String)String

scala> getFirstParagraph(null)
res2: String = null

scala> getFirstParagraph("fsdfasf")
res3: String = fsdfasf

scala> getFirstParagraph("fsdfasf\nxxxxxxx")
res4: String = fsdfasf


Option(txt) converts txt into an Option[String] which will be None if txt is null.

map will execute the takeWhile only if the Option is Some.

Finally orNull will pull the value out of the Option if it is Some or evaluate to null otherwise.

-
This gives me a warning: "<console>:9: warning: comparing values of types Char and java.lang.String using !=' will always yield true" on Sacla 2.9.2, also the code didn't work... –  bertzzie Aug 13 '12 at 4:03
Nevermind, silly mistake. I tested against "\n", not '\n'. Sorry. –  bertzzie Aug 13 '12 at 4:08

Here's my take on it:

def getFirstParagraph(txt: String): String = txt.lines.next


As to the null objection: in idiomatic Scala, you don't use null. If there's some API which might return you a null string, then, at that point, you turn it into an Option, and handle the Option elsewhere as needed.

Handling null (or even Option) at the getFirstParagraph method is misplaced.

-
I agree on the misplaced responsabilities note. –  fedesilva Aug 13 '12 at 23:00
Good point, I agree. –  ericacm Aug 14 '12 at 3:19

ericacm's code may be shortened (removing explicit lambda notation). Also, propagating null is a bad/dangerous thing (unless you are forced to stay close to the metal, but then how about writing in C), so why not return an Option?

def getFirstParagraph(txt: String) = {
Option(txt).map(_.takeWhile(_ != '\n'))
}


Or, if you don't use this from Java, testing for null is kinda weird, as in pure world there is no null. So there is:

def getFirstParagraph(txt: String) = {
txt.takeWhile(_ != '\n')
}
`
-
In the second case map call is excess. –  citxx Nov 17 '12 at 15:12
Thank you for mentioning error. I was too careless. –  Sarge Borsch Nov 20 '12 at 14:08