Archive for the ‘Scala’ Category

Scala exercise 2: observer design pattern

Sunday, October 10th, 2010

Introduction

This is the second exercise in my Scala exercises series. If you haven’t seen it before, you may want to start from exercise 1: template method. Below is exercise 2: observer design pattern.

Problem: Complete a Scala trait Observed (shown below) to represent the subject being observed and the Scala trait Observer to represent an observer. The Observed object allows one or more Observers to register with it. Later, it can fire an event and notify all such Observers. The code is like (where E is the type of the event to be fired):

trait Observed[E] {
  def addObserver(o: Observer[E]) ...
  def notifyObservers(ev: E) ...
}

trait Observer[E] {
  def eventOccurred(ev: E)
}

Then use these traits to implement Java bean “bounded properties”, e.g., to allow others to get notified when properties of a Book instance is changed:

//Let others observe changes to its properties
case class Book(var title: String, var price: Double) extends Observed[PropertyChangeEvent] {
  def setTitle(title: String) {
    val oldTitle = this.title
    this.title = title
    //Notify the observers
    ...
  }
  def setPrice(price: Double) {
    val oldPrice = this.price
    this.price = price
    //Notify the observers
    ...
  }
}

//A sample observer class
class Foo extends Observer[PropertyChangeEvent] {
  //Just print some info after a property has been changed
  def eventOccurred(ev: PropertyChangeEvent) = {
    printf("Foo: %s of %s has changed from %s to %s\n", ev.getPropertyName, ev.getSource, ev.getOldValue, ev.getNewValue)
  }
}

object BeanTest {
  def main(args: Array[String]) {
    val b1 = new Book("Scala programming", 35.95)
    val foo = new Foo
    b1.addObserver(foo) //Register the observer
    b1.setTitle("Thinking in Scala")  //foo should get an event
    b1.setPrice(39.95) //ditto
    b1.setTitle("Effective Scala") //ditto
  }
}

The above code should print:

Foo: title of Book(Thinking in Scala,35.95) has changed from Scala programming to Thinking in Scala
Foo: price of Book(Thinking in Scala,39.95) has changed from 35.95 to 39.95
Foo: title of Book(Effective Scala,39.95) has changed from Thinking in Scala to Effective Scala

Try to do it now! Then, click here to see the answer.

Scala exercise 1: template method design pattern

Sunday, October 3rd, 2010

Introduction

As part of my studying with Scala, I have tried to find some exercises to do but most are either too simple or too “academic”. So, I decided to create a series of Scala exercises to implement the well known design patterns in an industrial context. Here is the first one: template method.

Problem: Create a Scala class JdbcTemplate that has two template methods: execute() and load(). They will execute a SQL statement and load the query results using JDBC respectively. The methods should open and close the connection, create and close the statement and etc. so that the caller doesn’t need to worry about those. For example, the client could use your code like this:

object Test {
  def main(args: Array[String]) {
    Class.forName("org.h2.Driver")
    val t = new JdbcTemplate
    val ds = () => DriverManager.getConnection("jdbc:h2:~/test")
    t.execute(ds, "drop table products if exists")
    t.execute(ds, "create table products (id long primary key, name varchar(128))")
    val insertSql = "insert into products values(?, ?)"
    t.execute(ds, insertSql, List(100, "p1")) //the list is the parameters
    t.execute(ds, insertSql, List(101, "p2")) //ditto
    val ps = t.load[Product](ds, "select * from products", Nil,
      { //this function maps a record into an object
        (rs) => new Product(rs.getLong("id"), rs.getString("name"))
      })
    println(ps)
  }
}

//make it a case class so that it can be printed to the console nicely
case class Product(val id: Long, val name: String) {
}

To make it run, you need to include the h2 database into your classpath. If you use Maven, just add the following to pom.xml:

       <dependency>
             <groupId>com.h2database</groupId>
             <artifactId>h2</artifactId>
             <version>1.2.143</version>
       </dependency>

Note that I am not suggesting that you do this in production code; you’d probably want to use an ORM framework.

Click here to see the answer.

Getting started with Scala, Spring, Hibernate & Wicket

Saturday, June 19th, 2010

Introduction

Below is a tutorial to document what I did to create a fully working Scala project utilizing the best or the most popular frameworks or tools in enterprise Java such as Spring, Hibernate/JPA, Wicket, Maven and Intellij IDEA. The purpose is to help other Java programmers get started quickly with a fully working enterprise Scala project.

