00.scala2014. 3. 28. 13:34
반응형

While working on a new Scala application, I just ran into a situation where a Java class I was using returned a Java List to me. I wasn't exactly thinking too hard at that moment, and didn't realize it was actually a Java List until I tried to use the foreach method on it, and Eclipse balked at me.

Suddenly I ran into a common problem in Scala: When you're using Java classes from Scalaapplications, those Java class will return Java collections. You can then either use them as the Java collections that they are (such as using a Java Iterator), or cast them to Scala collections.

Easily converting Java collections to Scala collections

Amazingly, to use methods like foreach, map, filter, find, and so on with my Java List, all I had to do was add this one import statement to my Scala application:

import scala.collection.JavaConversions._

Once I did that, I could suddenly use a foreach method on my List.

Let's take a quick look at how this works with the Scala command line tool (the Scala REPL). First, we'll create a java.util.List as normal, and see what the REPL shows:

scala> var list = new java.util.ArrayList[Int]()
list: java.util.ArrayList[Int] = []

scala> list.add(1)
res1: Boolean = true

scala> list.add(2)
res2: Boolean = true

Now, if I try to use the foreach method on the Java list, it will fail, as expected:

scala> list.foreach
<console>:9: error: value foreach is not a member of java.util.ArrayList[Int]
             list.foreach
                   ^

However, if I now add the magic JavaConversions import statement to my Scala code:

import scala.collection.JavaConversions._

I can then "magically" use the foreach method on my Java List object:

list.foreach { i => println(i) }
1
2

Scala, Java List, foreach, map, filter - How it works

I just started learning Scala in 2011, and it looks like programmers long before me realized the need for the Java to Scala collection conversions, and added this functionality in Scala 2.8. I haven't dug into the source code behind the scenes to see how this magic works, but I just found a nice discussion of the background at the Graham Hacking Scala website.

Graham mentions several interesting points in that article, including these notes:

If we look a bit further into the Scala API, we'll see that there's also a trait called Seq, which is a slightly better parallel to Java's List than the Iterable or Traversable traits. So what you really want to end up with when you bring your Java List into your Scala code is a Scala Seq, not a Scala List.

Conversions between Java and Scala collections with JavaConversions

While I'm on this topic, I'll conclude with a few links to the Scala website, where you can find more information:

As you can see from that second link, the JavaConversions object currently supports the following Java to Scala collections conversions:

scala.collection.Iterable <=> java.lang.Iterable
scala.collection.Iterable <=> java.util.Collection
scala.collection.Iterator <=> java.util.{ Iterator, Enumeration }
scala.collection.mutable.Buffer <=> java.util.List
scala.collection.mutable.Set <=> java.util.Set
scala.collection.mutable.Map <=> java.util.{ Map, Dictionary }
scala.collection.mutable.ConcurrentMap <=> java.util.concurrent.ConcurrentMap

Important for my current project, the following one-way conversions are also offered:

scala.collection.Seq         => java.util.List
scala.collection.mutable.Seq => java.util.List
scala.collection.Set         => java.util.Set
scala.collection.Map         => java.util.Map
java.util.Properties         => scala.collection.mutable.Map[String, String]

In summary, I hope this brief tutorial on converting Java collections, such as a List, to Scala collections, has been helpful.

Posted by 1010
00.scala2014. 3. 28. 13:27
반응형

Scala FAQ: What are the Scala data types? How many bits do they use to store their data, and what is the range of those data types?

Courtesy of the excellent book, Programming in Scala, here is a list and description of the Scala data types, including bit sizes and data ranges:

Data Type     Definition

Boolean       true or false

Byte          8-bit signed two's complement integer (-2^7 to 2^7-1, inclusive)
Short         16-bit signed two's complement integer (-2^15 to 2^15-1, inclusive)
Int           32-bit two's complement integer (-2^31 to 2^31-1, inclusive)
Long          64-bit two's complement integer (-2^63 to 2^63-1, inclusive)

Float         32-bit IEEE 754 single-precision float
Double        64-bit IEEE 754 double-precision float

Char          16-bit unsigned Unicode character (0 to 2^16-1, inclusive)
String        a sequence of Chars

