6

Can I somehow cache the i.toString in this simple definition of function?

def palindrome(i: Int) = i.toString == i.toString.reverse

I want to keep this function simple, w/o a classic multi-line, brace-enclosed function..

Parobay
  • 2,549
  • 3
  • 24
  • 36

6 Answers6

6

You could do:

def palindrome(i: Int) = ((s:String) => s == s.reverse)(i.toString)
Marimuthu Madasamy
  • 13,126
  • 4
  • 30
  • 52
6

Well, Scala doesn't have a let statement like some traditional functional languages, but that's largely because val + braces fulfill the same purpose. Are you objecting to the multi-line part or to braces in general? Because it's pretty hard to beat:

def palindrome(i: Int) = { val s = i.toString; s == s.reverse }

Attempts to elide the braces will likely only drive the character count up.

Reimer Behrends
  • 8,600
  • 15
  • 19
  • This is an obvious solution and I guess in real-world problems I'd use it. But while I'm learning Scala, I want something more interesting.. beause as you can see, in Scala even such a simple operation like the one in my question can be solved in 1000 ways .. while in Java (or x, y, z ) the answer is probably "*nah, you can only ... *" . Thanks anyway! – Parobay Apr 12 '13 at 06:08
  • @Parobay I believe in nearly every programming language there are multiple ways to solve a problem – mgttlinger Dec 16 '13 at 08:23
5

Use the forward pipe operator:

scala> implicit class PipedObject[A](value: A) {
     |   def |>[B](f: A => B): B = f(value)
     | }
defined class PipedObject

scala> def palindrome(i: Int) = i.toString |> (s => s == s.reverse)
palindrome: (i: Int)Boolean

While this solves your problem elegantly I advise to change the signature of palindrome from palindrome(Int) to palindrome(String) and call it with palindrome(i.toString) (and rename it to isPalindrome).

kiritsuku
  • 52,967
  • 18
  • 114
  • 136
3

It is a one-liner, but the braces are still here. It seems shorter to me, though:

def palindrome(i: Int) = { val s = i.toString; s == s.reverse }

If you have many such functions, you could also do something like this:

@inline def let[T, R](expr: =>T)(body: T => R): R = body(expr)

def palindrome(i: Int) = let(i.toString) { s => s == s.reverse }
axel22
  • 32,045
  • 9
  • 125
  • 137
  • though this requires a second definition, I think the 2nd definition is the most universal. Nice solution +1 ! – Parobay Apr 12 '13 at 06:11
1

Starting Scala 2.13, the standard library provides the chaining operation pipe which can be used to convert/pipe i.toString with the function checking if a string is a palindrome:

import scala.util.chaining._

def palindrome(i: Int) = i.toString.pipe(s => s == s.reverse)
Xavier Guihot
  • 54,987
  • 21
  • 291
  • 190
0

Needing to refer to something exactly twice comes up often enough that it's useful to have enrich it into a method:

implicit class DiamondMapper[A](val a: A) extends AnyVal {
  def diamond[B](f: (A,A) => B) = f(a,a)
}

Then:

scala> 575.toString.diamond(_ == _.reverse)
res1: Boolean = true

This is a special case of the pipe operator (|> if you like symbolic notation), but it's a common enough use case that you might want to create your own.

(Diamond here because it takes one value, splits it in two, and merges it back together again.)

Rex Kerr
  • 166,841
  • 26
  • 322
  • 407