Setting up the IDE

First, download the Intellij IDEA 9.0.x (community edition) as it is the best scala IDE right now. Then choose File | Settings | Plugins, choose the Available tab to install the Scala plugin.

Creating the Maven project

In IDEA, choose File | New Project and choose the Maven module to create a Maven project. Then modify pom.xml as shown below. This will add all the dependencies you need and set up the compilation of Scala classes in the build processes:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.foo</groupId>
    <artifactId>myapp</artifactId>
    <packaging>war</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>myapp Java EE 6 Webapp</name>
    <url>http://maven.apache.org</url>
    <properties>
        <spring.version>3.0.3.RELEASE</spring.version>
    </properties>
    <repositories>
        <repository>
            <id>java.net2</id>
            <name>Repository hosting the jee6 artifacts</name>
            <url>http://download.java.net/maven/2</url>
        </repository>
        <repository>
            <id>scala-tools.org</id>
            <name>Scala-tools Maven2 Repository</name>
            <url>http://scala-tools.org/repo-releases</url>
        </repository>
        <repository>
            <id>wpt-release</id>
            <url>http://wicketpagetest.sourceforge.net/m2-repo/releases</url>
        </repository>
        <repository>
            <id>wpt-snapshot</id>
            <url>http://wicketpagetest.sourceforge.net/m2-repo/snapshots</url>
        </repository>
    </repositories>
    <pluginRepositories>
        <pluginRepository>
            <id>scala-tools.org</id>
            <name>Scala-tools Maven2 Repository</name>
            <url>http://scala-tools.org/repo-releases</url>
        </pluginRepository>
    </pluginRepositories>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>${spring.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-core</artifactId>
                <version>${spring.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-web</artifactId>
                <version>${spring.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-orm</artifactId>
                <version>${spring.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <version>1.2.120</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>3.4.0.GA</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
        </dependency>
        <dependency>
            <groupId>com.ttdev</groupId>
            <artifactId>wpt-core</artifactId>
            <version>1.5.2-SNAPSHOT</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.ttdev</groupId>
            <artifactId>wpt-runtime-spring</artifactId>
            <version>1.5.2-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-web-api</artifactId>
            <version>6.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.2</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.scala-lang</groupId>
            <artifactId>scala-library</artifactId>
            <version>2.8.0.RC3</version>
        </dependency>
        <dependency>
            <groupId>org.apache.wicket</groupId>
            <artifactId>wicket</artifactId>
            <version>1.4.9</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.4.2</version>
        </dependency>
    </dependencies>
    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>2.0.2</version>
                </plugin>
                <plugin>
                    <groupId>org.scala-tools</groupId>
                    <artifactId>maven-scala-plugin</artifactId>
                    <version>2.9.1</version>
                </plugin>
            </plugins>
        </pluginManagement>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <executions>
                    <execution>
                        <phase>compile</phase>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.1-beta-1</version>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.scala-tools</groupId>
                <artifactId>maven-scala-plugin</artifactId>
                <executions>
                    <execution>
                        <id>scala-compile-first</id>
                        <phase>process-resources</phase>
                        <goals>
                            <goal>add-source</goal>
                            <goal>compile</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>scala-test-compile</id>
                        <phase>process-test-resources</phase>
                        <goals>
                            <goal>testCompile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
        <finalName>myapp</finalName>
    </build>
</project>

Wait for a while and IDEA will prompt you on whether to import the changes into the project. Say yes.

Setting up web.xml

Next, modify main/webapp/WEB-INF/web.xml as below. This sets up the Wicket filter, the Spring filter to open the JPA entity manager and the Spring listener to initialize Spring itself.

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
    <filter>
        <filter-name>f2</filter-name>
        <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
    </filter>
    <filter>
        <filter-name>f1</filter-name>
        <filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
        <init-param>
            <param-name>applicationClassName</param-name>
            <param-value>com.foo.myapp.MyApp</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>f1</filter-name>
        <url-pattern>/app/*</url-pattern>
    </filter-mapping>
    <filter-mapping>
        <filter-name>f2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:/beans.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
</web-app>

Setting up the Spring beans for database access and transaction

To define those Spring beans, create main/resources/beans.xml with the content below. This defines the entity manager factory, the transaction manager and etc.

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context-3.0.xsd

http://www.springframework.org/schema/tx

http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

    <context:component-scan base-package="com.foo.myapp"/>
    <bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="persistenceXmlLocation" value="classpath:/META-INF/my-persistence.xml"/>
    </bean>
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="emf"/>
    </bean>
    <tx:annotation-driven />
</beans>

The entity manager factory will read the database configuration from the my-persistence.xml file. So, create it in main/resources/META-INF with the content below. Here, you’ll access an H2 database named myapp in your home directory.

<persistence xmlns="http://java.sun.com/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
             version="2.0">
    <persistence-unit name="myapp" transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <properties>
            <property name="hibernate.connection.driver_class" value="org.h2.Driver"/>
            <property name="hibernate.connection.url" value="jdbc:h2:tcp://localhost/~/myapp"/>
            <property name="hibernate.connection.username" value="sa"/>
            <property name="hibernate.connection.password" value=""/>
            <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
            <property name="hibernate.hbm2ddl.auto" value="create"/>
        </properties>
    </persistence-unit>
</persistence>

Creating the Wicket page

Here, you’ll create a Wicket page to display some products loaded from the database. So, create the main/scala folder, right click it and choose New | Scala Class. Name the class as MyPage and put it into the com.foo.myapp package. The class is shown below:


package com.foo.myapp

import org.apache.wicket.markup.html._
import basic.Label
import list.{ListItem, ListView}
import org.apache.wicket.spring.injection.annot.SpringBean
import org.apache.wicket.model.CompoundPropertyModel

class MyPage extends WebPage {
  @SpringBean
  var ps: ProductService = _
  val productListView = new ListView[Product]("productListView", ps.getAll) {
    def populateItem(item: ListItem[Product]) = {
      item.setModel(new CompoundPropertyModel[Product](item.getDefaultModelObject))
      item.add(new Label("name"))
      item.add(new Label("price"))
    }
  }
  add(productListView)
}

Note that it is using a ProductService object to load the products. You’ll create it later. In addition, note that the field is assigned to an underscore (_), which tells the Scala compile to NOT initialize, but leave it at the default state (null in this case). This is required for the injection to work. If you assign it to null explicitly, you
will overwrite the Spring bean as the injection will occur before the constructor of MyPage is executed.

Now, create the MyPage.html file in src/main/resources/com/foo/myapp:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
    <table border="1">
        <tr wicket:id="productListView">
            <td wicket:id="name"></td>
            <td wicket:id="price"></td>
        </tr>
    </table>
</html>

Creating the ProductService

Right click the com.foo.myapp package in the src/main/scala folder and choose New | Scala Class, then choose to create a trait named ProductService:

package com.foo.myapp

import java.util.List

trait ProductService {
  def getAll: List[Product]
}

This is the interface. To create the implementation, create a DefaultProductService Scala class in the same package:

package com.foo.myapp

import javax.persistence.{PersistenceContext, EntityManager}
import org.springframework.stereotype.{Service}
import org.springframework.transaction.annotation.Transactional
import org.springframework.beans.factory.annotation.Autowired

@Service
@Transactional
class DefaultProductService extends ProductService {
  @Autowired
  var products: Products = _

  def getAll = products.getAll
}

Note that it is using a DAO named of type Products to do the work.

Creating the Products DAO

To create the DAO, create a trait named Products in the same package:

package com.foo.myapp

import java.util.List

trait Products {
   def getAll: List[Product]
}

Then create the implementation Scala class DefaultProducts in the same package:

package com.foo.myapp

import javax.persistence.{PersistenceContext, EntityManager}
import org.springframework.stereotype.Repository
import java.util.List

@Repository
class DefaultProducts extends Products {
  @PersistenceContext
  var em: EntityManager = _

  def getAll = {
    em.createQuery("select p from Product p").getResultList.asInstanceOf[List[Product]]
  }
}

Creating the entity class

Create the Product class and map it to the database:

package com.foo.myapp

import javax.persistence.{GeneratedValue, Id, Entity}

@Entity
class Product {
  @Id
  @GeneratedValue
  var id: Long = _
  var name: String = _
  var price: Double = _
}

Creating the Wicket application class

Finally, create MyApp Scala class in the same package:


package com.foo.myapp

import org.apache.wicket.protocol.http.WebApplication
import com.ttdev.wicketpagetest.MockableSpringBeanInjector

class MyApp extends WebApplication {
  def getHomePage = classOf[MyPage]

  override def init = {
    MockableSpringBeanInjector.installInjector(this)
  }
}

Here you specify MyPage as the home page and install an injector that can inject Spring beans (as well as mock objects, even though you won’t use this capability here).

Running the application

As the Intellij IDEA community edition doesn’t include the integration with app servers, you’ll embed Jetty to run your application. This is easy. Just create a Scala class ManualTest in the com.foo.myapp package in the test/scala folder (NOT the main/scala folder). The content is below:

package com.foo.myapp

import com.ttdev.wicketpagetest.{WebAppJettyConfiguration, WicketAppJettyLauncher}

object ManualTest {
  def main(args: Array[String]) {
    val l = new WicketAppJettyLauncher
    l.startAppInJetty(new WebAppJettyConfiguration)
  }
}

To run the application, you need to have the H2 database server running first. So, go to http://www.h2database.com to download and unpack it. Then change into h2/bin and run h2.bat (or h2.sh on Linux).

While the ManualTest class is the active editor in IDEA, choose Run | Run in IDEA. It will run ManualTest which will launch Jetty to run your application.

To test it, try accessing http://localhost:8888/app in a browser. It should display nothing as there is no product in the database. However, it will create the table required.

To add some products, go to http://localhost:8082 to access the H2 web client. Enter jdbc:h2:tcp://localhost/~/myapp as the JDBC URL. Click Connect. Then issue the SQL statement:

SELECT * FROM PRODUCT

to select the product. Nothing should be there. That’s fine. In the result display, click the plus sign to create a product record. Feel free to add more.

Finally, reload http://localhost:8888/app and you should see the products displayed in the Wicket page.

Updated: You can download the project folder.

Scala IDE has matured for the mass

Friday, June 18th, 2010

For a language to be readily used by the mass, in addition to the language itself, it needs a production quality runtime, rich libraries and IDE (I know superstar programmers can use Emacs or vi to program, but I believe the mass including myself really need an IDE that works). As Scala is using the JVM and can use all the libraries written in Java, the first two conditions are already checked. What has been holding it back is the IDE. The good news is, the free intellij IDEA community edition now meets all the needs of the majority of web programmers.

Why? First of all, code complete actually works. Second, it supports Maven project mixing Java and Scala. Third, even though the community edition doesn’t support integration with app servers, we can easily launch an embedded Jetty to run the webapp right in the IDE (to see an example, see the example given by Larry H there). The effect is no different from having an integration with Jetty.

Before trying intellij IDEA, I also tried Eclipse and NetBeans. The Scala plugin for Eclipse is of alpha quality (and has always been so for the past several years). Every time I tried it always had all kinds of obvious problems like code-completion not working while it should, showing errors while the code compiles fine with scalac.

The Scala plugin for NetBeans is much better than the Eclipse one and is quite close to being production ready. Basically code complete works. However, when auto-completing a class name, it won’t add the import statement for you. In addition, it can’t generate the method signature for you when you want to override a method or implement an abstract method. In my opinion these shortcomings must be fixed before it can be used in day-to-day work.

Applying scala to solving real world problems: making delegation super easy

Saturday, June 12th, 2010

In Java it is very common to write boring code like below to perform logging:

public class Foo {
   private static Logger logger = LoggerFactory.getLogger(Foo.class);

   public void m1() {
      logger.debug("...");
      ...
      logger.debug("...");
   }
   public void m2() {
      logger.debug("...");
      ...
      logger.debug("...");
   }
}

As you keep typing the delegation call logger.debug(…) repeatedly, you’ll wonder if there is an easy way to do that. For example, you can create your own debug() method, then you can just call debug() instead of logger.debug():

public class Foo {
   private static Logger logger = LoggerFactory.getLogger(Foo.class);

   public void debug(String msg) {
      logger.debug(msg);
   }
   public void m1() {
      debug("...");
      ...
      debug("...");
   }
   public void m2() {
      debug("...");
      ...
      debug("...");
   }
}

The problem is that,you’ll need to create other similar methods like info(), warn() and error(). In addition, when you work on another class Bar, you will need to create those  methods in Bar again! To solve these problems, you may extract this code into a common base class to be reused:

public class DelegatingLogger {
   protected static Logger logger;

   public void debug(String msg) {
      logger.debug(msg);
   }
   public void info(String msg) {
      logger.info(msg);
   }
   ...
}

public class Foo extends DelegatingLogger {
   static {
      logger = LoggerFactory.getLogger(Foo.class);
   }
   public void m1() {
      debug("...");
      ...
      debug("...");
   }
}

However, because Java only support single inheritance, if Foo needs to inherit a real base class, then this approach won’t work. To solve this problem in Scala, we can make the DelegatingLogger class a “trait” which is an auxiliary base class (any class can be a trait as long as its constructor takes no argument):

trait DelegatingLogger {
  val logger: Logger = LoggerFactory.getLogger(getClass());

  def debug(msg: String) {
    logger.debug(msg)
  }
  def info(msg: String) {
    logger.info(msg)
  }
}

class Foo extends SomeParent with DelegatingLogger {
  def m1 {
    debug("...")
    ...
    debug("...")
  }
}

What the trait mechanism does here is essentially allowing us to easily turn the Foo class from a logger user into a logger itself, that is, turning a “use” relationship into an “is” relationship.

If you’re careful, you may notice that now the logger is an instance variable, not a static variable. If you’re concerned about it, you can let a singleton object (which is also named Foo here but could be anything else) inherit DelegatingLogger, then use a static import to make the static methods available in the Foo class:

object Foo extends DelegatingLogger {

}

import Foo._

class Foo extends SomeParent {
  def m1 {
    debug("...")
  }
}

Applying scala to solving real world problems: Say bye bye to boring constructors and getters/setters

Sunday, January 24th, 2010

In Java, it is very common and boring to create constructors and getters/setters like:

public class Foo {
  private String x;
  private String y;

  public Foo(String x, String y) {
    this.x = x;
    this.y = y;
  }
  public String getX() {
    return x;
  }
  public String getY() {
    return y;
  }
  public void setX(String x) {
    this.x=x;
  }
  public void setY(String y) {
    this.y=y;
  }
}

Yes, Eclipse provides the "Generate constructor using fields" and "Generate getters and setters" commands to do that, but it is still very boring and requires work from us. In Scala, all this boring work is no longer required:

class Foo(x: String, y: String) {
}

Due to the closure support, x and y will be available to all methods inside the Foo class just like Java fields:

class Foo(x: String, y: String) {
  def someMethod {
    println(x+y)
  }
}

To create getters, use to the "val" keyword:

class Foo(val x: String, val y: String) {
  …
}

The Scala compile will create a getter methods named "x" and "y" automatically. To create setters in addition to getters, use "var" instead of "val":

class Foo(var x: String, var y: String) {
  …
}

Then the compiler will create setter methods named "x =" and "y =" for you (Yes, the method name contains a space and then an equal sign, which are allowed in Scala). To call the getters and setters, you may:

val f = new Foo("a", "b")
f.x            //In Scala you don’t need to use () to call a method
f.x = ("c")  //This is OK
f.x = "c"    //Again, don’t have to use ()

Pretty neat, isn’t it?

Applying scala to solving real world problems

Tuesday, October 9th, 2007

Scala is no doubt an excellent language. However, problems like 8-queen or quick sort in the scala doc just aren’t  convincing to software professionals in the industry. So I’d like to show how to apply it to solving real world problems in Java. Here let’s consider the logging problem in Java. Usually people write code like:

        if (log.isDebugEnabled())
        {
            log.debug("Foo is: " + foo);
        }

Why check isDebugEnabled() if the log object will not log the message if debug is not enabled? This is for performance. If we didn’t have this check, the toString() would always be called on foo and the result would always be appended to "Foo is:" to form a new string, even when debug was not enabled.

Scala can easily solve this problem using called-by-name parameters:

class Log {
  var isDebugEnabled: Boolean = false;
 
  def debug(msg: => String) {  //msg is a string expression that is unevaluated
    if (isDebugEnabled) {
      System.out.println(msg); //evaluate msg as if it is a function
    }
  }
}

Now you call this method and provide an expression and it won’t be evaluated unless debug is enabled:

    val log: Log = new Log();
    var foo: Int = 123;
    log.debug("Foo is:"+foo); //won’t be evaluated
    log.isDebugEnabled = true;
    log.debug("Foo is:"+foo); //will be evaluated inside the debug() method