<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-7017894832730513527</id><updated>2011-12-20T19:18:24.938-06:00</updated><category term='gradle'/><category term='f#'/><category term='scala'/><category term='fsharp'/><category term='java'/><category term='erlang'/><category term='clojure'/><category term='squib'/><category term='functional programming'/><title type='text'>Compulsion to Code</title><subtitle type='html'>In software development there are no silver bullets, but I am always looking out for the next bronze one.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://compulsiontocode.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7017894832730513527/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://compulsiontocode.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>tdalton</name><uri>http://www.blogger.com/profile/13151512717871227421</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://4.bp.blogspot.com/-c8KSZCmTdpI/TbmtJ04pIUI/AAAAAAAAAEM/AEmlqBQ4ecM/s220/tim.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>16</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-7017894832730513527.post-6537559401752367406</id><published>2011-07-01T09:04:00.001-05:00</published><updated>2011-07-01T09:40:40.224-05:00</updated><title type='text'>An Akka actor from the cutting room floor</title><content type='html'>&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;This is an example of hot-swapping actor behavior in Akka using the &lt;i&gt;become&lt;/i&gt; method. This demo was not part of my "Akka: Scaling Up and Out with Actors"(&lt;a href="http://java.ociweb.com/javasig/knowledgebase/2011-06/index.html"&gt;http://java.ociweb.com/javasig/knowledgebase/2011-06/index.html&lt;/a&gt;) talk given at the St. Louis JavaSIG on June 9th, 2011. It was left out due to time constraints on the presentation.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="white-space: pre;"&gt; &lt;/span&gt;Inspired by a post on Dale Schumaker's "The Computational Actor's Guild" site (&lt;a href="http://dalnefre.net/drupal/node/23"&gt;http://dalnefre.net/drupal/node/23&lt;/a&gt;), this demonstrates an actor that builds a ring of of actors of a specified size that then passes a message around the ring a given number of times. What's interesting about this implementation is that the actor uses &lt;i&gt;become&lt;/i&gt; to change the behavior of a Actor from one that helps construct the ring to one that handles the message by passing to the next actor in the ring.&lt;/p&gt;&lt;pre class="scala" name="code"&gt;object RingBecomeDemo {&lt;br /&gt;&lt;br /&gt;  class NodeActor(id:Int, start:Long) extends Actor {&lt;br /&gt;&lt;br /&gt;    def receive = {&lt;br /&gt;      case n:Int =&gt; self ! (self, n)&lt;br /&gt;      case (top:ActorRef, n:Int) =&gt; {&lt;br /&gt;        if (id == 0) {&lt;br /&gt;          become {&lt;br /&gt;            case np:Int =&gt; if (np == 0) {&lt;br /&gt;                self.stop&lt;br /&gt;                printf("Time %d ms\r\n", System.currentTimeMillis - start)&lt;br /&gt;              } else {&lt;br /&gt;                printf("decrementing from %d\r\n", np)&lt;br /&gt;                top ! (np - 1)&lt;br /&gt;              }&lt;br /&gt;          }&lt;br /&gt;          top ! n&lt;br /&gt;        } else {&lt;br /&gt;          val next = Actor.actorOf(new NodeActor(id-1, start)).start&lt;br /&gt;          next ! (top, n)&lt;br /&gt;          become {&lt;br /&gt;            case np:Int =&gt; {&lt;br /&gt;              next ! np&lt;br /&gt;              if (np == 0) {&lt;br /&gt;                self.stop&lt;br /&gt;              }&lt;br /&gt;            }&lt;br /&gt;          }&lt;br /&gt;        }&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  def main(args:Array[String]) {&lt;br /&gt;    val ring = Actor.actorOf(new NodeActor(1000000, System.currentTimeMillis)).start&lt;br /&gt;    ring ! 10&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;This implementation creates a million nodes and times how long it takes to construct the ring and pass an integer around 10 times. &lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Here (&lt;a href="http://sites.google.com/site/compulsiontocode/blog/ring-become.zip"&gt;http://sites.google.com/site/compulsiontocode/blog/ring-become.zip&lt;/a&gt;) is a file containing code above. &lt;a href="http://www.gradle.org/"&gt;Gradle&lt;/a&gt; is required to run it. To execute, unzip and enter 'gradle RingBecomeDemo' within the 'ring-become' directory.&lt;/p&gt;&lt;p&gt;&lt;p&gt;One million node requires a significant heap size. To reduce the number nodes, change the first parameter passed to the NodeActor constructor. The heap size can be changed by editing the RingBecomeDemo task in the &lt;i&gt;build.gradle&lt;/i&gt; file:&lt;/p&gt;&lt;pre class="groovy" name="code"&gt;task RingBecomeDemo(type:JavaExec, dependsOn: classes) {&lt;br /&gt;  jvmArgs = System.getProperty("sun.arch.data.model").equals("64") ? ["-Xms2048m", "-Xmx2048m"] : ["-Xms1024m", "-Xmx1024m", "-server"]&lt;br /&gt;  classpath = sourceSets.main.runtimeClasspath&lt;br /&gt;  main = "tfd.ringbecome.RingBecomeDemo"&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;A follow-up post is planned compare this implementation to one in &lt;a href="http://www.erlang.org/"&gt;Erlang&lt;/a&gt; including performance.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7017894832730513527-6537559401752367406?l=compulsiontocode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://compulsiontocode.blogspot.com/feeds/6537559401752367406/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7017894832730513527&amp;postID=6537559401752367406' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7017894832730513527/posts/default/6537559401752367406'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7017894832730513527/posts/default/6537559401752367406'/><link rel='alternate' type='text/html' href='http://compulsiontocode.blogspot.com/2011/07/akka-actor-from-cutting-room-floor.html' title='An Akka actor from the cutting room floor'/><author><name>tdalton</name><uri>http://www.blogger.com/profile/13151512717871227421</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://4.bp.blogspot.com/-c8KSZCmTdpI/TbmtJ04pIUI/AAAAAAAAAEM/AEmlqBQ4ecM/s220/tim.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7017894832730513527.post-1425854981544142454</id><published>2011-05-20T22:52:00.001-05:00</published><updated>2011-06-24T22:55:02.973-05:00</updated><title type='text'>Fixing Gradle compileScala to not depend on compileJava</title><content type='html'>&lt;p&gt;One problem encountered using the Scala plugin for Gradle is that the 'compileScala' task is dependent on the 'compileJava' task (as of Gradle 0.9.2). If a project has both Java and Scala sources and there are Java classes that depend on Scala ones, the build will fail. Consider two mutually dependent classes in a the same project:&lt;/p&gt;&lt;p&gt;Bar.java&lt;/p&gt;&lt;pre name="code" class="scala"&gt;public class Bar {&lt;br /&gt;    public void doFoo(Foo foo) { ... }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Foo.scala&lt;/p&gt;&lt;pre name="code" class="scala"&gt;class Foo {&lt;br /&gt;  def doBar(bar:Bar) { ... }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Gradle can't build this because Bar depends on Foo which hasn't been compiled yet. However, the Scala compiler can handle cross compilation with Java sources, so the solution is simply let the Scala compile occur first.&lt;/p&gt;&lt;p&gt;To override the compileScala task dependency and reverse the order of the tasks add the following to the 'build.gradle' file:&lt;/p&gt;&lt;pre name="code" class="groovy"&gt;compileScala.taskDependencies.values = compileScala.taskDependencies.values - 'compileJava'&lt;br /&gt;compileJava.dependsOn compileScala&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;The first line removes the task dependency on the compileJava task from the compileScala task. The second line makes the compileJava task depend on compileScala.&lt;/p&gt;&lt;p&gt;For the Java source to be available for cross compilation the directory needs to in a "sourceSet" for the Gradle Scala plugin. For example, if the Java class is in 'src/main/java' then the following will need to be included in build.gradle:&lt;/p&gt;&lt;pre name="code" class="groovy"&gt;sourceSets {&lt;br /&gt;    main {&lt;br /&gt;        scala {&lt;br /&gt;            srcDir 'src/main/java'&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Using this arrangement a project with mutual dependencies like the example above should be buildable with Gradle.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7017894832730513527-1425854981544142454?l=compulsiontocode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://compulsiontocode.blogspot.com/feeds/1425854981544142454/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7017894832730513527&amp;postID=1425854981544142454' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7017894832730513527/posts/default/1425854981544142454'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7017894832730513527/posts/default/1425854981544142454'/><link rel='alternate' type='text/html' href='http://compulsiontocode.blogspot.com/2011/05/fixing-gradle-compilescala-to-not.html' title='Fixing Gradle compileScala to not depend on compileJava'/><author><name>tdalton</name><uri>http://www.blogger.com/profile/13151512717871227421</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://4.bp.blogspot.com/-c8KSZCmTdpI/TbmtJ04pIUI/AAAAAAAAAEM/AEmlqBQ4ecM/s220/tim.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7017894832730513527.post-3819457853201905283</id><published>2011-05-18T22:47:00.001-05:00</published><updated>2011-06-24T22:52:05.284-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='gradle'/><category scheme='http://www.blogger.com/atom/ns#' term='scala'/><title type='text'>Enable a Scala compiler plugin using Gradle</title><content type='html'>&lt;p&gt;Having recently switched a Scala project to Gradle for building, I was faced with the difficulty of figuring out how to enable the Scala continuation plugin during the compileScala task. Below is a general solution I came up with. Hopefully it will be helpful for others and save someone some time.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;pre name="code" class="groovy"&gt;apply plugin: 'scala'&lt;br /&gt;...&lt;br /&gt;configurations {&lt;br /&gt;  scalaCompilerPlugins { transitive = false }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;dependencies {&lt;br /&gt;...&lt;br /&gt;    scalaCompilerPlugins 'org.scala-lang.plugins:continuations:2.9.0' &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;def scalacXPlugins() {&lt;br /&gt;     return ((configurations.scalaCompilerPlugins.files.collect { "\"-Xplugin:${it.path}\"" }))&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;compileScala.scalaCompileOptions.additionalParameters = scalacXPlugins() + ['-P:continuations:enable']&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;ul&gt;Note:&lt;li&gt;The "transitive = false" in the configurations block prevents dependencies of the plugin as being treated as plugins themselves. Namely, the Scala compiler and library.&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7017894832730513527-3819457853201905283?l=compulsiontocode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://compulsiontocode.blogspot.com/feeds/3819457853201905283/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7017894832730513527&amp;postID=3819457853201905283' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7017894832730513527/posts/default/3819457853201905283'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7017894832730513527/posts/default/3819457853201905283'/><link rel='alternate' type='text/html' href='http://compulsiontocode.blogspot.com/2011/05/enable-scala-compiler-plugin-using.html' title='Enable a Scala compiler plugin using Gradle'/><author><name>tdalton</name><uri>http://www.blogger.com/profile/13151512717871227421</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://4.bp.blogspot.com/-c8KSZCmTdpI/TbmtJ04pIUI/AAAAAAAAAEM/AEmlqBQ4ecM/s220/tim.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7017894832730513527.post-3804526931051428149</id><published>2010-10-29T06:50:00.010-05:00</published><updated>2010-10-29T08:15:24.620-05:00</updated><title type='text'>Code Kata for Parallel Programming</title><content type='html'>&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;One of the keynote presentations at the &lt;a href="http://strangeloop2010.com/"&gt;Strange Loop 2010&lt;/a&gt; conference in St. Louis was&lt;br /&gt;&lt;a href=http://labs.oracle.com/people/mybio.php?uid=25706"&gt;Guy Steele's&lt;/a&gt; "&lt;a href="http://strangeloop2010.com/talks/14299"&gt;How to Think about Parallel Programming: Not!."&lt;/a&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;One of the examples in the presentation was counting words in a presumably large text file. He showed example code in &lt;a href="http://projectfortress.sun.com/Projects/Community"&gt;Fortress&lt;/a&gt; of how one could go about taking a "divide-and-conquer" approach to the problem. This approach would divide the work into chunks that could be processed in parallel and then the outputs would be aggregated to form the solution.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Noticing some of the syntactic similarities between Fortress and &lt;a href="http://www.scala-lang.org/"&gt;Scala&lt;/a&gt;, I had the impulse to implement a solution in Scala. During &lt;a href="http://blog.polyglotprogramming.com/"&gt;Dean Wampler's&lt;/a&gt; "&lt;a href="http://strangeloop2010.com/talks/14477"&gt;Scalable Concurrent Applications with Akka and Scala&lt;/a&gt;" talk, I got the idea that that would make a good &lt;a href="http://codekata.pragprog.com/"&gt;code kata&lt;/a&gt; to use and learn &lt;a href="http://www.akkasource.org/"&gt;Akka&lt;/a&gt;.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;My final idea for the kata modifies the problem from counting words to finding sequences of digits where the last digit is the sum of its immediately preceding digits of any length. The input would be stream of non-zero digits. For example, the content below contains sequences "1326", "415", "246" and "617".&lt;br /&gt;&lt;pre align="center"&gt;&lt;br /&gt;8745648184845171326578518184151512461752149647129746915414816354846454&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Such "sum sequences" should be listed only once in the solution and in the order they are found in the input. Limiting the input to non-zero digits simplifies the problem a little bit since many consecutive zeros would produce a solution that will grow exponentially.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;My initial implementations for this will use Scala and Akka including one using remote actors. Over the coming months, I hope to have time to implement solutions in other languages, such as F#, Clojure and Erlang, using their various parallel programming / concurrency libraries. Hopefully others will find this problem compelling and implement such solutions as well.&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7017894832730513527-3804526931051428149?l=compulsiontocode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://compulsiontocode.blogspot.com/feeds/3804526931051428149/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7017894832730513527&amp;postID=3804526931051428149' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7017894832730513527/posts/default/3804526931051428149'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7017894832730513527/posts/default/3804526931051428149'/><link rel='alternate' type='text/html' href='http://compulsiontocode.blogspot.com/2010/10/code-kata-for-parallel-programming.html' title='Code Kata for Parallel Programming'/><author><name>tdalton</name><uri>http://www.blogger.com/profile/13151512717871227421</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://4.bp.blogspot.com/-c8KSZCmTdpI/TbmtJ04pIUI/AAAAAAAAAEM/AEmlqBQ4ecM/s220/tim.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7017894832730513527.post-2771961972245449181</id><published>2009-06-09T08:41:00.018-05:00</published><updated>2010-04-20T12:58:20.677-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='functional programming'/><category scheme='http://www.blogger.com/atom/ns#' term='scala'/><title type='text'>A Refactoring in Scala</title><content type='html'>&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;One pet project I have going is a little Logo interpreter done using Scala parser combinators with a Swing GUI where code can be edited and executed with results being rendered on a canvas. Being a good little Agile developer, I wrote automated tests for it&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;I've had experience on a previous Swing project using the Netbeans Jemmy library for driving the GUI tests in Java. I was curious of what Scala can wrap around such testing libraries like Jemmy. Initially, the test code was more Java style than Scala since I've only used Jemmy with Java previously. I found that interesting refactorings can be applied as the code takes on the more functional style of Scala.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Experienced Scala developers are probably familiar with these concepts, so the intended audience is developers who are relatively new to Scala and insights into why Scala code is the way it is.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;As I was developing the tests, I needed to programatically find buttons on a toolbar that do such things as "New", "Save", "Load", and "Execute". These buttons don't have text, so I am using the tooltip to distinguish them. A Java-style Scala function to do this would look like this:&lt;/p&gt;&lt;br /&gt;&lt;pre name="code" class="scala"&gt;&lt;br /&gt;def findJButton(container:Container, toolTipText:String) = {&lt;br /&gt;    val button = JButtonOperator.findJButton(container, &lt;br /&gt;        new ComponentChooser() {&lt;br /&gt;            override def checkComponent(component:Component) = &lt;br /&gt;                if (component.getClass.isAssignableFrom(classOf[JButton])) {&lt;br /&gt;                    component.asInstanceOf[JButton].getToolTipText == toolTipText&lt;br /&gt;                } else {&lt;br /&gt;                    false&lt;br /&gt;                }&lt;br /&gt;            override def getDescription() = "JButton Finder using toolTipText"&lt;br /&gt;         }&lt;br /&gt;    )&lt;br /&gt;    if (button == null) {&lt;br /&gt;        fail("cannot find JButton with tooltip = '" + toolTipText + "'")&lt;br /&gt;    }&lt;br /&gt;    new JButtonOperator(button)&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Client code:&lt;/p&gt;&lt;br /&gt;&lt;pre name="code" class="scala"&gt;&lt;br /&gt;val newButtonOper = findJButton(frmOper.getContentPane, "Start new Logo program" )&lt;br /&gt;val runButtonOper = findJButton(frmOper.getContentPane, "Run Logo program")&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;The "*Operator" classes in Jemmy wraps corresponding Swing components so that can be programatically manipulated in the same way an actual user would. The frmOper object is a Jemmy JFrameOperator that wraps the main frame of the application.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Now in Java, one can refactor the inner class into a regular class and leverage generics so that it can match any JComponent subtype since that is where getToolTipText is first implemented. In Scala, we will do something like that and make it so that a higher order function can be passed in the do the comparison provided the component is the correct type:&lt;/p&gt;&lt;br /&gt;&lt;pre name="code" class="scala"&gt;&lt;br /&gt;class LoanChooser[A &lt;: java.awt.Component](clazz: Class[A], filter: A =&gt; Boolean) &lt;br /&gt;    extends ComponentChooser&lt;br /&gt;{&lt;br /&gt;    override def checkComponent(component:Component) = &lt;br /&gt;        if (component.getClass.isAssignableFrom(clazz)) {&lt;br /&gt;            filter(component.asInstanceOf[A])&lt;br /&gt;        } else {&lt;br /&gt;            false&lt;br /&gt;        }&lt;br /&gt;    override def getDescription() = "Generic Finder using Loan Pattern"&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;def findJButton(container:Container, filter: JButton =&gt; Boolean) = {&lt;br /&gt;    val button = JButtonOperator.findJButton(container,&lt;br /&gt;                        new LoanChooser(classOf[JButton], filter))&lt;br /&gt;    if (button == null) {&lt;br /&gt;        fail("cannot find JButton with matching criteria")&lt;br /&gt;    }&lt;br /&gt;    new JButtonOperator(button)&lt;br /&gt;} &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Client code:&lt;/p&gt;&lt;br /&gt;&lt;pre name="code" class="scala"&gt;&lt;br /&gt;val newButtonOper = findJButton(frmOper.getContentPane, btn =&gt; btn.getToolTipText == "Start new Logo program" )&lt;br /&gt;val runButtonOper = findJButton(frmOper.getContentPane, btn =&gt; btn.getToolTipText == "Run Logo program")&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;The code above uses the "Loan Pattern" in Scala (&lt;a href="http://scala.sygneca.com/patterns/loan"&gt;http://scala.sygneca.com/patterns/loan&lt;/a&gt;). The client code is loaned the the JButton instance so it can be tested to see if it matches the criteria.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Knowing the Scala implements functions as objects, I know that two identical anonymous function classes are going be created in the form "JButton =&gt; Boolean", so I create a common function that can be curried (or partially applied) with the toolTipText as the first parameter:&lt;br /&gt;&lt;pre name="code" class="scala"&gt;&lt;br /&gt;def toolTipTextEquals(toolTipText:String)(component:JComponent) = component.getToolTipText == toolTipText&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre name="code" class="scala"&gt;&lt;br /&gt;val newButtonOper = findJButton(frmOper.getContentPane, toolTipTextEquals("Start new Logo program"))&lt;br /&gt;val runButtonOper = findJButton(frmOper.getContentPane, toolTipTextEquals("Run Logo program"))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Now is getting pretty obvious what the code is trying to accomplish. There are some repeated code patterns that can be refactored out. At this point, it probably more at matter of taste in that some will want to refactor more and others might see it an an exercise in of "Scala Golf" (&lt;a href="http://codegolf.com/"&gt;http://codegolf.com/&lt;/a&gt;). First we can get rid of the repeated "frmOper.getContentPane" by the traditional means of temporary local variable:&lt;/p&gt;&lt;pre name="code" class="scala"&gt;&lt;br /&gt;val contentPane = frmOper.getContentPane&lt;br /&gt;val newButtonOper = findJButton(contentPane, toolTipTextEquals("Start new Logo program"))&lt;br /&gt;val runButtonOper = findJButton(contentPane, toolTipTextEquals("Run Logo program"))&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Or use an implicit conversion:&lt;/p&gt;&lt;br /&gt;&lt;pre name="code" class="scala"&gt;&lt;br /&gt;implicit def jFrameOperator2Container(frmOper:JFrameOperator) = frmOper.getContentPane&lt;br /&gt;&lt;/pre&gt;&lt;pre name="code" class="scala"&gt;&lt;br /&gt;val newButtonOper = findJButton(frmOper, toolTipTextEquals("Start new Logo program"))&lt;br /&gt;val runButtonOper = findJButton(frmOper, toolTipTextEquals("Run Logo program"))&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;The implicit conversion is invoked since the findJButton function it expecting a Container as the first param, but is provided a JFrameOperator. Since there is an implicit function in scope in the form "JFrameOperator =&gt; Container", it is used to perform the conversion implicitly.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;My Logo application currently has four buttons on a toolbar that will need to be tested and I'll need JButtonOperators for all of them:&lt;/p&gt;&lt;pre name="code" class="scala"&gt;&lt;br /&gt;val newButtonOper = findJButton(frmOper, toolTipTextEquals("Start new Logo program"))&lt;br /&gt;val openButtonOper = findJButton(frmOper, toolTipTextEquals("Open existing .logo file"))&lt;br /&gt;val saveButtonOper = findJButton(frmOper, toolTipTextEquals("Save current logo code to file"))&lt;br /&gt;val runButtonOper = findJButton(frmOper, toolTipTextEquals("Run Logo program"))&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Once can utilize Scala's ability to deconstruct on patterns during declarations and do this:&lt;/p&gt;&lt;pre name="code" class="scala"&gt;&lt;br /&gt;val List(newButtonOper, openButtonOper, saveButtonOper, runButtonOper) = &lt;br /&gt;    List("Start new Logo program",&lt;br /&gt;         "Open existing .logo file",&lt;br /&gt;         "Save current logo code to file",&lt;br /&gt;      "Run Logo program").map(toolTipText =&gt; findJButton(frmOper, toolTipTextEquals(toolTipText)))&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;It is a matter of taste whether four buttons warrant such refactoring, but if the code started to look unwieldy and I didn't want to keep them in some kind of collection, I would definitely consider this approach.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;I felt this recent experience refactoring Scala code was interesting enough to blog about it and hope that readers gain some insight from this and want to use Scala more. I feel that Scala or at least a language with many of its features (like some kind of "Scala--") will play a big role on the JVM platform going forward.&lt;/p&gt; &lt;br /&gt;&lt;b&gt;Sidebar: Whither SQUIB&lt;/b&gt;&lt;br /&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;I haven't done much with the SQUIB project recently. I am seeing too many drawbacks to its approach:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Property resolution done at runtime - If the property is misspelled or uses an invalid type the best thing to do is fail fast and throw an exception. It would be nice if such issues could be detected at compile time at least.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Lack of IDE support - It would be nice if a framework uses actual methods that an IDE could then provide auto-completion and the like.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;It's just a little heavyweight: I've found that very useful things can be done in Scala with minimal code.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7017894832730513527-2771961972245449181?l=compulsiontocode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://compulsiontocode.blogspot.com/feeds/2771961972245449181/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7017894832730513527&amp;postID=2771961972245449181' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7017894832730513527/posts/default/2771961972245449181'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7017894832730513527/posts/default/2771961972245449181'/><link rel='alternate' type='text/html' href='http://compulsiontocode.blogspot.com/2009/06/refactoring-in-scala.html' title='A Refactoring in Scala'/><author><name>tdalton</name><uri>http://www.blogger.com/profile/13151512717871227421</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://4.bp.blogspot.com/-c8KSZCmTdpI/TbmtJ04pIUI/AAAAAAAAAEM/AEmlqBQ4ecM/s220/tim.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7017894832730513527.post-3988381674517780084</id><published>2009-03-10T21:56:00.012-05:00</published><updated>2009-03-14T22:04:30.246-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='functional programming'/><category scheme='http://www.blogger.com/atom/ns#' term='fsharp'/><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><title type='text'>Bowling in Yet Another Language (F#)</title><content type='html'>Another day, another blog posting involving bowling and a functional programming language. This one is in F#, which is very interesting language for the .NET platform. Code:&lt;br /&gt;&lt;pre name="code" class="fsharp"&gt;&lt;br /&gt;#light&lt;br /&gt;&lt;br /&gt;module Bowling &lt;br /&gt;&lt;br /&gt;open System;;&lt;br /&gt;&lt;br /&gt;let scoreToInt x = &lt;br /&gt;    match x with&lt;br /&gt;        Some y -&gt; y&lt;br /&gt;        | None -&gt; -1;;&lt;br /&gt;&lt;br /&gt;let rec tallyScores accum x = &lt;br /&gt;    match x with&lt;br /&gt;        [] -&gt; []&lt;br /&gt;        | x::rest -&gt;    let score = scoreToInt x in&lt;br /&gt;                        if (score &gt;= 0) then&lt;br /&gt;                            let total = (accum + score) in total :: tallyScores total rest;&lt;br /&gt;                        else&lt;br /&gt;                            [];;&lt;br /&gt;&lt;br /&gt;let rec take n l =&lt;br /&gt;    if (n &gt; 0) then&lt;br /&gt;        match l with&lt;br /&gt;            x::rest -&gt; let newn = n-1 in x :: take newn rest&lt;br /&gt;            |       [] -&gt; []&lt;br /&gt;        else&lt;br /&gt;            [];;&lt;br /&gt;&lt;br /&gt;let rec reduce f ys = &lt;br /&gt;    if ys &lt;&gt; [] then&lt;br /&gt;        let (x, ys') = f ys in x::reduce f ys'&lt;br /&gt;    else [];;&lt;br /&gt;&lt;br /&gt;let scoreFrame rolls = &lt;br /&gt;    match rolls with&lt;br /&gt;        x1::x2::x3::rest -&gt; if (x1 = 10) then (Some (x1+x2+x3), x2::x3::rest)&lt;br /&gt;                            else if (x1 + x2 = 10) then&lt;br /&gt;                                (Some (x1+x2+x3), x3::rest)&lt;br /&gt;                            else (Some(x1+x2), x3::rest)&lt;br /&gt;        |   x1::x2::[] -&gt;   if (x1 + x2 &lt; 10) then&lt;br /&gt;                                (Some(x1 + x2), [])&lt;br /&gt;                            else (None, []);&lt;br /&gt;        |   _ -&gt;            (None, []);;&lt;br /&gt;                            &lt;br /&gt;let scoreTenFrames rolls =&lt;br /&gt;    take 10 (reduce scoreFrame rolls);;&lt;br /&gt;    &lt;br /&gt;let tallyGame rolls = &lt;br /&gt;    tallyScores 0 (scoreTenFrames rolls);;&lt;br /&gt;    &lt;br /&gt;let printGame rolls = &lt;br /&gt;    List.iter (fun x -&gt; Console.Write(int x); Console.Write " ") (tallyGame rolls);&lt;br /&gt;        Console.Write "\n";;&lt;br /&gt;    &lt;br /&gt;let assertTrue expression = &lt;br /&gt;    if (expression = false) then &lt;br /&gt;        failwith "Assertion Not True";;&lt;br /&gt; &lt;br /&gt;assertTrue ([30;60;90;120;150;180;210;240;270;300] = tallyGame[10;10;10;10;10;10;10;10;10;10;10;10]);;&lt;br /&gt;assertTrue ([30;60;90;120;150;180;210;240;270;299] = tallyGame[10;10;10;10;10;10;10;10;10;10;10;9]);;&lt;br /&gt;assertTrue ([30;60;90;120;150;180;210;240;270;290] = tallyGame[10;10;10;10;10;10;10;10;10;10;10;0]);;&lt;br /&gt;assertTrue ([20;50;80;110;140;170;200;230;260;290] = tallyGame[9;1;10;10;10;10;10;10;10;10;10;10;10]);;&lt;br /&gt;assertTrue ([30;60;90;120;150;180;210;240;269;289] = tallyGame[10;10;10;10;10;10;10;10;10;10;9;1]);;&lt;br /&gt;assertTrue ([30;60;90;120;150;180;210;240;269;288] = tallyGame[10;10;10;10;10;10;10;10;10;10;9;0]);;&lt;br /&gt;assertTrue ([30;60;90;120;150;180;210;240;260;280] = tallyGame[10;10;10;10;10;10;10;10;10;10;0;10]);;&lt;br /&gt;assertTrue ([20;40;70;100;130;160;190;220;250;280] = tallyGame[10;9;1;10;10;10;10;10;10;10;10;10;10]);;&lt;br /&gt;assertTrue ([30;60;90;120;150;180;210;239;259;279] = tallyGame[10;10;10;10;10;10;10;10;10;9;1;10]);;&lt;br /&gt;assertTrue ([30;60;90;120;150;180;210;240;260;270] = tallyGame[10;10;10;10;10;10;10;10;10;10;0;0]);;&lt;br /&gt;assertTrue ([20;40;60;80;100;120;140;160;180;200] = tallyGame[10;9;1;10;9;1;10;9;1;10;9;1;10;9;1;10]);;&lt;br /&gt;assertTrue ([19;38;57;76;95;114;133;152;171;190] = tallyGame[9;1;9;1;9;1;9;1;9;1;9;1;9;1;9;1;9;1;9;1;9]);;&lt;br /&gt;assertTrue ([19;38;57;76;95;114;133;152;171;180] = tallyGame[9;1;9;1;9;1;9;1;9;1;9;1;9;1;9;1;9;1;9;0]);;&lt;br /&gt;// Partial games&lt;br /&gt;assertTrue ([] = tallyGame[]);;&lt;br /&gt;assertTrue ([] = tallyGame[0]);;&lt;br /&gt;assertTrue ([] = tallyGame[9]);;&lt;br /&gt;assertTrue ([] = tallyGame[10]);;&lt;br /&gt;assertTrue ([] = tallyGame[9;1]);;&lt;br /&gt;assertTrue ([] = tallyGame[10; 9]);;&lt;br /&gt;assertTrue ([] = tallyGame[10; 10]);;&lt;br /&gt;assertTrue ([0] = tallyGame[0; 0]);;&lt;br /&gt;assertTrue ([1] = tallyGame[0; 1]);;&lt;br /&gt;assertTrue ([9] = tallyGame[8; 1]);;&lt;br /&gt;assertTrue ([9] = tallyGame[9; 0]);;&lt;br /&gt;assertTrue ([19] = tallyGame[9; 1; 9]);;&lt;br /&gt;assertTrue ([19; 28] = tallyGame[10; 9; 0]);;&lt;br /&gt;assertTrue ([19; 28] = tallyGame[9; 1; 9; 0]);;&lt;br /&gt;assertTrue ([20] = tallyGame[10; 9; 1]);;&lt;br /&gt;assertTrue ([30] = tallyGame[10; 10; 10]);;&lt;br /&gt;assertTrue ([30; 59] = tallyGame[10; 10; 10; 9]);;&lt;br /&gt;assertTrue ([30; 59; 78; 87] = tallyGame[10; 10; 10; 9; 0]);;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Note that I've included a quick and dirty assertTrue method to validate the functions.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;The above example can be used via the interactive shell (fsi) like below:&lt;/p&gt;&lt;br /&gt;&lt;pre class="command-prompt"&gt;&lt;br /&gt;C:\DotNET\src&gt;fsi&lt;br /&gt;&lt;br /&gt;Microsoft F# Interactive, (c) Microsoft Corporation, All Rights Reserved&lt;br /&gt;F# Version 1.9.6.2, compiling for .NET Framework Version v2.0.50727&lt;br /&gt;&lt;br /&gt;Please send bug reports to fsbugs@microsoft.com&lt;br /&gt;For help type #help;;&lt;br /&gt;&lt;br /&gt;&gt; #load "bowling.fs";;&lt;br /&gt;[Loading C:\DotNET\src\bowling.fs]&lt;br /&gt;&lt;br /&gt;namespace FSI_0002&lt;br /&gt;  val scoreToInt : int option -&gt; int&lt;br /&gt;  val tallyScores : int -&gt; int option list -&gt; int list&lt;br /&gt;  val take : int -&gt; 'a list -&gt; 'a list&lt;br /&gt;  val reduce : ('a list -&gt; 'b * 'a list) -&gt; 'a list -&gt; 'b list&lt;br /&gt;  val scoreFrame : int list -&gt; int option * int list&lt;br /&gt;  val scoreTenFrames : int list -&gt; int option list&lt;br /&gt;  val tallyGame : int list -&gt; int list&lt;br /&gt;  val printGame : int list -&gt; unit&lt;br /&gt;  val assertTrue : bool -&gt; unit&lt;br /&gt;&lt;br /&gt;&gt; Bowling.printGame [10; 10; 10; 10; 10; 10; 10; 10; 10; 10; 10; 10];;&lt;br /&gt;30 60 90 120 150 180 210 240 270 300&lt;br /&gt;val it : unit = ()&lt;br /&gt;&gt; Bowling.printGame [10; 9;1; 10; 9;0; 10; 8;2; 10; 10; 9;1; 9;1; 10];;&lt;br /&gt;20 40 59 68 88 108 137 157 176 196&lt;br /&gt;val it : unit = ()&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Each element on the list represents a roll of the ball. The program will figure out which frames the rolls belong to. For example, "[9;1]" represents single frame consisting of a nine count followed by spare of the remaining pin. This implementation assumes valid input and is not designed to handle such things as more than 10 pins in a frame on a negative value for a roll.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7017894832730513527-3988381674517780084?l=compulsiontocode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://compulsiontocode.blogspot.com/feeds/3988381674517780084/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7017894832730513527&amp;postID=3988381674517780084' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7017894832730513527/posts/default/3988381674517780084'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7017894832730513527/posts/default/3988381674517780084'/><link rel='alternate' type='text/html' href='http://compulsiontocode.blogspot.com/2009/03/bowling-in-yet-another-language-f.html' title='Bowling in Yet Another Language (F#)'/><author><name>tdalton</name><uri>http://www.blogger.com/profile/13151512717871227421</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://4.bp.blogspot.com/-c8KSZCmTdpI/TbmtJ04pIUI/AAAAAAAAAEM/AEmlqBQ4ecM/s220/tim.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7017894832730513527.post-942933592814202030</id><published>2009-02-10T12:30:00.006-06:00</published><updated>2009-12-22T22:47:43.841-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='functional programming'/><category scheme='http://www.blogger.com/atom/ns#' term='clojure'/><title type='text'>Bowling with Clojure</title><content type='html'>Having an interest in function programming languages (notably Scala), I decided to take a look at &lt;a href="http://clojure.org/"&gt;Clojure&lt;/a&gt;. In a nutshell, Clojure is a LISP variant that runs on the Java Virtual Machine and hence enjoys access to all libraries therein. &lt;br /&gt;One of my favorite simple &lt;a href="http://codekata.pragprog.com/"&gt;code katas&lt;/a&gt; with functional languages is to tally up bowling scores. Previously, I had done this with &lt;a href="http://compulsiontocode.blogspot.com/2007/05/bowling-with-erlang-and-scala.html"&gt;Erlang and Scala&lt;/a&gt;. Here is a Clojure version of the same including some tests:&lt;br /&gt;&lt;pre name="code" class="clojure"&gt;(defn score-frame [rolls]&lt;br /&gt;    (let [[x1 x2 x3] rolls]&lt;br /&gt;        (cond   &lt;br /&gt;            (nil? x1)           nil  &lt;br /&gt;            (nil? x2)           nil                         &lt;br /&gt;            (nil? x3)           (let [sumx (+ x1 x2)] &lt;br /&gt;                                    (if (&lt; sumx 10) (list sumx)))       ; open at end of game                                                   &lt;br /&gt;            (= x1 10)           (cons (+ x1 x2 x3) (rest rolls))        ; strike  &lt;br /&gt;            (= (+ x1 x2) 10)    (cons (+ x1 x2 x3)  (nthrest rolls 2))  ; spare  &lt;br /&gt;            (&lt; (+ x1 x2) 10)    (cons (+ x1 x2) (nthrest rolls 2))      ; open  &lt;br /&gt;            (true) nil  &lt;br /&gt;        )&lt;br /&gt;    )&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;(defn roll-reduce [remaining-rolls]  &lt;br /&gt;    (if (not (= nil remaining-rolls))&lt;br /&gt;        (let [result (score-frame remaining-rolls)]&lt;br /&gt;        (if (not (= nil result)) &lt;br /&gt;            (cons (first result) (roll-reduce (rest result))))))&lt;br /&gt;)        &lt;br /&gt;&lt;br /&gt;(defn score-ten-frames [rolls]&lt;br /&gt; (take 10 (roll-reduce rolls)))&lt;br /&gt;&lt;br /&gt;(defn tally-game [accum scores]&lt;br /&gt;    (if (&gt; (count scores) 0) (let [new_accum (+ accum (first scores))] (cons new_accum (tally-game new_accum (rest scores)))))&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;(defn score-game [rolls]&lt;br /&gt;    (tally-game 0 (score-ten-frames rolls))&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;(assert (= '(30 60 90 120 150 180 210 240 270 300) (score-game '(10 10 10 10 10 10 10 10 10 10 10 10))))&lt;br /&gt;(assert (= '(30 60 90 120 150 180 210 240 270 299) (score-game '(10 10 10 10 10 10 10 10 10 10 10 9))))&lt;br /&gt;(assert (= '(30 60 90 120 150 180 210 240 270 290) (score-game '(10 10 10 10 10 10 10 10 10 10 10 0))))&lt;br /&gt;(assert (= '(20 50 80 110 140 170 200 230 260 290) (score-game '(9 1 10 10 10 10 10 10 10 10 10 10 10))))&lt;br /&gt;(assert (= '(30 60 90 120 150 180 210 240 269 289) (score-game '(10 10 10 10 10 10 10 10 10 10 9 1))))&lt;br /&gt;(assert (= '(30 60 90 120 150 180 210 240 269 288) (score-game '(10 10 10 10 10 10 10 10 10 10 9 0))))&lt;br /&gt;(assert (= '(30 60 90 120 150 180 210 240 260 280) (score-game '(10 10 10 10 10 10 10 10 10 10 0 10))))&lt;br /&gt;(assert (= '(20 40 70 100 130 160 190 220 250 280) (score-game '(10 9 1 10 10 10 10 10 10 10 10 10 10))))&lt;br /&gt;(assert (= '(30 60 90 120 150 180 210 239 259 279) (score-game '(10 10 10 10 10 10 10 10 10 9 1 10))))&lt;br /&gt;(assert (= '(30 60 90 120 150 180 210 240 260 270) (score-game '(10 10 10 10 10 10 10 10 10 10 0 0))))&lt;br /&gt;(assert (= '(20 40 60 80 100 120 140 160 180 200) (score-game '(10 9 1 10 9 1 10 9 1 10 9 1 10 9 1 10))))&lt;br /&gt;(assert (= '(19 38 57 76 95 114 133 152 171 190) (score-game '(9 1 9 1 9 1 9 1 9 1 9 1 9 1 9 1 9 1 9 1 9))))&lt;br /&gt;(assert (= '(19 38 57 76 95 114 133 152 171 180) (score-game '(9 1 9 1 9 1 9 1 9 1 9 1 9 1 9 1 9 1 9 0))))&lt;br /&gt;(assert (= '(0 0 0 0 0 0 0 0 0 0) (score-ten-frames '(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0))))&lt;br /&gt;&lt;br /&gt;; Partial games&lt;br /&gt;(assert (= nil (score-game nil)))&lt;br /&gt;(assert (= nil (score-game '(0))))&lt;br /&gt;(assert (= nil (score-game '(9))))&lt;br /&gt;(assert (= nil (score-game '(10))))&lt;br /&gt;(assert (= nil (score-game '(9 1))))&lt;br /&gt;(assert (= nil (score-game '(10 10))))&lt;br /&gt;(assert (= '(0) (score-game '(0 0)))) &lt;br /&gt;(assert (= '(1) (score-game '(0 1))))&lt;br /&gt;(assert (= '(9) (score-game '(8 1))))&lt;br /&gt;(assert (= '(9) (score-game '(9 0))))&lt;br /&gt;(assert (= '(19) (score-game '(9 1 9))))&lt;br /&gt;(assert (= '(19 28) (score-game '(10 9 0))))&lt;br /&gt;(assert (= '(19 28) (score-game '(9 1 9 0))))&lt;br /&gt;(assert (= '(20) (score-game '(10 9 1))))&lt;br /&gt;(assert (= '(30) (score-game '(10 10 10))))&lt;br /&gt;(assert (= '(30 59) (score-game '(10 10 10 9))))&lt;br /&gt;(assert (= '(30 59 78 87) (score-game '(10 10 10 9 0))))&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;i&gt;Note this code has been updated since initial posting to incorporate changes based on feedback in a comment from Mark Volkmann below. Mark has published an excellent overview of Clojure here, &lt;a href="http://www.ociweb.com/jnb/jnbMar2009.html"&gt;http://www.ociweb.com/jnb/jnbMar2009.html&lt;/a&gt;&lt;/i&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;a href="http://sites.google.com/site/compulsiontocode/code/bowling.clj"&gt;Link to code&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;b&gt;Example:&lt;/b&gt;&lt;br /&gt;&lt;pre class="command-prompt"&gt;C:\lang\clojure&gt;java -jar clojure.jar bowling.clj&lt;br /&gt;Clojure&lt;br /&gt;user=&gt; (score-game '(10 10 10 10 10 10 10 10 10 10 10 10))&lt;br /&gt;(30 60 90 120 150 180 210 240 270 300)&lt;br /&gt;user=&gt; (score-game '(10 10 10 10 10 10 10 10 10 10 10 9))&lt;br /&gt;(30 60 90 120 150 180 210 240 270 299)&lt;br /&gt;user=&gt; (score-game '(10 10 10 10 10 10 10 10 10 10 9 1))&lt;br /&gt;(30 60 90 120 150 180 210 240 269 289)&lt;br /&gt;user=&gt; (score-game '(10 10 10 10 10 10 10 10 10 9 1 10))&lt;br /&gt;(30 60 90 120 150 180 210 239 259 279)&lt;br /&gt;user=&gt; (score-game '(10 10 10 10 10 10 10 10 10 9 0))&lt;br /&gt;(30 60 90 120 150 180 210 239 258 267)&lt;br /&gt;user=&gt; (score-game '(9 0 10 10 10 10 10 10 10 10 10 10 10))&lt;br /&gt;(9 39 69 99 129 159 189 219 249 279)&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7017894832730513527-942933592814202030?l=compulsiontocode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://compulsiontocode.blogspot.com/feeds/942933592814202030/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7017894832730513527&amp;postID=942933592814202030' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7017894832730513527/posts/default/942933592814202030'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7017894832730513527/posts/default/942933592814202030'/><link rel='alternate' type='text/html' href='http://compulsiontocode.blogspot.com/2009/01/bowling-with-clojure.html' title='Bowling with Clojure'/><author><name>tdalton</name><uri>http://www.blogger.com/profile/13151512717871227421</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://4.bp.blogspot.com/-c8KSZCmTdpI/TbmtJ04pIUI/AAAAAAAAAEM/AEmlqBQ4ecM/s220/tim.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7017894832730513527.post-8807730338808563488</id><published>2008-05-19T12:44:00.002-05:00</published><updated>2008-05-19T12:48:00.253-05:00</updated><title type='text'>SQUIB Google Group</title><content type='html'>I should have done this a while ago. I've created a Google Group for discussion about the SQUIB project:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://groups.google.com/group/scala-squib"&gt;http://groups.google.com/group/scala-squib&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7017894832730513527-8807730338808563488?l=compulsiontocode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://compulsiontocode.blogspot.com/feeds/8807730338808563488/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7017894832730513527&amp;postID=8807730338808563488' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7017894832730513527/posts/default/8807730338808563488'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7017894832730513527/posts/default/8807730338808563488'/><link rel='alternate' type='text/html' href='http://compulsiontocode.blogspot.com/2008/05/squib-google-group.html' title='SQUIB Google Group'/><author><name>tdalton</name><uri>http://www.blogger.com/profile/13151512717871227421</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://4.bp.blogspot.com/-c8KSZCmTdpI/TbmtJ04pIUI/AAAAAAAAAEM/AEmlqBQ4ecM/s220/tim.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7017894832730513527.post-8920708185357476022</id><published>2008-03-06T12:30:00.000-06:00</published><updated>2008-12-10T03:26:24.496-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='squib'/><category scheme='http://www.blogger.com/atom/ns#' term='scala'/><title type='text'>SQUIB demos now "Web Start-able"</title><content type='html'>&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;p&gt;I've packaged and signed the SQUIB libraries and the Scala 2.6.1 runtime to enable demos to executed via Java Web Start. My ISP doesn't send the appropriate MIME type to launch Web Start from JNLP links. To get around this, one can save the link to a local drive and (if they have the right file associations) launch the application. Another way, would be to use the command line using "javaws &amp;lt;JNLP URL&amp;gt;". Java version 1.5 or newer is required to launch these demos.&lt;/p&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;p&gt;The first is the Scene Graph Intro program from a prior post, &lt;a href="http://compulsiontocode.blogspot.com/2008/02/squib-kicks-part-1.html"&gt;http://compulsiontocode.blogspot.com/2008/02/squib-kicks-part-1.html&lt;/a&gt;:&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&lt;a href="http://webpages.charter.net/daltontk/scala/scala_scenegraph_intro.jnlp"&gt;http://webpages.charter.net/daltontk/scala/scala_scenegraph_intro.jnlp&lt;/a&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;p&gt;&lt;br /&gt;The second is a simple picture viewer inspired by the animated rotation done by Google Picasa. Image rotation is animated and done in 90 degree increments using translucent buttons in upper left corner of the image. Use the mouse wheel to zoom in and out.&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&lt;a href="http://webpages.charter.net/daltontk/scala/scala_squib_pictureviewer.jnlp"&gt;http://webpages.charter.net/daltontk/scala/scala_squib_pictureviewer.jnlp&lt;/a&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;Link to source:&lt;br/&gt;&lt;br /&gt;&lt;a href="http://scala-squib.googlecode.com/svn/trunk/demo/src/tfd/scala/squib/demo/scenegraph/PictureViewer.scala"&gt;http://scala-squib.googlecode.com/svn/trunk/demo/src/tfd/scala/squib/demo/scenegraph/PictureViewer.scala&lt;/a&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;Screenshot:&lt;br/&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_UDmxiqUyDAo/R9GR9ny_G6I/AAAAAAAAACg/2f8XtIrxGFk/s1600-h/SQUIBPictureViewer.JPG"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_UDmxiqUyDAo/R9GR9ny_G6I/AAAAAAAAACg/2f8XtIrxGFk/s320/SQUIBPictureViewer.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5175077934666292130" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7017894832730513527-8920708185357476022?l=compulsiontocode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://compulsiontocode.blogspot.com/feeds/8920708185357476022/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7017894832730513527&amp;postID=8920708185357476022' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7017894832730513527/posts/default/8920708185357476022'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7017894832730513527/posts/default/8920708185357476022'/><link rel='alternate' type='text/html' href='http://compulsiontocode.blogspot.com/2008/03/squib-demos-now-web-start-able.html' title='SQUIB demos now &quot;Web Start-able&quot;'/><author><name>tdalton</name><uri>http://www.blogger.com/profile/13151512717871227421</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://4.bp.blogspot.com/-c8KSZCmTdpI/TbmtJ04pIUI/AAAAAAAAAEM/AEmlqBQ4ecM/s220/tim.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_UDmxiqUyDAo/R9GR9ny_G6I/AAAAAAAAACg/2f8XtIrxGFk/s72-c/SQUIBPictureViewer.JPG' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7017894832730513527.post-7137022224923979841</id><published>2008-02-24T22:18:00.004-06:00</published><updated>2009-02-10T12:13:26.441-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='squib'/><category scheme='http://www.blogger.com/atom/ns#' term='scala'/><title type='text'>SQUIB Kicks (Part 1)</title><content type='html'>&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;p&gt;SQUIB (Scala's Quirky User Interface Builder) has been undergoing changes in the last month. New features include support for many event types beyond the simple ActionEvent. Instead of just showing cool things done using SQUIB (That will come later), I want to take a step back and a start a little tutorial on how to use SQUIB.&lt;br /&gt;&lt;/p&gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;p&gt;&lt;br /&gt;SQUIB gets its inspiration from JavaFX, but is not intended to be a clone of it. A design goal of SQUIB is to be lightweight, but enable developers to code GUIs in a more expressive manner with less lines of code. &lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;p&gt;&lt;br /&gt;For this tutorial, I've built a release and made it available at the project home on Google Code. Please download the main library jar, &lt;a href="http://scala-squib.googlecode.com/files/scala_squibV0_4.jar"&gt;http://scala-squib.googlecode.com/files/scala_squibV0_4.jar&lt;/a&gt;.&lt;br /&gt;SQUIB requires Scala 2.6 or later. I've only done basic validation the release candidates for Scala 2.7, but it seems to be working. The examples below will be Scala scripts instead of compiled applications to simplify execution by removing the compile step.&lt;/p&gt;&lt;br /&gt;&lt;b&gt;A "Hello World" frame&lt;/b&gt;&lt;br /&gt;&lt;pre name="code" class="scala"&gt;&lt;br /&gt;import tfd.scala.squib._&lt;br /&gt;&lt;br /&gt;import javax.swing.WindowConstants&lt;br /&gt;&lt;br /&gt;frame(&lt;br /&gt;    attributes( 'title -&gt; "Hello",&lt;br /&gt;                'visible -&gt; true,&lt;br /&gt;                'defaultCloseOperation -&gt; WindowConstants.DISPOSE_ON_CLOSE),&lt;br /&gt;    contents(   &lt;br /&gt;        label(  attributes('text-&gt;"Hello World")    )&lt;br /&gt;    )&lt;br /&gt;).pack&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;a href="http://scala-squib.googlecode.com/svn/trunk/demo/script/helloWorld.scalash"&gt;link&lt;/a&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;p&gt;To execute the script, save the source code to a file (for example "helloWorld.scalash") or download from the link, Ensure the scala_squibV0_4.jar is in the CLASSPATH, and invoke the script using "scala &amp;lt;saved source file&amp;gt;". Screenshot for the first example script:&lt;/p&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_UDmxiqUyDAo/R79F2TuvPlI/AAAAAAAAABg/20dPQtPk25Y/s1600-h/helloWorld.PNG"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_UDmxiqUyDAo/R79F2TuvPlI/AAAAAAAAABg/20dPQtPk25Y/s320/helloWorld.PNG" border="0" alt=""id="BLOGGER_PHOTO_ID_5169927696556179026" /&gt;&lt;/a&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;p&gt;SQUIB uses a helper object, &lt;b&gt;attributes&lt;/b&gt;, to convert variable number of arguments into a list passed into an apply method of an object  that constructs the component. Objects, &lt;b&gt;frame&lt;/b&gt; and &lt;b&gt;label&lt;/b&gt;, are used to construct JFrames and JLabels respectively. Originally, the apply method was overloaded to handle various combination of options. Eventually this got burdensome, so I made the apply methods use pattern matching of variable arguments and pretty much made &lt;b&gt;attributes&lt;/b&gt; optional. For example, the code below doesn't use &lt;b&gt;attributes&lt;/b&gt;:&lt;/p&gt;  &lt;br /&gt;&lt;pre name="code" class="scala"&gt;&lt;br /&gt;import tfd.scala.squib._&lt;br /&gt;&lt;br /&gt;import javax.swing.WindowConstants&lt;br /&gt;&lt;br /&gt;frame(&lt;br /&gt;      'title -&gt; "Hello",&lt;br /&gt;      'visible -&gt; true,&lt;br /&gt;      'defaultCloseOperation -&gt; WindowConstants.DISPOSE_ON_CLOSE,&lt;br /&gt;      contents(&lt;br /&gt;                label('text-&gt;"Hello World Again!"))&lt;br /&gt;).pack&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;a href="http://scala-squib.googlecode.com/svn/trunk/demo/script/helloWorld2.scalash"&gt;link&lt;/a&gt;&lt;br /&gt;Screenshot:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_UDmxiqUyDAo/R79KFzuvPmI/AAAAAAAAABo/i5s13ab5QWo/s1600-h/helloWorld2.PNG"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_UDmxiqUyDAo/R79KFzuvPmI/AAAAAAAAABo/i5s13ab5QWo/s320/helloWorld2.PNG" border="0" alt=""id="BLOGGER_PHOTO_ID_5169932360890662498" /&gt;&lt;/a&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;p&gt;Attributes names are not case sensitive. Setter methods corresponding to the attributes are invoked on the event queue via invokeAndWait if the current thread is not the event dispatch thread.&lt;/p&gt;&lt;br /&gt;&lt;br/&gt;&amp;nbsp;&lt;br/&gt;&lt;br /&gt;&lt;b&gt;Buttons and Events&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;p&gt;&lt;br /&gt;The next example is a button that simply changes its text when pressed:&lt;/p&gt;&lt;br /&gt;&lt;pre name="code" class="scala"&gt;&lt;br /&gt;import tfd.scala.squib._&lt;br /&gt;&lt;br /&gt;import java.awt.event.ActionEvent&lt;br /&gt;import javax.swing.{JButton, WindowConstants}&lt;br /&gt;&lt;br /&gt;frame(&lt;br /&gt;    'title -&gt; "Press Me",&lt;br /&gt;    'visible -&gt; true,&lt;br /&gt;    'defaultCloseOperation -&gt; WindowConstants.DISPOSE_ON_CLOSE,&lt;br /&gt;    contents(&lt;br /&gt;        button(&lt;br /&gt;            'text-&gt;"Press Me",&lt;br /&gt;            events (&lt;br /&gt;                'actionPerformed -&gt; { ae:ActionEvent =&gt;&lt;br /&gt;                    ae.getSource.asInstanceOf[JButton].setText("Pressed")&lt;br /&gt;                }&lt;br /&gt;            )&lt;br /&gt;        )&lt;br /&gt;    )&lt;br /&gt;).pack&lt;br /&gt;&lt;/pre&gt;&lt;a href="http://scala-squib.googlecode.com/svn/trunk/demo/script/pressMeEvent.scalash"&gt;link&lt;/a&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;Screenshots before and after button pressed:&lt;br /&gt;&lt;table&gt;&lt;tr&gt;&lt;td&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_UDmxiqUyDAo/R79TJzuvPnI/AAAAAAAAABw/aiu3YISVbm8/s1600-h/pressMe.PNG"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_UDmxiqUyDAo/R79TJzuvPnI/AAAAAAAAABw/aiu3YISVbm8/s320/pressMe.PNG" border="0" alt=""id="BLOGGER_PHOTO_ID_5169942325214789234" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/td&gt;&lt;td&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_UDmxiqUyDAo/R79TYTuvPoI/AAAAAAAAAB4/d7tV2Mw2sU4/s1600-h/pressed.PNG"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_UDmxiqUyDAo/R79TYTuvPoI/AAAAAAAAAB4/d7tV2Mw2sU4/s320/pressed.PNG" border="0" alt=""id="BLOGGER_PHOTO_ID_5169942574322892418" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;&lt;p&gt;Event names are not case sensitive using this notation. Like &lt;b&gt;attributes&lt;/b&gt;, &lt;b&gt;events&lt;/b&gt; is also pretty much optional as well. However, there is one tiny risk. The pattern matcher could mistake an attribute for an event if by small chance, there is an attribute that is a Scala Function1[EventObject] object. This could not happen with an existing Swing component, but only with a custom component developed in Scala. The risk is very small and can be avoided by using &lt;b&gt;events&lt;/b&gt;. Here is the equivalent code sans &lt;b&gt;events&lt;/b&gt;:&lt;/p&gt;&lt;br /&gt;&lt;pre name="code" class="scala"&gt;&lt;br /&gt;import tfd.scala.squib._&lt;br /&gt;&lt;br /&gt;import java.awt.event.ActionEvent&lt;br /&gt;import javax.swing.{JButton, WindowConstants}&lt;br /&gt;&lt;br /&gt;frame(&lt;br /&gt;    'title -&gt; "Press Me",&lt;br /&gt;    'visible -&gt; true,&lt;br /&gt;    'defaultCloseOperation -&gt; WindowConstants.DISPOSE_ON_CLOSE,&lt;br /&gt;    contents(&lt;br /&gt;        button(&lt;br /&gt;            'text-&gt;"Press Me",&lt;br /&gt;            'actionPerformed -&gt; { ae:ActionEvent =&gt;&lt;br /&gt;                ae.getSource.asInstanceOf[JButton].setText("Pressed")&lt;br /&gt;            }&lt;br /&gt;        )&lt;br /&gt;    )&lt;br /&gt;).pack&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;a href="http://scala-squib.googlecode.com/svn/trunk/demo/script/pressMeEvent2.scalash"&gt;link&lt;/a&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;p&gt;Since there are a finite number of events within Swing, SQUIB has helper/factory objects for the most common events. Being the name of an object, the event specification does become case sensitive. Here an a example that uses such a helper for the &lt;b&gt;actionPerformed&lt;/b&gt; event which is in the tfd.scala.squib.event package:&lt;/p&gt;&lt;br /&gt;&lt;pre name="code" class="scala"&gt;&lt;br /&gt;import tfd.scala.squib._&lt;br /&gt;import tfd.scala.squib.event._&lt;br /&gt;&lt;br /&gt;import java.awt.event.ActionEvent&lt;br /&gt;import javax.swing.{JButton, WindowConstants}&lt;br /&gt;&lt;br /&gt;frame(&lt;br /&gt;    'title -&gt; "Press Me",&lt;br /&gt;    'visible -&gt; true,&lt;br /&gt;    'defaultCloseOperation -&gt; WindowConstants.DISPOSE_ON_CLOSE,&lt;br /&gt;    contents(&lt;br /&gt;        button(&lt;br /&gt;            'text-&gt;"Press Me",&lt;br /&gt;            actionPerformed { ae:ActionEvent =&gt;&lt;br /&gt;                ae.getSource.asInstanceOf[JButton].setText("Pressed")&lt;br /&gt;            }&lt;br /&gt;        )&lt;br /&gt;    )&lt;br /&gt;).pack&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;a href="http://scala-squib.googlecode.com/svn/trunk/demo/script/pressMeEventHelper.scalash"&gt;link&lt;/a&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;p&gt;The &lt;b&gt;actionPerformed&lt;/b&gt; object makes the code a little tidier. Another benefit is that they can be passed a block without the EventObject parameter for those cases where the event handler is not "interested" in it. Example:&lt;/p&gt;&lt;br /&gt;&lt;pre name="code" class="scala"&gt;import tfd.scala.squib._&lt;br /&gt;import tfd.scala.squib.event._&lt;br /&gt;&lt;br /&gt;import javax.swing.{JButton, WindowConstants}&lt;br /&gt; &lt;br /&gt;var clickCount = 0;&lt;br /&gt;&lt;br /&gt;def clickCountText = "ClickCount: " + clickCount&lt;br /&gt;&lt;br /&gt;frame(&lt;br /&gt;    'title -&gt; "Press Me",&lt;br /&gt;    'visible -&gt; true,&lt;br /&gt;    'defaultCloseOperation -&gt; WindowConstants.DISPOSE_ON_CLOSE,&lt;br /&gt;    'layout-&gt;gridlayout('rows-&gt;2, 'columns-&gt;1),&lt;br /&gt;    contents(&lt;br /&gt;        button('text-&gt;"Press Me",&lt;br /&gt;            actionPerformed { &lt;br /&gt;                clickCount += 1&lt;br /&gt;                label.id("clickCount").setText(clickCountText)&lt;br /&gt;            }&lt;br /&gt;        ),&lt;br /&gt;        label("clickCount", 'text-&gt;clickCountText)&lt;br /&gt;    )&lt;br /&gt;).pack&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;a href="http://scala-squib.googlecode.com/svn/trunk/demo/script/pressMeEventHelperBlock.scalash"&gt;link&lt;/a&gt;&lt;br /&gt;Screenshot:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_UDmxiqUyDAo/R8CNWzuvPrI/AAAAAAAAACQ/AeSZjvgvpVA/s1600-h/clickCount.PNG"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_UDmxiqUyDAo/R8CNWzuvPrI/AAAAAAAAACQ/AeSZjvgvpVA/s320/clickCount.PNG" border="0" alt=""id="BLOGGER_PHOTO_ID_5170287795204210354" /&gt;&lt;/a&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;p&gt;Removing the unneeded "ActionEvent:ae =&gt; " cleans up the code even more. This example also introduces the concept of component ids. Every SQUIB component object (like "label", "button" or "frame") keeps a map of components indexed by a String. The "id" method takes a String and returns the last component of that type constructed with that id (if there is any). Each component type has a different map, so different component types can have the same id. In the previous example, looking up the id during every event is not optimal, since the event handlers are lexically scoped closures, that can access values or variables within the current scope requiring the lookup to be performed only once. Example:&lt;/p&gt;&lt;br /&gt;&lt;pre name="code" class="scala"&gt;&lt;br /&gt;import tfd.scala.squib._&lt;br /&gt;import tfd.scala.squib.event._&lt;br /&gt;&lt;br /&gt;import javax.swing.{JButton, WindowConstants}&lt;br /&gt; &lt;br /&gt;var clickCount = 0;&lt;br /&gt;&lt;br /&gt;def clickCountText = "ClickCount: " + clickCount&lt;br /&gt;&lt;br /&gt;lazy val clickCountLabel = label.id("clickCount")&lt;br /&gt;&lt;br /&gt;frame(&lt;br /&gt;    'title -&gt; "Press Me",&lt;br /&gt;    'visible -&gt; true,&lt;br /&gt;    'defaultCloseOperation -&gt; WindowConstants.DISPOSE_ON_CLOSE,&lt;br /&gt;    'layout-&gt;gridlayout('rows-&gt;2, 'columns-&gt;1),&lt;br /&gt;    contents(&lt;br /&gt;        button('text-&gt;"Press Me",&lt;br /&gt;            actionPerformed { &lt;br /&gt;                clickCount += 1&lt;br /&gt;                clickCountLabel.setText(clickCountText)&lt;br /&gt;            }&lt;br /&gt;        ),&lt;br /&gt;        label("clickCount", 'text-&gt;clickCountText)&lt;br /&gt;    )&lt;br /&gt;).pack&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;a href="http://scala-squib.googlecode.com/svn/trunk/demo/script/pressMeEventLazyVal.scalash"&gt;link&lt;/a&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;p&gt;Since the label id is not set until after the block declaration, the val needs to be "lazy", so that it is not instantiated until the first time it is needed in the button event handler. Use of "lazy" is very helpful for SQUIB applications, because of situations like this.&lt;/p&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;p&gt;&lt;br /&gt;If one doesn't want to use an id, the component itself can be referenced by a value and used:&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;pre name="code" class="scala"&gt;&lt;br /&gt;import tfd.scala.squib._&lt;br /&gt;import tfd.scala.squib.event._&lt;br /&gt;&lt;br /&gt;import javax.swing.{JButton, WindowConstants}&lt;br /&gt; &lt;br /&gt;var clickCount = 0;&lt;br /&gt;&lt;br /&gt;def clickCountText = "ClickCount: " + clickCount&lt;br /&gt;&lt;br /&gt;val clickCountLabel = label("clickCount", 'text-&gt;clickCountText)&lt;br /&gt;&lt;br /&gt;frame(&lt;br /&gt;    'title -&gt; "Press Me",&lt;br /&gt;    'visible -&gt; true,&lt;br /&gt;    'defaultCloseOperation -&gt; WindowConstants.DISPOSE_ON_CLOSE,&lt;br /&gt;    'layout-&gt;gridlayout('rows-&gt;2, 'columns-&gt;1),&lt;br /&gt;    contents(&lt;br /&gt;        button('text-&gt;"Press Me",&lt;br /&gt;            actionPerformed { &lt;br /&gt;                clickCount += 1&lt;br /&gt;                clickCountLabel.setText(clickCountText)&lt;br /&gt;            }&lt;br /&gt;        ),&lt;br /&gt;        clickCountLabel&lt;br /&gt;    )&lt;br /&gt;).pack&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;a href="http://scala-squib.googlecode.com/svn/trunk/demo/script/pressMeEventRef.scalash"&gt;link&lt;/a&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;p&gt;Here is one last example of a button with mouse event handlers:&lt;/p&gt;&lt;br /&gt;&lt;pre name="code" class="scala"&gt;&lt;br /&gt;import tfd.scala.squib._&lt;br /&gt;import tfd.scala.squib.event._&lt;br /&gt;&lt;br /&gt;import javax.swing.{JButton, WindowConstants}&lt;br /&gt;&lt;br /&gt;val defaultButtonText = "Please Press Me"&lt;br /&gt;&lt;br /&gt;lazy val pressMeButton = button.id("pressMe")&lt;br /&gt;&lt;br /&gt;frame(&lt;br /&gt;    'title -&gt; "Press Me",&lt;br /&gt;    'visible -&gt; true,&lt;br /&gt;    'defaultCloseOperation -&gt; WindowConstants.DISPOSE_ON_CLOSE,&lt;br /&gt;    contents(&lt;br /&gt;        button("pressMe",&lt;br /&gt;            'text-&gt;defaultButtonText,&lt;br /&gt;            actionPerformed { &lt;br /&gt;                pressMeButton.setText("Ouch !!!!")&lt;br /&gt;            },&lt;br /&gt;            mouseEntered {&lt;br /&gt;                pressMeButton.setText("Don't Press Me")&lt;br /&gt;            },&lt;br /&gt;            mouseExited {&lt;br /&gt;                pressMeButton.setText(defaultButtonText)&lt;br /&gt;            }&lt;br /&gt;        )&lt;br /&gt;    )&lt;br /&gt;).pack&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;a href="http://scala-squib.googlecode.com/svn/trunk/demo/script/pressMeMouse.scalash"&gt;link&lt;/a&gt;&lt;br /&gt;Screenshots before and after the mouse entered the component:&lt;br /&gt;&lt;table&gt;&lt;tr&gt;&lt;td&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_UDmxiqUyDAo/R79YhTuvPpI/AAAAAAAAACA/NjGLSpwsIQs/s1600-h/pleasePressMe.PNG"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_UDmxiqUyDAo/R79YhTuvPpI/AAAAAAAAACA/NjGLSpwsIQs/s320/pleasePressMe.PNG" border="0" alt=""id="BLOGGER_PHOTO_ID_5169948226499853970" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/td&gt;&lt;td&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_UDmxiqUyDAo/R79YqzuvPqI/AAAAAAAAACI/oRKlm_jH9pY/s1600-h/dontPressMe.PNG"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_UDmxiqUyDAo/R79YqzuvPqI/AAAAAAAAACI/oRKlm_jH9pY/s320/dontPressMe.PNG" border="0" alt=""id="BLOGGER_PHOTO_ID_5169948389708611234" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;p&gt;Currently, not all events are supported by SQUIB. For example, HierarchyEvent is not supported. In the those cases, one would have to implement a HierarchyListener in the same manner as Java. Supported events are ActionEvent, ChangeEvent, ComponentEvent, FocusEvent, InternalFrameEvent, ItemEvent, KeyEvent, ListSelectionEvent, MouseEvent, MouseWheelEvent, and WindowEvent.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;p&gt;This should pretty good starting point for how to use the SQUIB library. There will be future posts that will demonstrate other aspects including layouts and the SceneGraph library.&lt;/p&gt;&lt;br /&gt;&lt;font size="+1"&gt;&lt;b&gt;"Cool Thing" for this post&lt;/b&gt;&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;p&gt;I've created a version of a SceneGraph demo named "Intro". The Java version is demonstrated here, &lt;a href="https://scenegraph-demos.dev.java.net/demos.html"&gt;https://scenegraph-demos.dev.java.net/demos.html&lt;/a&gt;.&lt;br /&gt;There is an also a link to the source on the demo page.&lt;br /&gt;The Scala source can be viewed here, &lt;a href="http://scala-squib.googlecode.com/svn/trunk/demo/src/tfd/scala/squib/demo/scenegraph/Intro.scala"&gt;http://scala-squib.googlecode.com/svn/trunk/demo/src/tfd/scala/squib/demo/scenegraph/Intro.scala&lt;/a&gt;.&lt;br /&gt;To execute the demo, one needs the scala_squibV0_4.jar linked above and the jar with SQUIB SceneGraph support downloaded from &lt;a href="http://scala-squib.googlecode.com/files/scala_squib_scenegraphV0_4.jar"&gt;http://scala-squib.googlecode.com/files/scala_squib_scenegraphV0_4.jar&lt;/a&gt;. Also, required is the archive containing the SceneGraph library itself available here, &lt;a href="http://download.java.net/javadesktop/scenario/releases/0.5/Scenario-0.5.jar"&gt;http://download.java.net/javadesktop/scenario/releases/0.5/Scenario-0.5.jar&lt;/a&gt; , and a jar containing the compiled application and resources downloaded from &lt;br /&gt;&lt;a href="http://scala-squib.googlecode.com/files/scala_scenegraph_intro.jar"&gt;http://scala-squib.googlecode.com/files/scala_scenegraph_intro.jar&lt;/a&gt;. Execute via:&lt;br /&gt;&lt;div class="command-prompt"&gt;scala -cp scala_squibV0_4.jar;scala_squib_scenegraphV0_4.jar;Scenario-0.5.jar;scala_scenegraph_intro.jar tfd.scala.squib.demo.scenegraph.Intro&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Screenshot of the SQUIB application which is pretty much identical to the Java version on the SceneGraph demos page:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_UDmxiqUyDAo/R8Cb9TuvPsI/AAAAAAAAACY/wGPWqIPU758/s1600-h/sceneGraphIntro.PNG"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_UDmxiqUyDAo/R8Cb9TuvPsI/AAAAAAAAACY/wGPWqIPU758/s320/sceneGraphIntro.PNG" border="0" alt=""id="BLOGGER_PHOTO_ID_5170303849791962818" /&gt;&lt;/a&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;p&gt;I'll let readers draw their own conclusions comparing the Scala/SQUIB code with the Java code for the application.&lt;/p&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;p&gt;My own experience with Scala was that at first, I found the syntax kind of "wonky", but once I got used to it, I found it to be well thought out and even intuitive. Features like type inference and first class function objects are sorely missed at times when developing in Java at work.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7017894832730513527-7137022224923979841?l=compulsiontocode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://compulsiontocode.blogspot.com/feeds/7137022224923979841/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7017894832730513527&amp;postID=7137022224923979841' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7017894832730513527/posts/default/7137022224923979841'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7017894832730513527/posts/default/7137022224923979841'/><link rel='alternate' type='text/html' href='http://compulsiontocode.blogspot.com/2008/02/squib-kicks-part-1.html' title='SQUIB Kicks (Part 1)'/><author><name>tdalton</name><uri>http://www.blogger.com/profile/13151512717871227421</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://4.bp.blogspot.com/-c8KSZCmTdpI/TbmtJ04pIUI/AAAAAAAAAEM/AEmlqBQ4ecM/s220/tim.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_UDmxiqUyDAo/R79F2TuvPlI/AAAAAAAAABg/20dPQtPk25Y/s72-c/helloWorld.PNG' height='72' width='72'/><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7017894832730513527.post-5020073472006165396</id><published>2008-01-16T00:30:00.002-06:00</published><updated>2009-02-10T12:08:03.077-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='squib'/><category scheme='http://www.blogger.com/atom/ns#' term='scala'/><title type='text'>SQUIB on Google Code</title><content type='html'>&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;p&gt;I am happy to announce that Scala's Quirky User Interface Builder (SQUIB) is now a Google Code project. The project home page is &lt;a href="http://code.google.com/p/scala-squib/"&gt;http://code.google.com/p/scala-squib/&lt;/a&gt;.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;A Subversion client is required to get the latest source from the trunk. To check out a copy of the current source use: &lt;div class="command-prompt"&gt;svn checkout http://scala-squib.googlecode.com/svn/trunk/ scala-squib-read-only&lt;/div&gt; If you don't have a Subversion client, a snapshot from 1/16/08 is made available &lt;a href="http://webpages.charter.net/daltontk/scala/squib/scala-squib-read-only_011608.zip"&gt;here  &lt;/a&gt;. Of course using a Subversion client allows one to stay in sync with updates to the project via "svn update".&lt;/p&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;p&gt;Requirements for SQUIB is Scala version 2.6 or later and a JRE version 1.5 or later. I've only used 1.6 for SQUIB, but there shouldn't be any problem using 1.5. Please let me know if there are issues. To build the project, Ant 1.6 or later is required.&lt;/p&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;p&gt;There is a &lt;a href="http://scala-squib.googlecode.com/svn/trunk/README.txt"&gt;README.txt&lt;/a&gt; file on the root directory of the project that gives a quick run down of ant tasks available and demo programs currently in the project.&lt;/p&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;p&gt;Currently, the scaladoc API documentation is rather thin, so in the near term, I will focused on getting more API documentation in the source code, so re-run "ant doc" after any Subversion update for updated documentation. &lt;/p&gt;&lt;br /&gt;&lt;p&gt;Please feel free to provide me feedback about this library. This is my first open source project that I've owned. What I have so far is just a start and there is lot of functionality yet to be added. I will be looking for new members for the project in the near future.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7017894832730513527-5020073472006165396?l=compulsiontocode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://compulsiontocode.blogspot.com/feeds/5020073472006165396/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7017894832730513527&amp;postID=5020073472006165396' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7017894832730513527/posts/default/5020073472006165396'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7017894832730513527/posts/default/5020073472006165396'/><link rel='alternate' type='text/html' href='http://compulsiontocode.blogspot.com/2008/01/squib-on-google-code.html' title='SQUIB on Google Code'/><author><name>tdalton</name><uri>http://www.blogger.com/profile/13151512717871227421</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://4.bp.blogspot.com/-c8KSZCmTdpI/TbmtJ04pIUI/AAAAAAAAAEM/AEmlqBQ4ecM/s220/tim.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7017894832730513527.post-3124729228759963643</id><published>2007-12-22T13:03:00.002-06:00</published><updated>2009-02-10T12:06:02.247-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='squib'/><category scheme='http://www.blogger.com/atom/ns#' term='scala'/><title type='text'>GUI Building with Scala - Part 3 (SQUIB and Scene Graphs)</title><content type='html'>&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;p&gt;I have opted to rename this little project from the rather generic, "Scala Gui Builder" to SQUIB (Scala's Quirky User Interface Builder). Originally, I was going to demonstrate little custom components I had developed to be used by SQUIB to draw shapes, but when I saw the announcement of the Java Scene Graph library (https://scenegraph.dev.java.net/), it was clear that it a perfect fit for SQUIB.&lt;/p&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;p&gt;I have just started development of Scene Graph support for SQUIB, so only minimal features are supported. Additionally, the Scene Graphs APIs are not finalized yet, so it would be not feasible to try to create a complete library against a changing API.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;b&gt;A Simple Example&lt;/b&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;I have created example programs to demonstrate the potential for Scene Graphs in SQUIB. Requirements for SQUIB with Scene Graph support are the updated &lt;a href="http://webpages.charter.net/daltontk/scala/ScalaSquibV0_3.jar"&gt;SQUIB jar file&lt;br /&gt;&lt;/a&gt; and the &lt;a href="http://webpages.charter.net/daltontk/scala/lib/Scenario-0.4.jar"&gt;Scene Graph jar&lt;/a&gt; file. &lt;a href="http://webpages.charter.net/daltontk/scala/src/SceneGraphSimple.scala"&gt;Here&lt;br /&gt;&lt;/a&gt; is a link to the source for the first example or you could copy and paste from below. Compile and run:&lt;br /&gt;&lt;div class="command-prompt"&gt;C:\tmp&gt;scalac -cp ScalaSquibV0_3.jar;Scenario-0.4.jar SceneGraphSimple.scala&lt;/div&gt;&lt;br /&gt;&lt;div class="command-prompt"&gt;C:\tmp\scala -cp .;ScalaSquibV0_3.jar;Scenario-0.4.jar tfd.scala.squib.scenegraph.demo.SceneGraphSimple&lt;/div&gt; &lt;br /&gt;&lt;p&gt;Source Code:&lt;/p&gt;&lt;br /&gt;&lt;pre name="code" class="scala"&gt;&lt;br /&gt;package tfd.scala.squib.scenegraph.demo;&lt;br /&gt;&lt;br /&gt;import java.awt.{Color, Point, Font, Dimension, Rectangle, BasicStroke}&lt;br /&gt;import javax.swing.{JFrame}&lt;br /&gt;&lt;br /&gt;import com.sun.scenario.scenegraph._&lt;br /&gt;import com.sun.scenario.animation._&lt;br /&gt;&lt;br /&gt;import tfd.scala.squib._&lt;br /&gt;import tfd.scala.squib.scenegraph._&lt;br /&gt;&lt;br /&gt;object SceneGraphSimple extends Application {&lt;br /&gt;    text.attributesDefault = attributes(&lt;br /&gt;            'font -&gt; new Font("Courier", Font.BOLD, 24),&lt;br /&gt;            'mode -&gt; SGAbstractShape.Mode.FILL,&lt;br /&gt;            'fillPaint -&gt; Color.BLUE&lt;br /&gt;    )&lt;br /&gt;    &lt;br /&gt;    val frm = frame(&lt;br /&gt;            attributes(&lt;br /&gt;                    'title-&gt;"SQUIB Scenegraph Demo",&lt;br /&gt;                    'visible -&gt; true,&lt;br /&gt;                    'defaultCloseOperation -&gt; JFrame.EXIT_ON_CLOSE,&lt;br /&gt;                    'size -&gt; new Dimension(100,200)&lt;br /&gt;             ),&lt;br /&gt;             borderlayout(),&lt;br /&gt;                 contents(&lt;br /&gt;                     scenepanel("scene",&lt;br /&gt;                         'scene -&gt; group("root",&lt;br /&gt;                                       group("sub",&lt;br /&gt;                                           translate(50, 100, &lt;br /&gt;                                               rotate("square", 0.0,&lt;br /&gt;                                                   shape(&lt;br /&gt;                                                         'shape -&gt; new Rectangle(-20,-20,40,40),&lt;br /&gt;                                                         'mode -&gt; SGAbstractShape.Mode.STROKE_FILL,&lt;br /&gt;                                                         'fillPaint -&gt; Color.RED,&lt;br /&gt;                                                         'drawPaint -&gt; Color.ORANGE,&lt;br /&gt;                                                         'drawStroke -&gt; new BasicStroke(5.0f)&lt;br /&gt;                                                   )&lt;br /&gt;                                               )&lt;br /&gt;                                           ),&lt;br /&gt;                                           scale("blah", 1.0, 1.0, &lt;br /&gt;                                               text("blah",&lt;br /&gt;                                                    'text -&gt; "Blah",&lt;br /&gt;                                                    'location -&gt; new Point(10,20)&lt;br /&gt;                                               )&lt;br /&gt;                                           ),&lt;br /&gt;                                           translate(10, 110,&lt;br /&gt;                                               composite(0.75, &lt;br /&gt;                                                   component('component -&gt; button("FooBar"))&lt;br /&gt;                                               )&lt;br /&gt;                    )&lt;br /&gt;                                       )&lt;br /&gt;                         ),&lt;br /&gt;                         'background -&gt; Color.GREEN&lt;br /&gt;                     ) -&gt; "Center"&lt;br /&gt;                 )&lt;br /&gt;    )&lt;br /&gt;    &lt;br /&gt;    Clip.create(&lt;br /&gt;            500,&lt;br /&gt;            600.0,&lt;br /&gt;            rotate.id("square"), &lt;br /&gt;            "rotation", &lt;br /&gt;            Array(-3.14159f, 3.14159f).map(_.asInstanceOf[Object]) &lt;br /&gt;    ).start();&lt;br /&gt;    &lt;br /&gt;    Clip.create(&lt;br /&gt;            500, &lt;br /&gt;            900.0,&lt;br /&gt;            scale.id("blah"), &lt;br /&gt;            "scaleY",&lt;br /&gt;            Array(0.5f, 5.0f).map(_.asInstanceOf[Object]) &lt;br /&gt;    ).start();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Screenshot of Simple Example:&lt;/p&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_UDmxiqUyDAo/R2rnz72-pSI/AAAAAAAAAAw/_gPIoqcNqCU/s1600-h/SceneGraphSimple.PNG"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_UDmxiqUyDAo/R2rnz72-pSI/AAAAAAAAAAw/_gPIoqcNqCU/s320/SceneGraphSimple.PNG" border="0" alt=""id="BLOGGER_PHOTO_ID_5146180403651847458" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;p&gt;The &lt;span style="font-family: courier; white-space: pre;"&gt;Array(0.5f, 5.0f).map(_.asInstanceOf[Object])&lt;/span&gt; expression represents one of the few areas where Scala/Java integration is not seamless. Scala does not handle Java variable arguments and "sees" the signature of the method as requiring an Array. The Scala code needs to explicitly put those parameters into an Array. Perhaps this could be done by an implicit conversion ? I'll have to experiment sometime.&lt;/p&gt; &lt;br /&gt;&lt;p&gt;&lt;b&gt;A Spinning Calculator?&lt;/b&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;This is a little more elaborate example that embeds the calculator from a previous &lt;br /&gt;&lt;a href="http://compulsiontocode.blogspot.com/2007/11/gui-building-with-scala-part-2.html"&gt;post&lt;/a&gt; in a scene graph. Source is available &lt;a href="http://webpages.charter.net/daltontk/scala/src/RotatingCalculator.scala"&gt;here&lt;br /&gt;&lt;/a&gt;. Compile and run:&lt;br /&gt;&lt;div class="command-prompt"&gt;C:\tmp&gt;scalac -cp ScalaSquibV0_3.jar;Scenario-0.4.jar RotatingCalculator.scala&lt;/div&gt;&lt;br /&gt;&lt;div class="command-prompt"&gt;C:\tmp\scala -cp .;ScalaSquibV0_3.jar;Scenario-0.4.jar  tfd.scala.squib.scenegraph.demo.RotatingCalculator&lt;/div&gt; &lt;br /&gt;&lt;p&gt;Screenshot of Rotating Calculator:&lt;/p&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_UDmxiqUyDAo/R2rs2r2-pTI/AAAAAAAAAA4/JAkHTgINb6I/s1600-h/RotatingCalculator.PNG"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_UDmxiqUyDAo/R2rs2r2-pTI/AAAAAAAAAA4/JAkHTgINb6I/s320/RotatingCalculator.PNG" border="0" alt=""id="BLOGGER_PHOTO_ID_5146185948454626610" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;p&gt;Looking at the RotatingCalculator source, you will see new button factory methods that allow definition of Actions in the button declaration itself and other "shorthand" methods. I am still planning to get the source out on Google Code in the coming months.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;The examples here show the power of the Scene Graph library and how SQUIB can be used to generate scene graphs in Scala in a rather expressive manner.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7017894832730513527-3124729228759963643?l=compulsiontocode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://compulsiontocode.blogspot.com/feeds/3124729228759963643/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7017894832730513527&amp;postID=3124729228759963643' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7017894832730513527/posts/default/3124729228759963643'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7017894832730513527/posts/default/3124729228759963643'/><link rel='alternate' type='text/html' href='http://compulsiontocode.blogspot.com/2007/12/gui-building-with-scala-part-3-squib.html' title='GUI Building with Scala - Part 3 (SQUIB and Scene Graphs)'/><author><name>tdalton</name><uri>http://www.blogger.com/profile/13151512717871227421</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://4.bp.blogspot.com/-c8KSZCmTdpI/TbmtJ04pIUI/AAAAAAAAAEM/AEmlqBQ4ecM/s220/tim.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_UDmxiqUyDAo/R2rnz72-pSI/AAAAAAAAAAw/_gPIoqcNqCU/s72-c/SceneGraphSimple.PNG' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7017894832730513527.post-8143448283451548711</id><published>2007-11-21T08:39:00.002-06:00</published><updated>2009-02-10T12:02:50.493-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='squib'/><category scheme='http://www.blogger.com/atom/ns#' term='scala'/><title type='text'>GUI Building with Scala - Part 2</title><content type='html'>&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;In my previous post, &lt;a href="http://compulsiontocode.blogspot.com/2007/10/gui-building-with-scala.html"&gt;http://compulsiontocode.blogspot.com/2007/10/gui-building-with-scala.html&lt;/a&gt;, I introduced a library for building Swing interfaces in Scala that I've been creating. This post will show more features of the library and demonstrate them by building a rudimentary calculator.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Based on feedback received, features have been added since the previous post, so a new version of library is made available &lt;a href="http://webpages.charter.net/daltontk/scala/ScalaGuiBuilderV0_2.jar"&gt;here&lt;br /&gt;&lt;/a&gt; along with &lt;a href="http://webpages.charter.net/daltontk/scala/src/GuiBuilderCalc.scala"&gt;source &lt;/a&gt; for the calculator.&lt;br /&gt;Ensure the jar above is on the CLASSPATH, compile and run the example program:&lt;br /&gt;&lt;div class="command-prompt"&gt;C:\tmp&gt;scalac -cp ScalaGuiBuilderV0_2.jar GuiBuilderCalc.scala&lt;/div&gt;&lt;br /&gt;&lt;div class="command-prompt"&gt;C:\tmp\scala -cp .;ScalaGuiBuilderV0_2.jar tfd.scala.guibuilder.demo.GuiBuilderCalc&lt;/div&gt;&lt;br /&gt;Here is a screenshot of the calculator:&lt;br /&gt;&lt;center&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_UDmxiqUyDAo/Rz4LlrHwloI/AAAAAAAAAAo/mFWy5vcWHLQ/s1600-h/GuiBuilderCalc.PNG"&gt;&lt;img style="cursor: pointer;" src="http://3.bp.blogspot.com/_UDmxiqUyDAo/Rz4LlrHwloI/AAAAAAAAAAo/mFWy5vcWHLQ/s320/GuiBuilderCalc.PNG" alt="" id="BLOGGER_PHOTO_ID_5133553367107278466" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;/center&gt;&lt;br /&gt;&lt;h4&gt;Summary of the GuiBuilderCalc.scala source:&lt;/h4&gt;&lt;br /&gt;The first piece of noteworthy code is below:&lt;br /&gt;&lt;pre name="code" class="scala"&gt;frame.attributes_default = attributes('defaultcloseoperation-&gt;JFrame.EXIT_ON_CLOSE)&lt;br /&gt;&lt;br /&gt;button.attributesDefault = attributes('foreground-&gt;Color.blue)&lt;br /&gt;&lt;br /&gt;button.attributesByPattern += ("\\d" -&gt; attributes('foreground-&gt;Color.red))&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;The "attributesDefault" property of the component objects stores attribute mappings to be applied to any instance of the component thereafter. The first two lines above ensure that all frames created thereafter exit on close and all buttons created thereafter have blue text.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;The "attributesByPattern" property stores a mapping of strings to attribute mappings that are applied to components whose id match the regular expression in the string key. It's kind of a "pseudo CSS". The last line above specifies that any button whose id is a single digit should have red text. The "attributesByPattern" are applied after the "attributesDefault" and therefore have precedence.&lt;br /&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;The next thing done in the code is create the textfield:&lt;br /&gt;&lt;pre name="code" class="scala"&gt;val calcField = textfield(&lt;br /&gt;     'text-&gt;"0"&lt;br /&gt;    ,'horizontalalignment-&gt;SwingConstants.RIGHT&lt;br /&gt;    ,'editable-&gt;false&lt;br /&gt;    ,'background-&gt;Color.white&lt;br /&gt;)&lt;/pre&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Based on feedback from the last post, I made it optional to explicitly specify "attributes" when the attributes are the last parameter. The code above creates a JTextField without a string id, with specified attributes, and assigns it to value "calcField".&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Below the panel containing the calculator buttons is created:&lt;br /&gt;&lt;pre name="code" class="scala"&gt;val gridPanel = panel(&lt;br /&gt;     gridlayout('rows-&gt;5, 'columns-&gt;4, 'vgap-&gt;4, 'hgap-&gt;2)&lt;br /&gt;    ,contents(&lt;br /&gt;        button("clear"      ,'text-&gt;"C" , 'foreground-&gt;Color.black)&lt;br /&gt;       ,button("clear_erase",'text-&gt;"CE", 'foreground-&gt;Color.black)&lt;br /&gt;       ,new JLabel("")&lt;br /&gt;       ,button("/","/")&lt;br /&gt;       ,button("7","7")&lt;br /&gt;       ,button("8","8")&lt;br /&gt;       ,button("9","9")&lt;br /&gt;       ,button("*","*")&lt;br /&gt;       ,button("4","4")&lt;br /&gt;       ,button("5","5")&lt;br /&gt;       ,button("6","6")&lt;br /&gt;       ,button("-","-")&lt;br /&gt;       ,button("1","1")&lt;br /&gt;       ,button("2","2")&lt;br /&gt;       ,button("3","3")&lt;br /&gt;       ,button("+","+")&lt;br /&gt;       ,button("0","0")&lt;br /&gt;       ,button("negate","+/-")&lt;br /&gt;       ,button(".",".")&lt;br /&gt;       ,button("=","=") &lt;br /&gt;    )    &lt;br /&gt;)&lt;/pre&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;I've added factory methods for the button component to cover the more common of component construction scenarios. For example, &lt;span style="font-family: courier; white-space: pre;"&gt;button("+","+")&lt;/span&gt; creates a button with string id of "+" and "+" for the text. This can also be expressed as &lt;span style="font-family: courier; white-space: pre;"&gt;button("+", 'text-&gt;"+")&lt;/span&gt; or even &lt;span style="font-family: courier; white-space: pre;"&gt;button("+", attributes('text-&gt;"+"))&lt;/span&gt;.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;The &lt;span style="font-family: courier; white-space: pre;"&gt;new JLabel("")&lt;/span&gt; part shows that you can create Swing components using the normal constructors and include them. This allows custom components to be built into the interface. Components included this way can not have string ids nor do "attributesDefault" or "attributesByPattern" get applied to them.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;The textfield and buttons are assembled together in a panel:&lt;br /&gt;&lt;pre name="code" class="scala"&gt;val frm = frame(&lt;br /&gt;    attributes(&lt;br /&gt;      'title-&gt;"GUIBuilder Calculator"&lt;br /&gt;    )&lt;br /&gt;   ,borderlayout()&lt;br /&gt;   ,contents(&lt;br /&gt;        panel(&lt;br /&gt;             borderlayout()&lt;br /&gt;            ,contents(&lt;br /&gt;                 calcField -&gt; "North"&lt;br /&gt;                ,gridPanel -&gt; "Center"&lt;br /&gt;            )&lt;br /&gt;        ) -&gt; "Center"&lt;br /&gt;   )&lt;br /&gt;)&lt;/pre&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Here components in the contents need constraints due to the use of borderlayout. In Scala, the expression "foo -&gt; bar" is simply a tuple so &lt;span style="font-family: courier; white-space: pre;"&gt;(calcField, "North")&lt;/span&gt; and &lt;span style="font-family: courier; white-space: pre;"&gt;(gridPanel, "Center")&lt;/span&gt; could also have been used.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;Finally, button handlers are added.&lt;br /&gt;&lt;pre name="code" class="scala"&gt;var stored = 0.0&lt;br /&gt;var operation = ' '&lt;br /&gt;var newInput = true&lt;br /&gt;&lt;br /&gt;// Iterate and attach event handlers for the number buttons&lt;br /&gt;for (val num&lt;-Iterator.range(0, 10)) {  &lt;br /&gt;    button.onAction("" + num,(ae: ActionEvent) =&gt; {&lt;br /&gt;        val prepend = if (newInput) "" else calcField.getText&lt;br /&gt;        calcField.setText(prepend + num)&lt;br /&gt;        newInput = false&lt;br /&gt;    })&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// Attach an event handling to clear the sum text field&lt;br /&gt;button.onAction("clear", (ae: ActionEvent) =&gt; {&lt;br /&gt;    calcField.setText("0")&lt;br /&gt;    newInput = true&lt;br /&gt;})&lt;br /&gt;&lt;br /&gt;button.onAction("clear_erase", (ae: ActionEvent) =&gt; {&lt;br /&gt;    calcField.setText("0")&lt;br /&gt;    stored = 0.0&lt;br /&gt;    newInput = true&lt;br /&gt;})&lt;br /&gt;&lt;br /&gt;button.onAction("negate", (ae: ActionEvent) =&gt; {&lt;br /&gt;    calcField.setText("" + (-calcField.getText().toDouble))&lt;br /&gt;})&lt;br /&gt;&lt;br /&gt;button.onAction(".", (ae: ActionEvent) =&gt; {&lt;br /&gt;    if (newInput) {&lt;br /&gt;        calcField.setText("0.")&lt;br /&gt;        newInput = false;&lt;br /&gt;    } else {&lt;br /&gt;        val text = calcField.getText()&lt;br /&gt;        if (!text.contains('.')) {&lt;br /&gt;            calcField.setText(text + ".")&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;})&lt;br /&gt;&lt;br /&gt;def doOperation(oper:Char) {&lt;br /&gt;    operation = oper&lt;br /&gt;    stored = calcField.getText().toDouble&lt;br /&gt;    newInput = true&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;button.onAction("+", (ae: ActionEvent) =&gt; {&lt;br /&gt;    doOperation('+')&lt;br /&gt;})&lt;br /&gt;&lt;br /&gt;button.onAction("-", (ae: ActionEvent) =&gt; {&lt;br /&gt;    doOperation('-')&lt;br /&gt;})&lt;br /&gt;&lt;br /&gt;button.onAction("*", (ae: ActionEvent) =&gt; {&lt;br /&gt;    doOperation('*')&lt;br /&gt;})&lt;br /&gt;&lt;br /&gt;button.onAction("/", (ae: ActionEvent) =&gt; {&lt;br /&gt;    doOperation('/')&lt;br /&gt;})&lt;br /&gt;&lt;br /&gt;button.onAction("=", (ae: ActionEvent) =&gt; {&lt;br /&gt;    val current = calcField.getText().toDouble&lt;br /&gt;    calcField.setText("" + (operation match {&lt;br /&gt;        case '+' =&gt;  (stored + current)&lt;br /&gt;        case '*' =&gt;  (stored * current)&lt;br /&gt;        case '-' =&gt;  (stored - current)&lt;br /&gt;        case '/' =&gt;  (stored / current)&lt;br /&gt;        case _ =&gt; current&lt;br /&gt;    }))&lt;br /&gt;    newInput = true&lt;br /&gt;})&lt;/pre&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;The library continues to grow based on feedback from others and from my own ideas. There are still features already built in to be shown in future posts. At some point, I am hoping to release the source and create a project on SourceForge or Google Code. The name "Scala GUI Builder" is not very original. Shortening "SCala User Inteface Builder" makes "SCUIB" which isn't a word. I am liking "SQUIB" for "Scala Quick User Interface Builder".&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7017894832730513527-8143448283451548711?l=compulsiontocode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://compulsiontocode.blogspot.com/feeds/8143448283451548711/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7017894832730513527&amp;postID=8143448283451548711' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7017894832730513527/posts/default/8143448283451548711'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7017894832730513527/posts/default/8143448283451548711'/><link rel='alternate' type='text/html' href='http://compulsiontocode.blogspot.com/2007/11/gui-building-with-scala-part-2.html' title='GUI Building with Scala - Part 2'/><author><name>tdalton</name><uri>http://www.blogger.com/profile/13151512717871227421</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://4.bp.blogspot.com/-c8KSZCmTdpI/TbmtJ04pIUI/AAAAAAAAAEM/AEmlqBQ4ecM/s220/tim.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_UDmxiqUyDAo/Rz4LlrHwloI/AAAAAAAAAAo/mFWy5vcWHLQ/s72-c/GuiBuilderCalc.PNG' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7017894832730513527.post-924057572610644284</id><published>2007-11-14T07:44:00.004-06:00</published><updated>2009-02-10T11:58:31.533-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='squib'/><category scheme='http://www.blogger.com/atom/ns#' term='scala'/><title type='text'>GUI Building with Scala</title><content type='html'>&lt;p&gt;One the strengths of Scala is a flexible syntax that allows for Scala code be more like a Domain Specific Language. A while back, I started to put such a Scala "DSL" together inspired in part by what was then known as F3, but has since been re-branded, JavaFX. This idea languished for few months while I got distracted by other pursuits. I've decided to publish what I have produced so far to get feedback about it and determine if such a thing is a worth continuing.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;I've published the supporting classes in a jar file available &lt;a href="http://webpages.charter.net/daltontk/scala/ScalaGuiBuilderV0_1.jar"&gt;here &lt;br /&gt;&lt;/a&gt; along with a simple example &lt;a href="http://webpages.charter.net/daltontk/scala/src/GuiBuilderSimple.scala"&gt;program&lt;/a&gt;. Ensure the jar above is on the CLASSPATH, compile and run the example program:&lt;br /&gt;&lt;div class="command-prompt"&gt;C:\tmp&gt;scalac -cp ScalaGuiBuilderV0_1.jar GuiBuilderSimple.scala&lt;/div&gt;&lt;br /&gt;&lt;div class="command-prompt"&gt;C:\tmp\scala -cp .;ScalaGuiBuilderV0_1.jar tfd.scala.guibuilder.demo.GuiBuilderSimple&lt;/div&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Simple Example Code:&lt;br /&gt;&lt;pre name="code" class="scala"&gt;package tfd.scala.guibuilder.demo&lt;br /&gt;&lt;br /&gt;object GuiBuilderSimple extends Application {&lt;br /&gt;  import java.awt.{Color, FlowLayout}&lt;br /&gt;  import java.awt.event.ActionEvent&lt;br /&gt;  import javax.swing.JFrame&lt;br /&gt;&lt;br /&gt;  import tfd.scala.guibuilder._&lt;br /&gt;&lt;br /&gt;  var frm = frame(&lt;br /&gt;                attributes(&lt;br /&gt;                   'title-&gt;"GUIBuilder Simple Demo",&lt;br /&gt;                   'defaultCloseOperation-&gt;JFrame.EXIT_ON_CLOSE&lt;br /&gt;                ),&lt;br /&gt;                flowlayout(attributes('alignment -&gt; FlowLayout.LEFT)),&lt;br /&gt;                contents(&lt;br /&gt;                    button("PressButton", attributes('text-&gt;"Press"   ,'foreground-&gt;Color.blue)),&lt;br /&gt;                    label("PressLabel",   attributes('text-&gt;"Not Pressed",'foreground-&gt;Color.red))&lt;br /&gt;                )&lt;br /&gt;  )&lt;br /&gt;&lt;br /&gt;  button.onAction("PressButton",(ae: ActionEvent) =&gt; {&lt;br /&gt;      label.applyAttributes("PressLabel", attributes('text -&gt; "Pressed", 'foreground -&gt; Color.black))&lt;br /&gt;  })&lt;br /&gt;&lt;br /&gt;  frm.pack&lt;br /&gt;  frm.setVisible(true)&lt;br /&gt;}&lt;/pre&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Running the program will create a window like the first one below:&lt;table style="width: 100%;padding:0px;margin:0px"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;br /&gt;&lt;td&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_UDmxiqUyDAo/Rznp3B5CriI/AAAAAAAAAAM/nkqC4giL40A/s1600-h/GuiBuilderSimple1.JPG"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; cursor: pointer;" src="http://2.bp.blogspot.com/_UDmxiqUyDAo/Rznp3B5CriI/AAAAAAAAAAM/nkqC4giL40A/s320/GuiBuilderSimple1.JPG" alt="" id="BLOGGER_PHOTO_ID_5132390381975154210" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;i&gt;Before the button is pressed&lt;/i&gt;&lt;/td&gt;&lt;br /&gt;&lt;td&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_UDmxiqUyDAo/RznqGx5CrjI/AAAAAAAAAAU/TdQ6DS3lHIY/s1600-h/GuiBuilderSimple2.JPG"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; cursor: pointer;" src="http://1.bp.blogspot.com/_UDmxiqUyDAo/RznqGx5CrjI/AAAAAAAAAAU/TdQ6DS3lHIY/s320/GuiBuilderSimple2.JPG" alt="" id="BLOGGER_PHOTO_ID_5132390652558093874" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;i&gt;After the button is pressed&lt;/i&gt;&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;So what's going on here ? Each component is represented by a Scala object with overloaded "apply" methods that represent various options of constructing the component. In other words, they are factories. To prevent confusion or collisions with existing class names, the component objects names are all lowercase. If "Frame" was used instead of "frame" then it becomes unwieldy if the program wants to "import java.awt.Frame". The "attributes" are also processed by a factory object via its "apply" method. I could have used "List(&amp;lt;attribute1&gt;,&amp;lt;attribute2&amp;gt;...)" or "&amp;lt;attribute1&amp;gt; :: &amp;lt;attribute2&amp;gt; ... ::  Nil", for listing the attributes, but I feel it's more concise to use "attributes". It would be nice if Scala supported lists in more shorthanded way like Erlang or Ocaml then I could have done something like "[&amp;lt;attribute1&amp;gt;,&amp;lt;attribute2&amp;gt;...]".&lt;/p&gt;&lt;br /&gt;&lt;p&gt;I opted to use Scala symbols for the attribute names to save a keystroke and reduce problems from trailing quotes being omitted. Using strings would have required code like:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="scala"&gt;attributes(&lt;br /&gt;  "title"-&gt;"GUIBuilder Simple Demo",&lt;br /&gt;  "defaultCloseOperation"-&gt;JFrame.EXIT_ON_CLOSE&lt;br /&gt;)&lt;/pre&gt;&lt;br /&gt;Feedback on the using string versus symbols would be appreciated.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Let's break down what is going on in the sample above:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;The "frame" factory object returns the JFrame it constructed and takes the following parameters:&lt;br /&gt;- The "attributes" represent mappings of bean properties to values. The library will use introspection to look for get methods to invoke in order to set the attribute.&lt;br /&gt;- A layout manager specification. Here the "flowlayout" object will return a java.awt.Flowlayout to be used for the content pane of the frame.&lt;br /&gt;- The "contents" object specifies the components to be added to the frame's content pane using the specified layout manager. Here, since we are using a FlowLayout, we don't need to provide constraints for the layout manager in the contents. Using more complicated layout managers will require such constraints in the contents.&lt;br /&gt;- The components added here are simply a button and label which map to Swing JButton and JLabel components respectively. The first parameter passed to their "constructor" object is an optional string identifier that allows the component to be looked up later using an "id" method on the factory object. Example 'var btn = button.id("PressButton")' will assign the JButton with id of "PressButton" to variable "btn".&lt;/li&gt;&lt;br /&gt;&lt;li&gt;The button.onAction method takes the string id for the button and function object with an ActionEvent parameter and adds an ActionListener to the button that delegates it's actionPerformed call to the passed function object. The body of the function object invokes an applyAttributes method on the label applies attribute to a label specifies by the string id. The same can can accomplished in a more Java like style with the code below:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="scala"&gt;button.onAction("PressButton",(ae: ActionEvent) =&gt; {&lt;br /&gt;  var label = label.id("PressLabel")&lt;br /&gt;  label.setText("Pressed")&lt;br /&gt;  label.setForeground(Color.black)&lt;br /&gt;})&lt;/pre&gt;&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Finally, the JFrame is packed and made visible.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;As of yet, the library only supports a subset of the Swing components. I plan to follow up with more posts shortly with examples showing how to use constrained components in frames and panels with other layout managers (including GridBagLayout), show more supported component types and other features I have built into the library. I will also publish the source for the library.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7017894832730513527-924057572610644284?l=compulsiontocode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://compulsiontocode.blogspot.com/feeds/924057572610644284/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7017894832730513527&amp;postID=924057572610644284' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7017894832730513527/posts/default/924057572610644284'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7017894832730513527/posts/default/924057572610644284'/><link rel='alternate' type='text/html' href='http://compulsiontocode.blogspot.com/2007/10/gui-building-with-scala.html' title='GUI Building with Scala'/><author><name>tdalton</name><uri>http://www.blogger.com/profile/13151512717871227421</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://4.bp.blogspot.com/-c8KSZCmTdpI/TbmtJ04pIUI/AAAAAAAAAEM/AEmlqBQ4ecM/s220/tim.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_UDmxiqUyDAo/Rznp3B5CriI/AAAAAAAAAAM/nkqC4giL40A/s72-c/GuiBuilderSimple1.JPG' height='72' width='72'/><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7017894832730513527.post-3199530880664919749</id><published>2007-10-25T09:45:00.005-05:00</published><updated>2009-02-10T11:51:29.878-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='scala'/><title type='text'>Extending the properties.scala Example</title><content type='html'>&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;I was tinkering with the properties.scala example (&lt;a href="http://www.scala-lang.org/docu/examples/files/properties.html"&gt;http://www.scala-lang.org/docu/examples/files/properties.html&lt;/a&gt;) from the main Scala site. One thing that occurred to me was that the functionality to automatically fire PropertyChange events could be added such a way that implementers would only need to the to use a trait and specify member properties.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;I'd originally called this concept "BeanProperty", but to prevent confusion with the Scala annotation of the same name, it's named "BindableProperty". Such as class could form the basis of some kind of property binding arrangement. &lt;br /&gt;&lt;br/&gt;&lt;br /&gt;Here is a example of a class with BindableProperties:&lt;br /&gt;&lt;pre name="code" class="scala"&gt;&lt;br /&gt;class BindableUser extends hasBindableProperties {&lt;br /&gt;    val firstName = BindableProperty("firstName","")&lt;br /&gt;      .onGet { v =&gt; v.toUpperCase() }&lt;br /&gt;      .onSet { v =&gt; if (v == null) &lt;br /&gt;                        throw new IllegalArgumentException("firstName can not be set to null");&lt;br /&gt;                    }&lt;br /&gt;                        v&lt;br /&gt;                    }&lt;br /&gt;              }&lt;br /&gt;    val lastName = BindableProperty("lastName", "&lt;noname&gt;")&lt;br /&gt;    &lt;br /&gt;    val employeeNbr = BindableProperty[Long]("employeeNbr") &lt;br /&gt;    &lt;br /&gt;    var isMarried = BindableProperty[Option[Boolean]]("isMarried", None)&lt;br /&gt;    &lt;br /&gt;    var isMale = BindableProperty[Boolean]("isMale")&lt;br /&gt;         .onSet { v =&gt; updateSalutation(v, isMarried()); v }&lt;br /&gt;    &lt;br /&gt;    var salutation = BindableProperty[String]("saluation");&lt;br /&gt;    &lt;br /&gt;    // Some some reason, this needed to be after isMale declaration   &lt;br /&gt;    isMarried.onSet { v =&gt; updateSalutation(isMale(), v); v }&lt;br /&gt;&lt;br /&gt;    private def updateSalutation(male:Boolean, married:Option[Boolean]):Unit = {&lt;br /&gt;         Console.println("update salutation " + (male, married))&lt;br /&gt;         salutation := ((male, married) match {&lt;br /&gt;             case (true,_) =&gt; "Mr."&lt;br /&gt;             case (false,Some(true)) =&gt; "Mrs."&lt;br /&gt;             case (false,Some(false)) =&gt; "Miss."&lt;br /&gt;             case (false,None) =&gt; "Ms."&lt;br /&gt;             case _ =&gt; ""&lt;br /&gt;         })&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    override def toString() = salutation() + " " + firstName() + " " + lastName() + ":" + employeeNbr()&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;The hasBindableProperties trait provide methods for creation of BindableProperties and a map to store PropertyChangeListeners much like the PropertyChangeSupport class in Java. &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;The onGet and onSet methods are used to specify a block of code that can transform or validate data. Above, the onGet method method converts the stored property to uppercase upon retrieval. The isMale and isMarried properties have onSet handlers that try to infer the salutation based on gender and marital status (i.e. "Mr.", "Mrs.", "Miss.", or "Ms."). The onSet handler for firstName throws an Exception if value passed is null. &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;The second parameter of the BindableProperty method specifies an initial value. If an initial value is not specified, the type for the property can not be inferred and the type parameter must be specified like how it is done for the employeeNbr property in the code above.&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;There are multiple ways to set a property. This is done because tastes may vary on what is readable and some people may dislike anything resembling operator overloading. Examples of setting a property:&lt;br /&gt;&lt;pre name="code" class="scala"&gt;&lt;br /&gt;val zaphod = new BindableUser()&lt;br /&gt;// Different ways to set&lt;br /&gt;zaphod.firstName("Zafod")&lt;br /&gt;zaphod.lastName.set("Beeblebrox")&lt;br /&gt;zaphod.isMale := true&lt;br /&gt;zaphod.employeeNbr() = 0&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;i&gt;The ":=" is the result of a flashback to Pascal that I learned in college.&lt;/i&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;There are two ways to get a property:&lt;br /&gt;&lt;pre name="code" class="scala"&gt;&lt;br /&gt;Console.println("user first name: " + user.firstName())&lt;br /&gt;Console.println("user last name: " + user.lastName.get())&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Here's an example of a PropertyChangeListener that simply reports the change to the console:&lt;br /&gt;&lt;pre name="code" class="scala"&gt;&lt;br /&gt;class TestBindablePropertyChangeListener extends PropertyChangeListener {&lt;br /&gt;    override def propertyChange(evt: PropertyChangeEvent) = &lt;br /&gt;        Console.println(String.format("Property '%s' for object '%s' changed from '%s' to '%s'", List(&lt;br /&gt;                 evt.getPropertyName()&lt;br /&gt;                ,evt.getSource().toString()&lt;br /&gt;                ,evt.getOldValue()&lt;br /&gt;                ,evt.getNewValue()&lt;br /&gt;          ).toArray)) // Scala varargs are different from Java&lt;br /&gt;                     // Had to explicitly pass an array for the Java varargs&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;To add the listener to a given object::&lt;br /&gt;&lt;pre name="code" class="scala"&gt;&lt;br /&gt;zaphod.addPropertyChangeListener(new TestBindablePropertyChangeListener())&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now when a property changes for a user, it is detected and reported on the console:&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Example:&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;To see this in action, download the BindableProperties source &lt;a href="http://webpages.charter.net/daltontk/scala/src/BindableProperties.scala"&gt;here&lt;/a&gt; and demo source &lt;a href="http://webpages.charter.net/daltontk/scala/src/BindablePropertiesDemo.scala"&gt;here&lt;/a&gt;. &lt;br /&gt;Compile the BindableProperties.scala first and it will create classes in directory, ./tfd/scala/bindableproperties. Secondly, compile the BindablePropertiesDemo.scala and it will put classes in ./tfd/scala/bindableproperties/demo directory. The above BindableUser and TestBindablePropertyChangeListener are included in the demo source.  From the base directory, the scala interpreter can be invoked:&lt;br /&gt;&lt;pre class="command-prompt"&gt;&lt;br /&gt;C:\stuff\mycode\trunk\scala\src&gt;scala&lt;br /&gt;Welcome to Scala version 2.6.0-final.&lt;br /&gt;Type in expressions to have them evaluated.&lt;br /&gt;Type :help for more information.&lt;br /&gt;&lt;br /&gt;scala&gt;import tfd.scala.bindableproperties.demo._&lt;br /&gt;import tfd.scala.bindableproperties.demo._&lt;br /&gt; &lt;br /&gt;scala&gt;val zaphod = new BindableUser()&lt;br /&gt; &lt;br /&gt;scala&gt;zaphod.firstName("Zafod")&lt;br /&gt; &lt;br /&gt;scala&gt;zaphod.lastName.set("Beeblebrox")&lt;br /&gt; &lt;br /&gt;scala&gt;zaphod.isMale := true&lt;br /&gt;update salutation (true,None)&lt;br /&gt; &lt;br /&gt;scala&gt;zaphod.employeeNbr() = 0&lt;br /&gt;    &lt;br /&gt;scala&gt;Console.println(zaphod.toString)&lt;br /&gt;Mr. ZAFOD Beeblebrox:0&lt;br /&gt; &lt;br /&gt;scala&gt;zaphod.addPropertyChangeListener(new TestBindablePropertyChangeListener())&lt;br /&gt; &lt;br /&gt;scala&gt;zaphod.firstName := "Zaphod"&lt;br /&gt;Property 'firstName' for object 'Mr. ZAPHOD Beeblebrox:0' changed from 'Zafod' to 'Zaphod'&lt;br /&gt; &lt;br /&gt;scala&gt;zaphod.salutation := "Part-time Galactic President"&lt;br /&gt;Property 'saluation' for object 'Part-time Galactic President ZAPHOD Beeblebrox:0' changed from 'Mr.' to 'Part-time Galactic President'&lt;br /&gt; &lt;br /&gt;scala&gt;Console.println(zaphod.toString)&lt;br /&gt;Part-time Galactic President ZAPHOD Beeblebrox:0&lt;br /&gt; &lt;br /&gt;scala&gt;val trillian = new BindableUser()&lt;br /&gt; &lt;br /&gt;scala&gt;trillian.firstName := "Trisha" &lt;br /&gt;    &lt;br /&gt;scala&gt;trillian.lastName := "McMillan" &lt;br /&gt;    &lt;br /&gt;scala&gt;trillian.isMale := false&lt;br /&gt;update salutation (false,None)&lt;br /&gt; &lt;br /&gt;scala&gt;trillian.employeeNbr := 22079460347L&lt;br /&gt; &lt;br /&gt;scala&gt;Console.println(trillian.toString)&lt;br /&gt;Ms. TRISHA McMillan:22079460347&lt;br /&gt; &lt;br /&gt;scala&gt;trillian.addPropertyChangeListener(new TestBindablePropertyChangeListener())&lt;br /&gt;   &lt;br /&gt;scala&gt;trillian.firstName := "Trillian"&lt;br /&gt;Property 'firstName' for object 'Ms. TRILLIAN McMillan:22079460347' changed from 'Trisha' to 'Trillian'&lt;br /&gt;    &lt;br /&gt;scala&gt;trillian.lastName := "" &lt;br /&gt;Property 'lastName' for object 'Ms. TRILLIAN :22079460347' changed from 'McMillan' to ''&lt;br /&gt; &lt;br /&gt;scala&gt;trillian.employeeNbr := 42&lt;br /&gt;Property 'employeeNbr' for object 'Ms. TRILLIAN :42' changed from '22079460347' to '42'&lt;br /&gt; &lt;br /&gt;scala&gt;trillian.isMarried := Some(false);&lt;br /&gt;Property 'isMarried' for object 'Miss. TRILLIAN :42' changed from 'None' to 'Some(false)'&lt;br /&gt; &lt;br /&gt;scala&gt;Console.println(trillian.toString)&lt;br /&gt;Miss. TRILLIAN :42&lt;br /&gt; &lt;br /&gt;scala&gt;trillian.lastName := "Dent"&lt;br /&gt;Property 'lastName' for object 'Miss. TRILLIAN Dent:42' changed from '' to 'Dent'&lt;br /&gt; &lt;br /&gt;scala&gt;trillian.isMarried := Some(true)&lt;br /&gt;update salutation (false,Some(true))&lt;br /&gt;Property 'salutation' for object 'Mrs. TRILLIAN Dent:42' changed from 'Miss.' to 'Mrs.'&lt;br /&gt;Property 'isMarried' for object 'Mrs. TRILLIAN Dent:42' changed from 'Some(false)' to 'Some(true)'&lt;br /&gt; &lt;br /&gt;scala&gt;Console.println(trillian.toString)&lt;br /&gt;Mrs. TRILLIAN Dent:42&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;I've also included a demo application in the BindablePropertiesDemo.scala file, BindablePropertiesDemo that can invoked via "scala tfd.scala.bindableproperties.demo.BindablePropertiesDemo". This demo runs the above commands and has a try/catch block where a firstName property is set to null.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Scala's flexible syntax provides a good basis for creating new idioms that can make code more expressive and DSL-like without losing static typing and be a compiled language.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7017894832730513527-3199530880664919749?l=compulsiontocode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://compulsiontocode.blogspot.com/feeds/3199530880664919749/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7017894832730513527&amp;postID=3199530880664919749' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7017894832730513527/posts/default/3199530880664919749'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7017894832730513527/posts/default/3199530880664919749'/><link rel='alternate' type='text/html' href='http://compulsiontocode.blogspot.com/2007/10/extending-propertiesscala-example.html' title='Extending the properties.scala Example'/><author><name>tdalton</name><uri>http://www.blogger.com/profile/13151512717871227421</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://4.bp.blogspot.com/-c8KSZCmTdpI/TbmtJ04pIUI/AAAAAAAAAEM/AEmlqBQ4ecM/s220/tim.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7017894832730513527.post-7391301352191954476</id><published>2007-05-25T21:20:00.013-05:00</published><updated>2009-02-10T12:37:37.416-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='functional programming'/><category scheme='http://www.blogger.com/atom/ns#' term='erlang'/><category scheme='http://www.blogger.com/atom/ns#' term='scala'/><title type='text'>Bowling with Erlang and Scala</title><content type='html'>&lt;span style="font-family:arial"&gt;    I read an blog entry  (&lt;/span&gt;&lt;a style="font-family: arial;" class="moz-txt-link-freetext" href="http://www.randomhacks.net/articles/2007/04/28/bowling-in-haskell"&gt;http://www.randomhacks.net/articles/2007/04/28/bowling-in-haskell&lt;/a&gt;&lt;span style="font-family:arial;"&gt;)  that was picked up by dzone.com demonstrating how to keep score of a  bowling game using Haskell. I modified the Haskell version to use the  Maybe data type to allow scoring of incomplete games and then ported  the code to Erlang and Scala to get a feel for the language  feature. If anyone is interested, here is the Erlang version I came up  with:&lt;/span&gt;&lt;br /&gt;&lt;pre name="code" class="erlang"&gt;-module(bowling).&lt;br /&gt;-export([tallyGame/1]).&lt;br /&gt;&lt;br /&gt;scoreToInt(X) -&gt;&lt;br /&gt;       case X of&lt;br /&gt;               none -&gt; 0;&lt;br /&gt;               _ -&gt; X&lt;br /&gt;       end.&lt;br /&gt;     &lt;br /&gt;take(N,L) -&gt;&lt;br /&gt;       if (N &gt; 0) -&gt;  &lt;br /&gt;           case L of&lt;br /&gt;               [X|Rest] -&gt; [X] ++ take(N-1, Rest);&lt;br /&gt;               [] -&gt; []&lt;br /&gt;           end;&lt;br /&gt;           true -&gt; []&lt;br /&gt;       end.&lt;br /&gt;     &lt;br /&gt;reduce(F,YS) -&gt;&lt;br /&gt;       if&lt;br /&gt;           (YS == []) -&gt; [];&lt;br /&gt;           true -&gt; {X, YS2} = F(YS),&lt;br /&gt;                   [X] ++ reduce(F,YS2)&lt;br /&gt;       end.&lt;br /&gt;&lt;br /&gt;invalid_pin_count() -&gt; throw("invalid_pin_count").&lt;br /&gt;&lt;br /&gt;scoreFrame(Balls) -&gt;&lt;br /&gt; case Balls of&lt;br /&gt;       [X|_] when X &lt;&gt; 10 -&gt; invalid_pin_count();&lt;br /&gt;       [_,X|_] when X &lt;&gt; 10 -&gt; invalid_pin_count();&lt;br /&gt;       [X1,X2|_] when X1 &lt;&gt; 10) -&gt; invalid_pin_count();&lt;br /&gt;       [X1,Y1,Y2|Rest] when (X1 == 10) -&gt; {(X1+Y1+Y2), [Y1,Y2] ++ Rest};&lt;br /&gt;       [X1,X2,Y1|Rest] when ((X1 + X2) == 10) -&gt; {(X1+X2+Y1), [Y1] ++ Rest};&lt;br /&gt;       [X1,X2|Rest] -&gt; {(X1 + X2), Rest};&lt;br /&gt;       _ -&gt; {none, []}&lt;br /&gt; end.&lt;br /&gt;     &lt;br /&gt;scoreGame(Balls) -&gt; take(10,reduce(fun scoreFrame/1, Balls)).&lt;br /&gt;&lt;br /&gt;tallyScores(Accum, L) -&gt;&lt;br /&gt;       case L of&lt;br /&gt;           [] -&gt; [];&lt;br /&gt;           [Head|Tail]  -&gt; Total = (Accum + scoreToInt(Head)),&lt;br /&gt;                           [Total] ++ tallyScores(Total, Tail)&lt;br /&gt;       end.&lt;br /&gt;     &lt;br /&gt;tallyGame(L) -&gt; tallyScores(0, scoreGame(L)).&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p style="font-family:arial;"&gt;&lt;br /&gt;Run this in "erl" via "bowling:tallyGame([&amp;lt;rolls&amp;gt;])". Example:&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;pre class="command-prompt"&gt;bowling:tallyGame([10,10,10,10,10,10,10,10,10,10,10,10]).&lt;br /&gt;[30,60,90,120,150,180,210,240,270,300]&lt;/pre&gt;&lt;br /&gt;&lt;p style="font-family:arial;"&gt;With some feed back from members of the Scala lounge mailing list, this is the Scala version:&lt;/p&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;object FunctionalBowling {&lt;br /&gt; type Score=Option[int]&lt;br /&gt; type Balls=List[int]&lt;br /&gt;&lt;br /&gt; def reduce[A,B](f:(A =&gt; (B, A)), ys:A): List[B] =&lt;br /&gt;   if (ys == Nil) Nil&lt;br /&gt;   else {val prime = f(ys); prime._1 :: reduce(f, prime._2)}&lt;br /&gt;&lt;br /&gt; def scoreGame(balls:Balls): List[Score] = reduce(&amp;scoreFrame,balls).take(10)&lt;br /&gt; &lt;br /&gt; implicit def scoreToInt(score:Score): int = score getOrElse 0&lt;br /&gt; &lt;br /&gt; implicit def intToScore(in: int): Score = Some(in)&lt;br /&gt;&lt;br /&gt; def invalidPinCount() = throw(new Exception("Invalid Pin Count"))&lt;br /&gt; &lt;br /&gt; def scoreFrame(balls: Balls): (Score, Balls) = balls match {&lt;br /&gt;  case (x :: _) if (x &lt;&gt; 10) =&gt; invalidPinCount() // Invalid first roll&lt;br /&gt;  case (_ :: x :: _) if (x &lt;&gt; 10) =&gt; invalidPinCount() // Invalid second roll&lt;br /&gt;  case (x1 :: x2 :: _) if (x1 &lt;&gt; 10) =&gt; invalidPinCount()&lt;br /&gt;   // Total pin count for spare frame can't be &gt; 10&lt;br /&gt;  case (x1 :: x2 :: x3 :: rest) if x1 == 10 =&gt; (x1 + x2 + x3, x2 :: x3 :: rest)&lt;br /&gt;  case (x1 :: x2 :: x3 :: rest) if x1 + x2 == 10 =&gt; (x1 + x2 + x3, x3 :: rest)&lt;br /&gt;  case (x1 :: x2 :: x3 :: rest) =&gt; (x1 + x2, x3 :: rest)&lt;br /&gt;  case (x1 :: x2 :: Nil) if x1 + x2 &lt; 10 =""&gt; (x1 + x2, Nil)&lt;br /&gt;  case _ =&gt; (None, Nil)&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; def tallyScores(accum:int, x:List[Score]):List[int] = x match {&lt;br /&gt;  case Nil =&gt; Nil&lt;br /&gt;  case x :: rest =&gt; val total = accum + x&lt;br /&gt;        total :: tallyScores(total, rest)&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; def main(args:Array[String]):Unit = {&lt;br /&gt;  val roll_list = args.toList.map(Integer.parseInt)&lt;br /&gt;  System.out.println("Scores: " + tallyScores(0,scoreGame(roll_list)));&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p style="font-family:arial;"&gt;Invoke the Scala version via "scala FunctionalBowling &amp;lt;rolls separated by space&amp;gt;". Example:&lt;/p&gt;&lt;br /&gt;&lt;pre class="command-prompt"&gt;scala FunctionalBowling 10 9 1 10 9 1 10 9  1 10 9 1 10 9 1 10 9 1&lt;br /&gt;Scores: List(20, 40, 60, 80, 100, 120, 140, 160, 180, 200)&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7017894832730513527-7391301352191954476?l=compulsiontocode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://compulsiontocode.blogspot.com/feeds/7391301352191954476/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7017894832730513527&amp;postID=7391301352191954476' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7017894832730513527/posts/default/7391301352191954476'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7017894832730513527/posts/default/7391301352191954476'/><link rel='alternate' type='text/html' href='http://compulsiontocode.blogspot.com/2007/05/bowling-with-erlang-and-scala.html' title='Bowling with Erlang and Scala'/><author><name>tdalton</name><uri>http://www.blogger.com/profile/13151512717871227421</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://4.bp.blogspot.com/-c8KSZCmTdpI/TbmtJ04pIUI/AAAAAAAAAEM/AEmlqBQ4ecM/s220/tim.jpg'/></author><thr:total>1</thr:total></entry></feed>
