8
\$\begingroup\$

Curious to know how I can improve it, especially the pattern matching part seems a bit repetitive at the moment (lots of case x if ds(x))

 def binarySearch(ds: Array[Double], key: Double): Int = {
 @annotation.tailrec
 def go(low: Int, mid: Int, high: Int): Int = {
 mid match {
 case x if ds(x) == key => x
 case x if high <= low => -1
 case x if ds(x) < key => go(mid + 1, (high - mid + 1) / 2 + mid, high)
 case x if ds(x) > key => go(low, (mid - low) / 2 + low, mid - 1)
 }
 }
 ds.size match {
 case 0 => -1
 case _ => go(0, ds.size / 2, ds.size - 1)
 }
 }
asked Jun 29, 2014 at 18:57
\$\endgroup\$

1 Answer 1

11
\$\begingroup\$

the high <= low part does not involve x and could be pulled out of the case. The rest is fine IMHO.

One remark: the -1 return in the error-case is a bit of a smell - why not return Option[Int] instead?

And finally: I think you don't need mid as an argument - as you guard for low > high anyway you can as easily compute it inside your inner function and make the calls a bit more readable (only low and high)

Could look like this

 type Index = Int
 def binarySearch(ds: Array[Double], key: Double): Option[Index] = {
 @tailrec
 def go(lo: Index, hi: Index): Option[Index] = {
 if (lo > hi)
 None
 else {
 val mid: Index = lo + (hi - lo) / 2
 ds(mid) match {
 case mv if (mv == key) => Some(mid)
 case mv if (mv <= key) => go(mid + 1, hi)
 case _ => go(lo, mid - 1)
 }
 }
 }
 go(0, ds.size - 1)
 }
answered Jun 29, 2014 at 19:24
\$\endgroup\$
4
  • 2
    \$\begingroup\$ You introduced a serious bug by changing the code from (high - mid + 1) / 2 + mid to mid = (lo + hi) / 2 - the first one is safe from overflow, the later isn't. The correct code is lo + (hi - lo) / 2. \$\endgroup\$ Commented Jun 29, 2014 at 22:28
  • \$\begingroup\$ yes thank you for pointing this out - big blunder there on my part! \$\endgroup\$ Commented Jun 30, 2014 at 4:04
  • \$\begingroup\$ Why use pattern matching on ds(mid) instead of just plain if/else if/else? \$\endgroup\$ Commented Feb 20, 2016 at 18:31
  • \$\begingroup\$ @OliverJosephAsh because you would get two nested ifs which most people see as ugly and in my opinion the match is just more readable \$\endgroup\$ Commented Feb 20, 2016 at 19:27

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.