Skip to content

Latest commit

 

History

History
157 lines (108 loc) · 5.18 KB

ch3-ExpressionsAndConditionals.asciidoc

File metadata and controls

157 lines (108 loc) · 5.18 KB

1) Given a string name, write a match expression that will return the same string if non-empty, or else the string "n/a" if it is empty.

Answer

You could use a pattern guard here and check if the size of the string is zero or non-zero. However, it’s easier to just match based on an empty string.

scala> val name = "Dresden"
name: String = Dresden

scala> name match {
     |   case "" => "n/a"
     |   case n => n
     | }
res0: String = Dresden

2) Given a double amount, write an expression to return "greater" if it is more than zero, "same" if it equals zero, and "less" if it is less than zero. Can you write this with if..else blocks? How about with match expressions?

Answer

First, here’s the if..else block (specifically an if..else-if..else block).

scala> val amount = 2.143
amount: Double = 2.143

scala> if (amount > 0) "greater" else if (amount < 0) "lesser" else "same"
res0: String = greater

Second, the match expression that achieves the same purpose.

scala> amount match {
     |   case x if x > 0 => "greater"
     |   case x if x < 0 => "lesser"
     |   case x => "same"
     | }
res1: String = greater

Which solution do you prefer? I find the match expression a bit more readable but the if..else block is certainly more compact.

3) Write an expression to convert one of the input values "cyan", "magenta", "yellow" to their 6-char hexadecimal equivalents in string form. What can you do to handle error conditions?

Answer

Returning an appropriate hexadecimal version of one of the three possible color names is easy enough. A good error handling solution should check if an unexpected color name was given and log the error, while still returning a useful color.

scala> val color = "magenta"
color: String = magenta

scala> color match {
     |   case "cyan" => "00ffff"
     |   case "magenta" => "00ff00"
     |   case "yellow" => "ffff00"
     |   case x => {
     |     println(s"Didn't expect $x !")
     |     "333333"
     |   }
     | }
res0: String = 00ff00

4) Print the numbers 1 to 100, with each line containing a group of 5 numbers. For example:

1, 2, 3, 4, 5,
6, 7, 8, 9, 10
....

Answer

Two for-loops, one for the rows and one for the columns, can handle this task.

scala> for (i <- 1 to 100 by 5) {
     |   for (j <- i to (i + 4)) { print(s"$j, ") }
     |   println("")
     | }
1, 2, 3, 4, 5,
6, 7, 8, 9, 10,
11, 12, 13, 14, 15,
...

5) There is a popular coding interview question I’ll call "typesafe", in which the numbers 1 - 100 must be printed one per line. The catch is that multiples of 3 must replace the number with the word "type", while multiples of 5 must replace the number with the word "safe". Of course, multiples of 15 must print "typesafe".

Answer

There’s a number of ways to solve this. Here’s a solution that isn’t very compact but plainly checks for the greatest factor (15) before checking for 5 and 3.

scala> for (i <- 1 to 100) {
     |   i match {
     |     case x if x % 15 == 0 => println("typesafe")
     |     case x if x % 5 == 0 => println("safe")
     |     case x if x % 3 == 0 => println("type")
     |     case x => println(x)
     |   }
     | }
1
2
type
4
safe
...

6) Can you rewrite the answer to question 5 to fit on one line? It probably won’t be easier to read, but reducing code to its shortest form is an art, and a good exercise to learn the language.

Answer

Note: in the first edition of the book the text says "answer to question 6", which is accidentally recursive. It should have said "answer to question 5".

To make this fit on a single line, I switched to a mutable string which could hold "type" and "safe". It can also be checked for emptiness and thus print the current integer value.

scala> for (i <- 1 to 100) { var s = ""; if (i%3==0) s="type"; if (i%5==0) s+="safe"; if(s.isEmpty) s += i; println(s) }
1
2
type
4
safe
type
7
8

Can you write a shorter version?