0

Here is how I can check if a number is even/odd in Ruby:

def even_or_odd(number)
  ['Even', 'Odd'][number % 2]
end

The closest I have in Scala is the following:

  def evenOrOdd(number: Int): String = {
     val a = Array("Even", "Odd")
     a(number % 2)
  }

What I really want to do is something like this, but it won't compile:

  def evenOrOdd(number: Int): String = {
    ("Even", "Odd")(number % 2)
  }

Firstly, what is this type of 'anonymous' structure called? Secondly, what is an elegant way to use it? If you have a similar example that illustrates the power/conciseness/clarity of Scala, I'd like to see it.

Fred
  • 564
  • 10
  • 21
  • 1
    Well... such use cases do not show "power" of a language in anyway. And `conciseness` and `clarity` are very subjective to the user. Power of Scala lies in its type-system and functional features. – sarveshseri Nov 15 '18 at 12:13
  • I understand. This is a trivial example that highlights my problem. I plan to use this construct in places where badly-written programs have several if-then statements interspersed with literals.In my business, conciseness and clarity have a direct impact on profitability. A philosopher might rightly argue they are subjective, but beauty is in the eye of the beholder and my colleagues have a keen eye for it. – Fred Nov 15 '18 at 13:52
  • Programming languages are tools. You can just think of them like different kind of modes of transportation around. You have bikes, cars, bus, trucks, trailers, trains, horse-carts, horses. Each one of these can take you to places but differ from each other and each has their strong and weak points. Now sense of aesthetics differ heavily from each other. `conciseness` and `clarity` are good to have but I will everytime choose `correctness` above both of them. – sarveshseri Nov 15 '18 at 16:03
  • 1
    This is a hack. What's more, it will throw an error on negative odd numbers, since `-1 % 2` evaluates to `-1` in Scala, Java, JavaScript, and probably a few others. Just use `if (number % 2 == 0) "even" else "odd"`. It's easier to read and works. – Brian McCutchon Nov 15 '18 at 18:40
  • Brian, if you want to see an original hack, have a look at this: https://stackoverflow.com/questions/51126534/fizzbuzz-ruby-one-liner . Ruby knows how to work with negative indices. It can be useful with calculation-based indices. Unfortunately, Scala and Java don't do negative indices. A weakness in my opinion. – Fred Nov 15 '18 at 19:42

3 Answers3

3

("Even", "Odd") is of type (String,String) which is an alias for Tuple2[String, String] it's accessors are ._1 and ._2

you could do Array("Even", "Odd")(number % 2) or EDIT: as pointed out in the comments this won't actually work. This will though Array("Even", "Odd").apply(number % 2)

number % 2 match {
    case 0 => "Even"
    case 1 => "Odd"
    case -1 => "Odd" //EDIT: as per comment. I forgot about this case
}
Dominic Egger
  • 1,016
  • 5
  • 7
  • `Array("Even", "Odd")(number % 2)` does not compile. It has something to do with the `ClassTag` type parameter, but I am not able to provide more details on that. – ygor Nov 15 '18 at 12:07
  • huh you're right weird. e.g. `Array(1,2)(4 % 2)` works as expected I'll edit it. thanks! – Dominic Egger Nov 15 '18 at 12:11
  • `Vector("Even", "Odd")(number % 2)` compiles. – Lasf Nov 15 '18 at 18:37
  • Your example doesn't work on negative numbers. You should probably change the second case to `_` – Ethan Nov 16 '18 at 22:19
2

This compiles:

def evenOrOdd(number: Int): String = {
    Array("Even", "Odd").apply(number % 2)
}

In most cases, calling the apply method can be omitted, because it comes with its syntactic sugar. However, in this case, it does not work. You either have to extract the Array("Even", "Odd") into a var, var or def or you have to give up on the syntactic sugar.

The reason, why the syntactic sugar Array("Even", "Odd")(number % 2) does not work, is somehow hard to explain, but it is caused by following:

  • Java does not allow generic array creation (e.g. new T[], where T is a generic type)
  • Scala allows generic array creation by utilizing ClassTag in Array.apply; the ClassTag comes with its own syntactic sugar, which makes Array("Even", "Odd")(number % 2) invalid
ygor
  • 1,726
  • 1
  • 11
  • 23
2
def evenOrOdd(number: Int) = 
 List("Even","Odd")(number % 2)
Bogdan Vakulenko
  • 3,380
  • 1
  • 10
  • 25