Notes about Scala data types

The String class resides in the package java.lang, and all these other types are in the package scala.

You may have noticed that these data types in Scala have the exact same range as the corresponding data types in Java. This makes it easy to convert these Scala types to their corresponding Java primitive types.

Also interesting to note, if you're into specifics: Collectively, Byte, Short, Int, Long, and Char are calledintegral types. The integral types plus Float and Double are called numeric types. (That was again courtesy of the book, Programming in Scala.)

Official Scala data type documentation

Here are links to the official Scala docs for these data types:

And here's a link to the Programming in Scala book on Amazon:

Posted by 1010
00.scala2014. 3. 28. 13:21
반응형

Scala collections FAQ: How can I convert a Scala array to a String?

A simple way to convert a Scala array to a String is with the mkString method of the Array class. (Although I've written "array", the same technique also works with any Scala sequence, including Array, List, Seq, ArrayBuffer, Vector, and other sequence types.)

Here's a quick array to string example using the Scala REPL:

scala> val args = Array("Hello", "world", "it's", "me")
args: Array[java.lang.String] = Array(Hello, world, it's, me)

scala> val string = args.mkString(" ")
string: String = Hello world it's me

In this first statement:

val args = Array("Hello", "world", "it's", "me")

I create a Scala array named args, and in this second statement:

val string = args.mkString(" ")

I create a new String variable named string, separating each String in the array with a space character, which I specified when calling the mkString function.

Using other separator strings

Note that I could have given the mkString function any String to use as a separating character, like this:

scala> val string = args.mkString("\n")
string: String = 
Hello
world
it's
me

or like this:

scala> val string = args.mkString(" . ")
string: String = Hello . world . it's . me

Converting a Scala Int array to a String

As a final example, you can also use the Scala mkString method to convert an Int array to a String, like this:

scala> val numbers = Array(1,2,3)
numbers: Array[Int] = Array(1, 2, 3)

scala> val string = numbers.mkString(", ")
string: String = 1, 2, 3

In summary, I hope these Scala "Array to String" examples have been helpful.

Posted by 1010
00.scala2014. 3. 28. 13:20
반응형

Scala array FAQ: How do I create a String array in Scala?

There are a few different ways to create String arrays in Scala. If you know all your array elements initially, you can create a Scala string array like this:

val fruits = Array("Apple", "Banana", "Orange")

If you don't know the strings that you want in your array initially, but know the size of your array, you can create it first, then populate it later, like this:

val fruits = new Array[String](3)

// somewhere later in the code ...

fruits(0) = "Apple"
fruits(1) = "Banana"
fruits(2) = "Orange"

Mutable Scala String arrays

Note that if you want to create a mutable Scala String array, you really want to use the Scala ArrayBufferclass instead of the Array class, like this:

import scala.collection.mutable.ArrayBuffer
var fruits = ArrayBuffer[String]()
fruits += "Apple"
fruits += "Banana"
fruits += "Orange"

See my Mutable Scala arrays (adding elements to arrays) tutorial for more information on using the Scala ArrayBuffer.

I can add more Scala String array syntax examples over time, but for now, those are the two most common approaches I know.

Posted by 1010
00.scala2014. 3. 28. 13:19
반응형

Just a quick note today that if you want to create a mutable Scala array -- particularly an array that can grow in size after you first declare it -- you need to use the Scala ArrayBuffer class instead of the Array class, which can't grow.

Here's a short example of how to instantiate an ArrayBuffer object, then add elements to the array:

import scala.collection.mutable.ArrayBuffer

var fruits = ArrayBuffer[String]()
fruits += "Apple"
fruits += "Banana"
fruits += "Orange"

Once you have an ArrayBuffer object, you can generally use it like an Array, getting elements like this:

println(fruits(0))

getting the array length like this:

println(fruits.length)

and so on.

Again, the only trick here is knowing that you can't add elements to a Scala array, and therefore, if you want to grow an array, you need to use the ArrayBuffer class instead.

Posted by 1010
00.scala2014. 3. 28. 13:19
반응형

Sometimes when you're writing Scala code, you need to create a null variable (a var, not a val), such as when you need to declare a variable right before using it in a try, catch, finally block. I just ran into this when writing a Scala IMAP email client, where I needed to create two variables right before the trydeclaration, so I could reference the fields in the try block and also in the finally block.

The way you declare a null var variable in Scala is like this:

var store: Store = null
var inbox: Folder = null

As you can see from that code, the secret is knowing that you have to assign the type to the variable when you declare it. If you don't do this, Scala won't know the data type of the variable, so it won't allow you to do this, but if you do it, Scala will be happy.

A complete example

As for my specific problem -- needing to declare a Scala variable right before a try/catch/finally clause -- here's what the solution looks like:

// (1) declare the null variables
var store: Store = null
var inbox: Folder = null

try {
  // (2) use the variables/fields in the try block
  store = session.getStore("imaps")
  inbox = getFolder(store, "INBOX")
  // rest of the code here ...
  catch {
    case e: NoSuchProviderException =>  e.printStackTrace()
                                        System.exit(1)
    case me: MessagingException =>      me.printStackTrace()
                                        System.exit(2)
} finally {
  // (3) use the variables/fields in the finally clause
  inbox.close
  store.close
}

In summary, I hope this short example of how to declare an empty/null variable before a try/catch block in Scala has been helpful.

Posted by 1010
00.scala2014. 3. 28. 13:13
반응형

Scala FAQ: Can you share some examples of the Scala try/catch/finally syntax? Also, can you show how to catch multiple exceptions, and just one exception with the Scala wildcard operator (_)?

The general Scala try/catch/finally syntax looks like this:

try
{
  // your scala code here
} 
catch
{
  case foo: FooException => handleFooException(foo)
  case bar: BarException => handleBarException(bar)
  case _ => println("Got some other kind of exception")
}
finally
{
  // your scala code here, such as to close a database connection
}

As you can see, the Scala try-catch-finally syntax is similar to the Java try-catch-finally syntax, except for the catch area, which uses Scala's pattern matching capabilities to handle the different exceptions you might run into.

In that example, I'm intentionally catching a FooException and a BarException, and then I'm using the Scala "_" wildcard operator to catch any other exceptions that might occur.

Using the Scala _ wildcard operator in a catch clause

One drawback of using Scala's wildcard character (_) in a catch clause is that you can't refer to it in your code, such as if you want to print the exception.

In the excellent book, Programmming Scala, the authors suggest naming your exception variable instead of using the wildcard, which you can then refer to in your own code, something like this:

try
{
  // your scala code here
} 
catch
{
  case foo: FooException => handleFooException(foo)
  case bar: BarException => handleBarException(bar)
  
  // handling any other exception that might come up
  case unknown => println("Got this unknown exception: " + unknown)
}
finally
{
  // your scala code here, such as to close a database connection
}

As you can see from that code, I just name a variable "unknown", which I can then refer to by name.

Printing a Scala exception's stack trace

Finally, here's another Scala try/catch example, where I demonstrate how to print the stack trace from an exception:

def runAppleScriptCommand(c: AppleScriptCommand) {
  val scriptEngineManager = new ScriptEngineManager
  val appleScriptEngine = scriptEngineManager.getEngineByName("AppleScript")
  try {
    appleScriptEngine.eval(c.command)
  } catch {
    case e: ScriptException => e.printStackTrace
  }
}

Scala try/catch/finally examples - Summary

I hope these examples of the Scala try/catch/finally syntax have been helpful. As usual, if you have any questions, comments, corrections, or better examples, just leave a note in the comments section below.

Posted by 1010
00.scala2014. 3. 28. 13:12
반응형

I haven't had the need for this syntax yet, but I just saw some code that shows how to create a private primary constructor in Scala, and I thought I'd test it and share an example of it.

In the example below, I've made the primary constructor of the Order class private:

object PrivateConstructorTests {

  def main(args: Array[String]) {
    val o = new Order  // this won't compile
  }

}

// note the 'private' keyword here
class Order private() {
  
  def this(orderId: Long) {
    this();
    // more code here ...
  }  
  
}

Private primary constructor syntax

The primary constructor is made private in this unusual looking line of code:

class Order private() {

This syntax might make a little more sense if I show a primary constructor that takes a parameter:

class Order private(customerId: Long) {

In either case, the "private" keyword in the location shown makes the primary constructor private.

Getting back to the first source code example, as you saw from the comment included in the source code, this line of code won't even compile because the primary constructor is private:

val o = new Order  // this won't compile

Again, I haven't had a need to use this Scala "private constructor" syntax yet, but I used to use it in Java when I wanted to enforce the Singleton Pattern, as is done in the Java Calendar class.

Posted by 1010
00.scala2014. 3. 28. 13:10
반응형

Scala offers a cool feature where you can rename a class when you import it, including both Scala and Java classes. The basic syntax to rename a class on import looks like this:

import scala.collection.mutable.{Map => MMap}

and this:

import java.util.{HashMap => JavaMap}

If all you needed to know, I hope those "rename on import" syntax examples were helpful.

Why rename a class on import?

An interesting question is, "Why would I want to rename a class on import?"

I've found that I do it to avoid namespace collisions, and/or to make things more clear. For instance, inScala the immutable Map class is imported by default, and if you want to use the mutable version you have to import it manually, as shown here:

# using Map w/o an import gives you an immutable Map
scala> val m = Map("name" -> "Al")
m: scala.collection.immutable.Map[java.lang.String,java.lang.String] = Map(name -> Al)

scala> import scala.collection.mutable.Map
import scala.collection.mutable.Map

# after the import, the same syntax gives you a mutable Map
scala> val m = Map("name" -> "Al")
m: scala.collection.mutable.Map[java.lang.String,java.lang.String] = Map(name -> Al)

This can seem confusing, so one way to work around this confusion -- and make your code more obvious -- is to rename the mutable Map class when you import it. Here's a similar example, but in this case I rename the mutable Map class when I import it:

# at first i get an immutable Map
scala> val m = Map("name" -> "Al")
m: scala.collection.immutable.Map[java.lang.String,java.lang.String] = Map(name -> Al)

# i rename the mutable Map class when i import it
scala> import scala.collection.mutable.{Map => MMap}
import scala.collection.mutable.{Map=>MMap}

# here i still get an immutable Map
scala> val m = Map("name" -> "Al")
m: scala.collection.immutable.Map[java.lang.String,java.lang.String] = Map(name -> Al)

# but here i get a mutable Map by referring to MMap
scala> val m = MMap("name" -> "Al")
m: scala.collection.mutable.Map[java.lang.String,java.lang.String] = Map(name -> Al)

I personally like this approach, because again it makes the code more obvious. You could correctly argue that I could have made it even more obvious if I renamed the class to MutableMap, but in this case I opted for brevity.

Summary

There are many more ways you can use this ability to rename classes when you import them in Scala, and if you have a good example you'd like to share, just leave a note below. Until then, reporting live from Boulder, Colorado, this is Alvin Alexander.

Posted by 1010
00.scala2014. 3. 28. 13:04
반응형

In Java, you sometimes refer to .class in your source code, like this:

info = new DataLine.Info(TargetDataLine.class, null);

As you can see, I refer to TargetDataLine.class in this code. This works fine in Java, but if you've tried it in Scala, you know the .class part of that code won't work.

In Scala, if you want to use ".class", you instead need to use the classOf function: The following Scala classOf code is equivalent to the previous Java .class code:

val info = new DataLine.Info(classOf[TargetDataLine], null)

In summary:

In Java, use Foo.class
In Scala, use classOf[Foo]

Scala getClass and classOf

I won't take any time to discuss this today, but if you're interested in a little more information, here's the output from a short Scala REPL session that shows how to use getClass and classOf:

scala> val s = "Foo"
s: java.lang.String = Foo

scala> s.getClass
res7: java.lang.Class[_ <: java.lang.String] = class java.lang.String

scala> s.getClass.toString
res8: java.lang.String = class java.lang.String

scala> classOf[String]
res9: java.lang.Class[String] = class java.lang.String


Posted by 1010